一、多渠道打包概述
由于國內(nèi)存在著有眾多的應(yīng)用市場,在不同的應(yīng)用市場可能有不同的統(tǒng)計需求,為此Android開發(fā)人員需要為每個應(yīng)用市場發(fā)布一個安裝包,這里就引出了Android的多渠道打包。在安裝包中添加不同的標(biāo)識,以此區(qū)分各個渠道,方便統(tǒng)計app在市場的各種效果。
因此,每當(dāng)發(fā)新版本時,市場會提供一個渠道列表,Android RD會根據(jù)這些渠道相應(yīng)地生成等量的渠道包。隨著渠道越來越多,為了提高渠道打包的效率,因此催生了對多渠道打包的方式的研究。
本篇文章主要總結(jié)一下多渠道打包的相關(guān)知識以及美團的新舊兩種多渠道打包方案。
二、渠道包生成
Maven方式: 每打一個包都要執(zhí)行一遍構(gòu)建過程,效率太低;
apktool: 雖然不需要重新構(gòu)建,但對每個包都要重新簽名;
隨著渠道包的增多,每次打包動輒幾個小時,以上兩種方式的效率太低。
關(guān)于這兩種打包方式詳見:美團Android自動化之旅—生成渠道包
META-INF添加空文件
這是美團為了提高打包效率而提出的一種新的多渠道打包方式,不需要重新構(gòu)建,也不需要重新簽名。
介紹
通過解壓apk,根目錄下會有一個META-INF目錄,在該目錄下添加空文件,可以不用重新簽名應(yīng)用。因此,通過為不同渠道的應(yīng)用添加不同的空文件,可以唯一標(biāo)識一個渠道。

具體步驟
利用python代碼用來給apk添加空的渠道文件
在Java代碼中讀取空渠道文件名,識別渠道
具體代碼在上面美團生成多渠道包的鏈接中有詳細(xì)給出。
Walle
Walle(瓦力):Android Signature V2 Scheme簽名下的新一代渠道包打包神器
瓦力通過在Apk中的APK Signature Block區(qū)塊添加自定義的渠道信息來生成渠道包,從而提高了渠道包生成效率,可以作為單機工具來使用,也可以部署在HTTP服務(wù)器上來實時處理渠道包Apk的升級網(wǎng)絡(luò)請求。
原理介紹
Android 7.0(Nougat)引入一項新的應(yīng)用簽名方案APK Signature Scheme v2,它是一個對全文件進行簽名的方案,能提供更快的應(yīng)用安裝時間、對未授權(quán)APK文件的更改提供更多保護,在默認(rèn)情況下,Android Gradle 2.2.0插件會使用APK Signature Scheme v2和傳統(tǒng)簽名方案來簽署你的應(yīng)用。

