提綱
渠道打包方案:v1下的渠道包方案迭代,v2渠道包,常見工具庫
原理深入:部分源碼
前言
要進行渠道打包,重點是設置渠道標識,而設置渠道標識,涉及apk打包和簽名,可以先閱讀《安卓簽名機制淺析》,了解相關知識再閱讀本文。
本文主要一個個說明渠道包打包的不同做法優劣和迭代,如果想要直接獲得比較好的渠道打包方式,可以直接看文章后半部分
V1簽名機制下打渠道包
由V1簽名和校驗機制可知,修改APK中的任何文件都會導致安裝失敗!那怎么添加渠道信息呢?
方案1:Android Gradle Plugin
原理:Gradle Plugin本身提供了多渠道的打包策略,Gradle編譯生成多渠道包時,會用不同的渠道信息替換AndroidManifest.xml中的占位符。
1.在AndroidManifest.xml中添加渠道信息占位符:
2.通過Gradle Plugin提供的productFlavors標簽,添加渠道信息
簽名包流程:靜態資源整理->編譯源碼,處理得到dex文件->合成APK->簽名,對齊
缺點:每生成一個渠道包,都要重新執行一遍構建流程,效率太低,只適用于渠道較少的場景
渠道包耗時 = 渠道數量 * (編譯源碼+添加渠道+簽名)
Q:能否避免解決多次編譯?
方案2:找個文件添加上信息(res/raw。assets/) ,要用再讀出來
原理:APK是自簽名:沒有第三方權威機構認證,用戶可以自行生成keystore,Android簽名方案無法保證APK不被二次簽名。我們可以重新打包app,再設置信息后簽名。
了解apk編譯的話,可以知道以下目錄不會被編譯二進制!res/raw? 和 assets/
所以我們可以從這方面下手,設置了信息之后,重簽名,app內再讀出來。有兩種做法(apktool和winrar類壓縮工具)
優點:避免了多次編譯,渠道包時長 = 編譯源碼+ 渠道數量 * (添加渠道 + 簽名)
缺點:1.項目逐漸膨脹 解壓-合成-重簽依然耗時
? ? ? ? ? ?2.簽名不便于管理,易泄露,大項目簽名保密
? ? ? ? ? ?3.不穩定,可能升級了 Gradle Plugin 的版本之后,會導致解包失敗
Q:能否避免解決多次簽名?
Ps:高效的多渠道打包的幾個關鍵:不能破壞簽名,不能重新打包,讀取信息必須高效
渠道包時長 = 編譯源碼+簽名+ 渠道數量 * 添加渠道
不破壞簽名就限制了不能解包以及重新簽名,勢必對效率有所提高。
高效方案一:到/META-INF 目錄下,寫入一個空文件,以文件名來標識渠道號(來自美團)
原理:了解V1簽名,發現V1簽名只會校驗元文件(/META-INF 目錄)以外的數據,所以可以從這個漏洞下手,在/META-INF 目錄下寫入空文件,文件名為渠道名,就可以高效達到渠道包目的
步驟:
1.Java Zip API解析APKZipFile api apk;
2.添加渠道信息META-INF添加空文件,如META-INF/xiaomi.channel
3.獲取渠道信息,遍歷META-INF/目錄,匹配xx.channel獲取渠道信息
使用這樣的方案,并不會破壞 v1 簽名,所以效率會很高。
高效方案二:在注釋區加渠道信息(騰訊的VasDolly)
原理:apk文件本質為zip包,檢驗只校驗數據區,通過修改 Apk 文件的 EOCD 部分,增加渠道的信息
V2簽名機制下打渠道包
Q:上述方式都改了apk文件,對V2不管用,需要尋求快速的V2下渠道包方案
A:在APK簽名塊中添加一個ID-Value,存儲渠道信息
原理:V2簽名區塊存在盲區:未知id-value不校驗(當前線上推廣的框架都是這個做法,騰訊的VasDolly,美團的Walle都是)
Android系統只會關注ID為0x7109871a的V2簽名塊,并且忽略其他的ID-Value,同時V2簽名只會保護APK本身,不包含簽名塊
方案步驟:
1.找到APK的EOCD塊
2.找到APK簽名塊
3.獲取已有的ID-Value Pair
4.添加包含渠道信息的ID-Value
5.基于所有的ID-Value生成新的簽名塊
6.修改EOCD的中央目錄的偏移量(修改EOCD的中央目錄偏移量,不會導致數據摘要校驗失敗)
7.用新的簽名塊替代舊的簽名塊,生成帶有渠道信息的APK
實際上,除了渠道信息,我們可以在APK簽名塊中添加任何輔助信息。
V3機制下的渠道打包,和V2一樣就可以
常見的渠道打包工具和對比
?VasDolly使用簡介
????? 命令行執行jar包(支持多線程)
????? java –jar VasDolly.jar
????? 編譯、添加渠道一條龍
????? gradlew channelAppDebug
????? 基于已編譯APK添加渠道
????? gradlew rebuildChannel
相關框架連接
【美團】Walle:https://github.com/Meituan-Dianping/walle
【騰訊電競】VasDolly:https://github.com/Tencent/VasDolly
【某大神】packer-ng-plugin:https://github.com/mcxiaoke/packer-ng-plugin
原理深入——源碼篇
展示關鍵代碼,相關講解在注釋中
?寫入渠道(V1SchemeUtil)
?讀取渠道(V1SchemeUtil)
?V2獲取渠道信息(V2SchemeUtil)
?V2添加渠道信息(VasDolly ——ChannelWriter)
?V2添加渠道信息(VasDolly —— IdValueWriter )
?V2獲取渠道信息(VasDolly ——IdValueReader)
?參考鏈接:
?Android多渠道打包實踐(VasDolly&AndResGuard) http://www.lxweimin.com/p/38ad00f73e94