99热99这里只有精品6国产,亚洲中文字幕在线天天更新,在线观看亚洲精品国产福利片 ,久久久久综合网

歡迎加入QQ討論群258996829
麥子學(xué)院 頭像
蘋果6袋
6
麥子學(xué)院

Android學(xué)習(xí)之多渠道打包

發(fā)布時間:2016-12-23 21:32  回復(fù):0  查看:2491   最后回復(fù):2016-12-23 21:32  

Android多渠道打包,由于傳統(tǒng)打包速度比較慢,本篇主要介紹一種新的打包方案,速度可提升百倍,希望對大家學(xué)習(xí)android有所幫助。

  背景:

  android studio支持多渠道打包方式,是通過gradle 的變種方式來進(jìn)行的:

  //build.gradle

  manifestPlaceholders = [FFCHANNEL_ID_VALUE: channel]//AndroidManifest.xml

  <meta-data

  android:name="FFCHANNEL_ID"

  android:value="${FFCHANNEL_ID_VALUE}" />

  這種方式是google推薦的方式,但這種方式對于幾個渠道包是可以支持的, 當(dāng)我們需要打上百個渠道包時,這種方案耗時很長,是項目開發(fā)不能忍受的。而目前我們項目需要進(jìn)行加固后保障安全,發(fā)布市場的app需要進(jìn)行加固。當(dāng)發(fā)布app時候,我們需要在集成打包機(jī)器上進(jìn)行打包,目前項目為11個渠道包,耗時一個多小時,時間已經(jīng)屬于不可容忍的,況且還未進(jìn)行加固,目前加固11個包,需要半小時,廣州銀行80個渠道包,2G多,全部加固完成需要半天時間。這種情況下,我們需要考慮采用新的方案來解決打渠道包耗時費力的問題。

  新方案

  新方案是通過zip包注釋的方案進(jìn)行多渠道打包的,由開發(fā)提供一個生成包即可,使用該包進(jìn)行加固,作為母包。通過開發(fā)提供的腳本,批量生成多渠道包,基本屬于拷貝復(fù)制的節(jié)奏,由于目前apk為27M多,偏大,所以基本一個渠道包為1s,生成80個渠道包耗時80秒,親測。

  可以考慮以后由開發(fā)只提供母包,由運營發(fā)布市場的同事根據(jù)運營需求來自己執(zhí)行腳本發(fā)布各市場渠道包,簡單,方便,快捷,不受限制。

  原理

  使用APK注釋字段保存渠道信息和MAGIC字節(jié),通過腳本將取渠道信息寫入apk注釋字段中。 android使用的apk包的壓縮方式是zip,與zip有相同的文件結(jié)構(gòu),在zip的Central directory file header中包含一個File comment區(qū)域,可以存放一些數(shù)據(jù)。File comment是zip文件如果可以正確的修改這個部分,就可以在不破壞壓縮包、不用重新打包的的前提下快速的給apk文件寫入自己想要的數(shù)據(jù)。 comment是在Central directory file header末尾儲存的,可以將數(shù)據(jù)直接寫在這里,下表是header末尾的結(jié)構(gòu)

  image

  由于數(shù)據(jù)是不確定的,我們無法知道comment的長度,從表中可以看到zip定義comment的長度的位置在comment之前,所以無法從zip中直接獲取comment的長度。這里我們需要自定義comment的長度,在自定義comment內(nèi)容的后面添加一個區(qū)域儲存comment的長度,結(jié)構(gòu)如下圖。 image

  目前也已經(jīng)和愛加密加固的同事進(jìn)行了確認(rèn),愛加密的加固方式不會占用該zip注釋,不會和該多渠道包方案沖突,也已經(jīng)在項目中測試驗證通過。

  實現(xiàn)

  寫入 :寫入可以使用java,也可以使用python,目前考慮到可以對外提供,使用python。

  讀取 :讀取需要在Android代碼中用java實現(xiàn)。

  //定義魔法串作為結(jié)束符

  MAGIC = '!ZXK!'

  //寫入

  def write_market(path, market, output):

  '''

  write market info to apk file

  write_market(apk-file-path, market-name, output-path)

  '''

  path = os.path.abspath(path)

  output = unicode(output)

  if not os.path.exists(path):

  print('apk file',path,'not exists')

  return

  if read_market(path):

  print('apk file',path,'had market already')

  return

  if not output:

  output = os.path.dirname(path)

  if not os.path.exists(output):

  os.makedirs(output)

  name,ext = os.path.splitext(os.path.basename(path))

  # name,package,vname,vcode

  app = parse_apk(path)

  apk_name = '%s-%s-%s-%s%s' % (app['app_package'],

  market.decode('utf8'), app['version_name'], app['version_code'], ext)

  # apk_name = name + "-" + market + ext

  apk_file = os.path.join(output,apk_name)

  shutil.copy(path,apk_file)

  # print('apk file:',apk_file)

  index = os.stat(apk_file).st_size

  index -= ZIP_SHORT

  with open(apk_file,"r+b") as f:

  f.seek(index)

  # write comment length

  f.write(struct.pack('<H',len(market) + ZIP_SHORT + len(MAGIC)))

  # write comment content

  # content = [market_string + market_length + magic_string]

  f.write(market)

  f.write(struct.pack('<H',len(market)))

  f.write(MAGIC)

  return apk_file

  //讀取

  public static String readZipComment(File file) throws IOException {

  RandomAccessFile raf = null;

  try {

  raf = new RandomAccessFile(file, "r");

  long index = raf.length();

  byte[] buffer = new byte[MAGIC.length];

  index -= MAGIC.length;

  // read magic bytes

  raf.seek(index);

  raf.readFully(buffer);

  // if magic bytes matched

  if (isMagicMatched(buffer)) {

  index -= SHORT_LENGTH;

  raf.seek(index);

  // read content length field

  int length = readShort(raf);

  if (length > 0) {

  index -= length;

  raf.seek(index);

  // read content bytes

  byte[] bytesComment = new byte[length];

  raf.readFully(bytesComment);

  return new String(bytesComment, UTF_8);

  } else {

  throw new IOException("zip comment content not found");

  }

  } else {

  throw new IOException("zip comment magic bytes not found");

  }

  } finally {

  if (raf != null) {

  raf.close();

  }

  }

  }

  使用

  目前提供寫入腳本到項目中,讀取渠道號代碼已經(jīng)集成到j(luò)ava代碼中。

  使用如下:

  格式是:python ngpacker.py [file] [market] [output]

  eg:

  python ngpacker.py app-release_signed.apk markets.txt apks

  渠道配置文件如下:

  1001#bdsj

  1002#azsc

  1003#91zs

  1004#wdj

  1005#txyyb

  1006#xmyy

  1007#360sj

  1008#hwyy

  1009#anzhisc

  1010#ppzs

1011#lsd

 

來源:簡書

您還未登錄,請先登錄

熱門帖子

最新帖子

?