Gradle多渠道打包的原理、實(shí)踐與輔助開(kāi)發(fā)

背景

在發(fā)布apk時(shí),經(jīng)常遇到需要發(fā)布多個(gè)版本,每個(gè)版本均有細(xì)微差異的情況,稱(chēng)為多渠道打包,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)多渠道打包。

buildTypes與文件目錄

在實(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í)的覆蓋。

drawable資源文件會(huì)直接覆蓋

2、資源文件的合并,字符串、顏色值、整型等資源以及 AndroidManifest.xml ,將會(huì)進(jìn)行元素級(jí)的覆蓋(不同版本只要寫(xiě)與主版本不同的元素即可)。

字符串等xml資源,會(huì)覆蓋元素

3、代碼資源的準(zhǔn)備,代碼文件不會(huì)覆蓋或合并,同一個(gè)類(lèi)文件, 在不同目錄(buildTypes 、 productFlavors 、 main)中只能存在一次,否則會(huì)有類(lèi)重復(fù)的錯(cuò)誤。

在main中不能有待分版的代碼文件

這種做法的問(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ù)邏輯

通過(guò)常量設(shè)置不同版本的代碼邏輯

需要說(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)前版本即可。

根據(jù)Build Variant使用不同的代碼

4、覆蓋等級(jí)為:buildTypes > productFlavors > main。

實(shí)踐

一個(gè)從零開(kāi)始做gradle多渠道打包的流程如下:

首先,我們要為每個(gè)版本創(chuàng)建BuildTypes及對(duì)應(yīng)的文件目錄

buildTypes與文件目錄

點(diǎn)開(kāi)左下角的Build Variant,可以看到多版本的配置已經(jīng)生效

多版本已生效

根據(jù)上文所述,根據(jù)各版本需要更換資源文件

更換資源文件

編寫(xiě)xml資源中待替換的元素

待替換的元素

制作各版本的java代碼文件

各版本的java代碼文件

再次強(qiáng)調(diào),這種方式下,在main中不能有同名代碼文件。

或者自定義版本常量,在main的代碼中編寫(xiě)各版本的業(yè)務(wù)邏輯

根據(jù)版本實(shí)現(xiàn)不同的業(yè)務(wù)邏輯

打包時(shí),可以選擇多個(gè)版本一起打包

同時(shí)打包

生成多個(gè)apk文件

生成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í)間就很可觀了,還依賴(lài)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時(shí)選擇不同的版本

在這里選擇需要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ā)。

mock模擬數(shù)據(jù)

在服務(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的妙用

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容