本文先回顧了以往流行的多渠道打包方式,隨后引入的mcxiaoke的packer-ng-plugin項目,介紹該項目在實際應用(配合友盟統計)中如何解決更方便的Android多渠道打包問題
- 多渠道打包方案解析
- 實際應用集成
多渠道打包方案解析
android應用市場多種多樣,應用寶、小米市場、豌豆莢...為了監督每個市場我們的應用下載和推廣情況,對發布在每個市場上的apk打上烙印是必須的一步,這就是多渠道apk的問題,“渠道”就是給apk打上的烙印。
同時友盟統計可以幫我們統計渠道數據(Channel),方便產品經理對數據分析后做下一步產品決策。
目前多渠道打包方式大致有:
- gradle自帶的productFlavor方式,見我之前的博客
- apktool重簽名重打包
- 在apk文件中的META-INF文件夾中寫入以渠道號命名的空文件方式(美團)
第三種是比較快的方式,據說900多個渠道不到一分鍾就能打完,參考。但是缺點也是有的,你需要維護一個python腳本,為每一種渠道寫入一個以渠道名命名的空文件。
本文將介紹的packer-ng-plugin的思路其實是有點類似的,由於apk就是一個zip文件,zip文件尾部有一個部分可以作為zip文件的注釋,正確修改這一部分不會對ZIP文件造成破壞,利用這個字段,我們可以添加一些自定義的數據,PackerNg項目就是在這里添加和讀取渠道信息。同時提供了讀取渠道信息的接口。
實際應用集成
修改項目gradle,加入
buildscript {
......
dependencies{
// add packer-ng
classpath 'com.mcxiaoke.gradle:packer-ng:1.0.5'
}
}
修改moudle級別gradle,加入
apply plugin: 'packer'
dependencies {
// add packer-helper
compile 'com.mcxiaoke.gradle:packer-helper:1.0.5'
}
注意:packer-ng 和 packer-helper 的版本號需要保持一致
在你的項目根目錄中加入渠道列表文件,比如文件名是market.txt,內容是
YingYongBao
XiaoMi
WanDouJia
Baidu
Qihoo
GooglePlay
...
就是每一行即一個渠道號
再在你的項目根目錄加入一個bat腳本(windows),比如叫做build.bat
,內容寫上(即一個命令)
gradle -Pmarket=markets.txt clean apkRelease
大功告成,以后每次打渠道包,只要進入你的根目錄,雙擊這bat腳本,packer-ng-plugin就開始自動幫你根據market.txt構建每一個渠道包;或者直接在android studio的Terminal
中執行build.bat亦可。
觀察控制台的輸出,packer-ng最終是為每一個渠道包的打制形成了一個個的gradle task:
...
:app:apkRelease processed apk for XiaoMi (4)
:app:apkRelease processed apk for WanDouJia (5)
:app:apkRelease processed apk for Baidu (6)
:app:apkRelease processed apk for Qihoo (7)
:app:apkRelease processed apk for GooglePlay (8)
:app:apkRelease all 8 apks saved to D:\workspace\shine\build\archives
:app:apkRelease PackerNg: Market Packaging Successful!
BUILD SUCCESSFUL
Total time: 1 mins 23.269 secs
根據這個輸出,他一共生成了8個渠道包,所有的apk輸出在了項目根目錄的build/archives文件夾中
packer-ng-plugin也提供了一些自定義配置,比如輸入的apk的命名方式,具體參考插件配置說明,同時提供了java和python的命令行腳本,供集成到持續集成環境中,具體參考命令行打包腳本。
最后需要提的一點就是如何讓友盟統計知道目前的apk是哪個渠道。首先你需要刪除之前的productFlavor或者manifest的占位符的方式的代碼,刪除AndroidManifest中友盟的渠道Channel的META-Data的配置。
然后在app入口(Application)的onCreate中加入下列代碼:
final String market = PackerNg.getMarket(this,"defaul_channel);
AnalyticsConfig.setChannel(market); //AnalyticsConfig是友盟的代碼方式設置渠道類