背景
在發(fā)布apk時(shí),經(jīng)常遇到需要發(fā)布多個(gè)版本宗兼,每個(gè)版本均有細(xì)微差異的情況躏鱼,稱為多渠道打包,Android Studio中提供了利用Gradle實(shí)現(xiàn)多渠道打包的功能殷绍。
原理
我們知道染苛,apk的打包過(guò)程分7步:
1、打包資源文件主到,生成R.java文件
2茶行、處理aidl文件,生成相應(yīng)java 文件
3登钥、編譯工程源代碼畔师,生成相應(yīng)class 文件
4、轉(zhuǎn)換所有class文件牧牢,生成classes.dex文件
5看锉、打包生成apk
6、對(duì)apk文件進(jìn)行簽名
7塔鳍、對(duì)簽名后的apk文件進(jìn)行對(duì)齊處理
多渠道打包伯铣,就是對(duì)這個(gè)過(guò)程進(jìn)行一定程度的干涉,Android Studio的Gradle可以通過(guò)設(shè)置productFlavors來(lái)實(shí)現(xiàn)這個(gè)功能轮纫,通過(guò)自定義buildTypes腔寡,在打包時(shí)把主目錄與自定義的buildType目錄合并,每個(gè)buildType對(duì)應(yīng)一個(gè)渠道掌唾,實(shí)現(xiàn)多渠道打包放前。
在實(shí)際操作中忿磅,針對(duì)不同的待打包文件,還要采取不同的方式:
1犀斋、配置文件贝乎,增設(shè)參數(shù),在打包時(shí)讀取不同版本的參數(shù)叽粹;
2、資源文件却舀,各版本準(zhǔn)備與主版本不同的資源文件虫几,在打包時(shí)合并或置換;
3挽拔、代碼文件辆脸,各版本準(zhǔn)備自己需要的代碼文件,或在代碼中針對(duì)不同的版本修改業(yè)務(wù)邏輯螃诅;
規(guī)則
1啡氢、資源文件的覆蓋,圖片术裸、音頻倘是、 XML 類(lèi)型的 Drawable 等資源文件,將會(huì)進(jìn)行文件級(jí)的覆蓋袭艺。
2搀崭、資源文件的合并,字符串猾编、顏色值瘤睹、整型等資源以及 AndroidManifest.xml ,將會(huì)進(jìn)行元素級(jí)的覆蓋(不同版本只要寫(xiě)與主版本不同的元素即可)答倡。
3、代碼資源的準(zhǔn)備瘪撇,代碼文件不會(huì)覆蓋或合并获茬,同一個(gè)類(lèi)文件, 在不同目錄(buildTypes 设江、 productFlavors 锦茁、 main)中只能存在一次,否則會(huì)有類(lèi)重復(fù)的錯(cuò)誤叉存。
這種做法的問(wèn)題是码俩,由于main目錄下不能有這個(gè)代碼文件,所以每個(gè)版本都需要維護(hù)一個(gè)本版本的代碼文件歼捏,在后續(xù)開(kāi)發(fā)中會(huì)有嚴(yán)重的代碼文件冗余問(wèn)題稿存。
如果代碼變動(dòng)不大笨篷,沒(méi)必要使用多個(gè)代碼文件,可以在gradle中定義一個(gè)與版本有關(guān)的常量瓣履,在代碼中根據(jù)這個(gè)常量判斷版本率翅,輸出不同的業(yè)務(wù)邏輯
需要說(shuō)明的是,在制作不同版本的java文件時(shí)袖迎,會(huì)發(fā)現(xiàn)圖標(biāo)不是熟悉的java代碼的藍(lán)色圖標(biāo)冕臭,只是普通的文件夾圖標(biāo),里面也不能右鍵創(chuàng)建package燕锥,這是因?yàn)楫?dāng)前的Build Variants不是當(dāng)前版本辜贵,AS并沒(méi)有使用那部分代碼,在Build Variants中更換為當(dāng)前版本即可归形。
4托慨、覆蓋等級(jí)為:buildTypes > productFlavors > main。
實(shí)踐
一個(gè)從零開(kāi)始做gradle多渠道打包的流程如下:
首先暇榴,我們要為每個(gè)版本創(chuàng)建BuildTypes及對(duì)應(yīng)的文件目錄
點(diǎn)開(kāi)左下角的Build Variant厚棵,可以看到多版本的配置已經(jīng)生效
根據(jù)上文所述,根據(jù)各版本需要更換資源文件
編寫(xiě)xml資源中待替換的元素
制作各版本的java代碼文件
再次強(qiáng)調(diào)蔼紧,這種方式下婆硬,在main中不能有同名代碼文件。
或者自定義版本常量歉井,在main的代碼中編寫(xiě)各版本的業(yè)務(wù)邏輯
打包時(shí)柿祈,可以選擇多個(gè)版本一起打包
生成多個(gè)apk文件
一個(gè)簡(jiǎn)單的多渠道打包過(guò)程就完成了。
速度問(wèn)題與快速多渠道打包
Gradle多渠道打包最大的問(wèn)題是速度太慢哩至,像上文那樣同時(shí)打包3個(gè)apk躏嚎,其實(shí)就是依次打3個(gè)apk,消耗的時(shí)間遠(yuǎn)遠(yuǎn)超過(guò)打包1個(gè)菩貌,如果待發(fā)布的產(chǎn)品版本過(guò)多(幾十個(gè))卢佣,一次打包消耗的時(shí)間就很可觀了,還依賴gradle就不合適了箭阶。
這種情況下虚茶,一個(gè)好的作法是先用gradle打包,把得到的apk當(dāng)做壓縮包仇参,用自定義工具去直接修改apk文件嘹叫。
所以快速多渠道打包的基本原理是:先制作1個(gè)基礎(chǔ)apk,然后自己寫(xiě)一個(gè)配置工具诈乒,去批量地解壓縮基礎(chǔ)apk并修改文件罩扇,從而取得較快的發(fā)布速度。
在Github上有一個(gè)很實(shí)用的開(kāi)源項(xiàng)目,快速多渠道打包開(kāi)源項(xiàng)目AndroidMultiChannelBuildTool喂饥,是使用Python實(shí)現(xiàn)的消约,使用也很簡(jiǎn)單,本文在此不再贅述员帮。
利用多渠道輔助開(kāi)發(fā)
Gradle多渠道打包不限于制作apk或粮,在debug時(shí)也會(huì)起作用,我們可以利用這一點(diǎn)輔助開(kāi)發(fā)捞高。
例如氯材,我們可以在開(kāi)發(fā)過(guò)程中模擬后臺(tái)數(shù)據(jù),這樣可以在后臺(tái)服務(wù)接口開(kāi)發(fā)滯后時(shí)硝岗,先完成Android端的業(yè)務(wù)開(kāi)發(fā)浓体。
前面說(shuō)過(guò),在多渠道打包會(huì)出現(xiàn)多個(gè)Build Variants
在這里選擇需要debug的版本辈讶,就可以mock模擬數(shù)據(jù)。
利用這樣的原理娄猫,我們可以制作一個(gè)mock版本贱除,在開(kāi)發(fā)前期使用mock版本模擬返回服務(wù)端數(shù)據(jù),在連接后臺(tái)調(diào)試和產(chǎn)品發(fā)布時(shí)媳溺,使用prod版本發(fā)布月幌,而他們使用的業(yè)務(wù)邏輯都是main中的同一套代碼,所以能很好的加速開(kāi)發(fā)悬蔽。
在服務(wù)端尚不能提供數(shù)據(jù)時(shí)扯躺,這可以幫助我們先完成Android端的開(kāi)發(fā),詳情可以參考Android Studio Flavors的妙用
參考文獻(xiàn)
本文參考了Gradle Plugin User Guide的第5節(jié)Build Variants蝎困,英文不好的童鞋可以去讀Android build.gradle配置進(jìn)階录语,簡(jiǎn)短清晰。
本文參考了Android Studio Flavors的妙用禾乘。