新應(yīng)用簽名方案的簽名信息會被保存在區(qū)塊(APK Signing Block)中, 而區(qū)塊(Contents of ZIP entries)、區(qū)塊(ZIP Central Directory)、區(qū)塊(ZIP End of Central Directory)是受保護的,在簽名后任何對其的修改都逃不過新的應(yīng)用簽名方案的檢查。
之前的渠道包生成方案是通過在META-INF目錄下添加空文件的打包方式在Signature Scheme v2的簽名方式下不可使用了,因為META-INF已經(jīng)被列入了保護區(qū)了,向META-INF添加空文件的方案會對上面受保護的三個區(qū)塊都有影響。
通過上面描述發(fā)現(xiàn)區(qū)塊(APK Signing Block)是不受簽名校驗規(guī)則保護的,因此Walle正是通過在該區(qū)塊做文章,寫入渠道信息。
具體步驟
對新的應(yīng)用簽名方案生成的APK包中區(qū)塊(
APK Signing Block)寫入渠道信息,并保存在APK中APK在安裝過程中進行的簽名校驗,是忽略我們添加的渠道信息的,這樣就能正常安裝了
在App運行階段,可以通過ZIP的
End of central directory、Central directory等結(jié)構(gòu)中的信息找到我們自己添加的渠道信息,從而實現(xiàn)獲取渠道信息的功能
最終,每打一個渠道包只需復(fù)制一個APK,然后在APK中添加一個渠道信息即可,這種打包方式速度非常快。
使用方式
Gradle插件方式,方便快速集成
命令行方式,最大化滿足各種自定義需求
關(guān)于Walle兩種使用方式的詳細(xì)步驟,參見:Android使用walle多渠道打包
三、渠道包適配
上述多渠道打包方式解決了打包慢的問題,但是隨著渠道越來越多,不同渠道對應(yīng)用的要求也不盡相同。
例如,有的渠道要求app的應(yīng)用名不同,有些渠道要求應(yīng)用不能使用第三方統(tǒng)計工具,有些渠道要求應(yīng)用不能自動更新。
之前的做法是為每個需要適配的渠道創(chuàng)建一個Git分支,發(fā)版時再切換到相應(yīng)的分支,并合并主分支的代碼。適配的渠道比較少的話這種方式還可以接受,隨著適配渠道的增多,這種方式就變得不可取。
幸好Gradle flavor,可以滿足渠道適配的需求,只需要通過配置Gradle即可以實現(xiàn)多渠道的適配工作,省心省力。
Flavor
先來看build.gradle文件中的一段代碼:
android {
....
productFlavors {
flavor1 {
minSdkVersion 14
}
}
}
上例定義了一個flavor:flavor1,并指定了應(yīng)用的minSdkVersion為14(當(dāng)然還可以配置更多的屬性,具體可參考相關(guān)文檔)。與此同時,Gradle還會為該flavor關(guān)聯(lián)對應(yīng)的sourceSet,默認(rèn)位置為src/<flavorName>目錄,對應(yīng)到本例就是src/flavor1。
接下來,要做的就是根據(jù)具體的需求在build.gradle文件中配置flavor,并添加必要的代碼和資源文件。以flavor1為例,運行gradle assembleFlavor1命令既可生成所需的適配包。通過適配不同的flavor即可以生成不同的渠道包,但該方式生成渠道包的方式需要重復(fù)編譯構(gòu)建。
具體示例
使用不同的包名
productFlavors {
qq {
applicationId "com.hello.group.qq"
}
}
面的代碼添加了一個名為qq的flavor,并指定了應(yīng)用的包名為com.hello.group.qq,運行gradle assembleqq命令即可生成qq適配包。
使用不同的應(yīng)用名
Gradle在構(gòu)建應(yīng)用時,會優(yōu)先使用flavor所屬sourceSet中的同名資源。所以,解決思路就是在flavor的sourceSet中添加同名的字符串資源,以覆蓋默認(rèn)的資源。
首先,在build.gradle配置文件中添加如下flavor:
android {
productFlavors {
wandoujia {
}
}
}
上面的配置會默認(rèn)src/wandoujia目錄為wandoujia flavor的sourceSet。
接下來,在src目錄內(nèi)創(chuàng)建wandoujia目錄,并添加如下應(yīng)用名字符串資源(src/wandoujia/res/values/appname.xml):
<resources>
<string name="app_name">wandoujia_app</string>
</resources>
默認(rèn)的應(yīng)用名字符串資源如下(src/main/res/values/strings.xml):
<resources>
<string name="app_name">origin_app</string>
</resources>
最后,運行gradle assembleWandoujia命令即可生成應(yīng)用名為wandoujia_app的應(yīng)用了。
wandoujia包下不使用strings.xml 名是因為會出現(xiàn)文件重復(fù),默認(rèn)的main 文件夾里存在的文件在其他適配目錄中不允許出現(xiàn)相同文件名的文件。
更多flavor適配示例,參見:美團Android自動化之旅—適配渠道包
以上就是最近了解關(guān)于多渠道打包的相關(guān)知識的總結(jié)。
想要實現(xiàn)更多自定義適配多渠道包的需求,還要更多的了解Gradle相關(guān)知識。