Android多渠道打包最佳實踐中介紹了幾種快速進行Android渠道包構(gòu)建的方式,嫌棄多渠道速度慢的同學可以先去看一下,一定會有所收獲。
<br /> 有時多渠道打包時不僅僅需要進行渠道號的設(shè)置,還需要對不同版本進行資源的替換或者在代碼中對于某些渠道的用戶進行一些特殊設(shè)置(運營的同學也不容易)。這時僅僅依靠前邊的方法就不靈了,除非你想手動打包。
<br /> 這里有兩種思路:
- 利用gradle Product flavors 進行打包, 使用 gradle打包在 速度上沒有優(yōu)勢,每個flavors都要進行編譯,混淆等操作(這里想寫篇文章具體介紹下)。
- 使用apktool 對資源進行替換,這種方式會需要重新打包資源,進行簽名,速度要快一些,但是在某些機器上有莫名其妙的crash,你懂的……
所以基本也就剩下了第一種方式。
流程分析
這里我們明確自己的目標:動態(tài)資源替換多渠道打包,同時過程要快速、自動化。基本流程如下:
- 首發(fā)渠道號配置
一般來說不是每個渠道都需要進行首發(fā)的,正常每個版本會有1~2個渠道進行首發(fā),首發(fā)的渠道包一方面要進行替換資源,另一方面在代碼上也有需求(比如有些渠道要求首發(fā)閃屏保持2s以上,心疼為app做啟動優(yōu)化的同學……)。因此這部分要進行動態(tài)配置。 - gradle打包時獲取渠道號
我們要利用gradle進行首發(fā)渠道包的打包,因此需要根據(jù)每次的需求動態(tài)獲取需要首發(fā)渠道號,并進行打包 - 普通多渠道打包時對首發(fā)渠道的處理
Android多渠道打包最佳實踐中直接在 defaultRelease 包的基礎(chǔ)進行了多渠道打包,這次gradle打包完成后會編譯出所有的首發(fā)渠道包,我們需要把渠道號寫入到對應(yīng)的渠道包中。
+ 代碼中對首發(fā)渠道號的處理
這里主要是根據(jù)需求在代碼中判斷自己是否是首發(fā)包。
Paste_Image.png
代碼實現(xiàn)
首發(fā)渠道號配置
這里三個地方要獲取首發(fā)渠道號,gradle、渠道號寫入、代碼中讀取,考慮到方便行,我們把首發(fā)渠道號單獨寫在文件中,方便各步的讀取。gradle中讀取
android中g(shù)radle實際使用groovy,groovy與java語法非常像,很容易上手。
這里利用groovy讀取配置文件,獲取到首發(fā)渠道號
//讀取首發(fā)渠道號
ArrayList channelList = new File("xxx").readLines()
java.lang.StringBuffer channels = new StringBuffer()
channelList.each {
channel -> channels.append(channel + ","
)}
//在這里進行渠道號到配置
productFlavors {
//自動打包每個渠道號,需要包各個渠道的資源放置在相應(yīng)的目錄下
//這里可以參考利用gradle進行多渠道打包,方法是一樣的,網(wǎng)上資源也比較多
channelList.each {
flavorName -> "$flavorName" {}
}
//首發(fā)渠道號到Androidmanifest,這樣代碼中可以讀取到
productFlavors.all {
flavor -> flavor.manifestPlaceholders = [Channel: channels]
}
}
渠道號寫入
非首發(fā)渠道可以通過在default包中寫入渠道號,首發(fā)包的渠道寫入相應(yīng)的渠道包中。
這里可以使用shell或則python腳本寫入。
shell命令參見Android多渠道打包最佳實踐代碼中讀取
在打包時已經(jīng)把所有的首發(fā)渠道號寫入到了AndroidManifest中,讀取即可
try {
ApplicationInfo ai = getPackageManager().getApplicationInfo( getPackageName(), PackageManager.GET_META_DATA);
if (null != ai) {
metaData = ai.metaData;
}
if (null != metaData) {
metaValue = metaData.getString(metaKey);
}
} catch (PackageManager.NameNotFoundException e) {
}
return metaValue;
至此,基本動態(tài)多渠道資源替換完成。