Chapter4:創建構建Variant
- Variant 英文翻譯:變體。
4.1 構建類型
在Gradle的Android插件中,構建類型用來定義如何構建一個應用或依賴庫。可以在 buildTypes代碼塊 中定義:
android { buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } }
minifyEnabled :清除無用資源。
創建構建類型:除了debug/release構建類型外,可以自定義構建類型,只需要在 buildTypes代碼塊 中新增一個類似debug/release的對象即可。
android { buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } staging{ applicationIdSuffix ".staging" versionNameSuffix "-staging" } } }
自定義構建類型staging定義了一個新的applicationId後綴,表示相同設備可以同時安裝release版本和staging版本。版本名也添加了新的後綴,用於在同一設備上區分多個應用版本。
//另一種創建方式,複製一個已存在的構建類型並在其基礎上覆寫或定義額外屬性。 staging.initWith(buildTypes.release) staging{ applicationIdSuffix ".staging" versionNameSuffix "-staging" }
源集:**一個源集(sorce set)就是一組源文件,他們會被一起執行和編譯。**當創建一個新的構建類型時,Gradle會創建一個新的源集。
在Android Studio中需要手動創建源集的目錄。
源集使得我們可以針對特定的構建類型覆寫某些屬性,爲某些構建類型添加自定義代碼,以及爲不同的構建類型添加自定義佈局或字符串。
注意:添加Java類到構建類型時時互相排斥的。比如添加了example.java到staging源集,可以往debug和release源集中加入example.java,但是不能添加example.java到main源集。
使用不同源集時,資源文件會被特殊處理。Drawables 和 layout 文件將完全覆蓋在 main 源集中有相同名稱的資源;values文件夾中的文件不會被覆蓋,而是整合到main資源中,同一子屬性會被非main源集中的替代。
<!--main源集--> <resources> <string name="app_name">main</string> <string name="other">abc</string> </resources> <!--staging源集--> <resources> <string name="app_name">staging</string> </resources> <!--合併後--> <resources> <string name="app_name">staging</string> <string name="other">abc</string> </resources>
依賴:每個構建類型都可以有自己的依賴。在依賴前加入源集的名稱即可。
//在debug源集中定義的依賴 debugImplementation 'androidx.cardview:cardview:1.0.0' //在staging源集中定義的依賴 stagingImplementation 'androidx.cardview:cardview:1.0.0'
4.2 product flavor
與配置相同的App/Library的不同構建相反,product flavor用來創建不同版本。比如:免費版和收費版。product flavor簡化了基於相同代碼構建多個版本的應用的過程。當你需要一個全新的App,度已於已有的發佈的App時,你需要用到product flavor。
創建product flavor:
在 productFlavor代碼塊 中添加新的product flavor:
android { flavorDimensions "version" productFlavors { red { flavorDimension "version" applicationId "com.virtual.red" versionCode 21 } blue { flavorDimension "version" applicationId "com.virtual.blue" minSdkVersion 24 versionCode 19 } } }
注意:新版Android Studio或要求爲所有類型都指定的一個類型維度,否則會報錯ERROR: All flavors must now belong to a named flavor dimension.
解決辦法:添加
flavorDimensions "version"
。具體參考官方說明。源集:和建構類型相似,product flavor也可以創建自己的源集目錄。甚至,可以爲一個特定的構建類型和flavor的結合體創建文件夾,文件夾名稱爲 flavor名+構建類型名 ,比如 blueRelease,合併的文件夾比flavor文件夾和構建類型文件夾擁有更高的優先級。
多種定製版本:
舉例一種情況,客戶A和客戶B想在他們的App中都有免費版和付費版,並且是基於相同代碼、不同的品牌。創建4中不同的flavor需要多個拷貝,不是最佳做法。結合flavor維度可以高效的解決:
android{ flavorDimensions "color","price" productFlavors{ red{ flavorDimension "color" } bule{ flavorDimension "color" } free{ flavorDimension "price" } paid{ flavorDimension "price" } }
注意:flavor維度數組的順序決定了那個flavor配置將被覆蓋,color將覆蓋price,該順序也決定了variant的名稱。比如:buleFreeDebug、buleFreeRelease、bulePaidDebug、bulePaidRelease、redFreeDebug、redFreeRelease、redPaidDebug、redPaidRelease。
4.3 構建variant
- 構建 variant 是構建類型和product flavor的結合的結果。當創建一個構建類型或product flavor時,新的variant 便會被創建。Android Studio在 Build variants 工具窗口中列舉了所有的variant並允許切換,選中要構建的variant,Run時將允許該variant:
沒有product flavor時variant將只包含構建類型。不可以沒有構建類型。(Gradle的Android插件會默認創建debug構建類型。)
任務:
- Gradle 的 Android插件會爲你配置的每一個構建variant創建任務。
- 使用 assemble+product flavor+構建類型 創建特定variant的APK(比如:assembleBlueDebug)。使用assemble創建所有variant的APKs。
源集:
構建variant是一個構建類型和一個或多個product flavor的結合體,可以有自己的源集文件夾。文件夾名稱爲 flavor名+構建類型名 。
對於資源和manifest文件的優先度:
Build type > Flavor >Main >Dependencies
關於manifest文件合併更詳細的內容參考:官方文檔
variant 過濾器:當你需要忽略某些variant時:1.會加快assemble命令構建所有variant的進程;2.任務列表不會被無需執行的任務污染;3.Android Studio的構建variant切換器中也不會出現過濾的構建variant。
android{...} //過濾掉blueRelease的variant構建 android.variantFilter{ variant -> if (variant.buildType.name.equals('release')){ variant.getFlavors().each(){ flavor-> if(flavor.name.equals('blue')){ variant.setIgnore(true); } } } }
簽名配置:在發佈App之前,需要用私鑰給它簽名。每個flavor要使用不同的私鑰簽名。
android{ signingConfigs{ staging.initWith(signingConfigs.debug) release{ storeFile file("release.keystore") storePassword "123456" keyAlias "gradleforandroid" keyPassword "654321" } } }
- Android插件會使用通用的 keystore和一個已知密碼自動創建debug的簽名配置,不需自己創建。
- 這裏使用兩種方式配置:1. .initWith() 方法從另一個簽名配置中複製所有屬性。2.realease通過storeFile來指定keystore文件的路徑,之後定義祕鑰別名和兩個密碼。
定義前面配置後,將配置用用到構建類型或flavor中。
//1.對於構建類型的簽名配置 android{ buildTypes{ release{ signingConfig signingConfigs.release } } } //2.對於flavor的簽名配置,會覆蓋構建類型的簽名配置 android{ productFlavors{ blue{ signingConfig signingConfigs.release } } } //3.在使用flavor是,爲每個構建類型的每個flavor分配不同的祕鑰 android{ buildTypes{ release{ productFlavors.red.signingConfig signingConfigs.red productFlavors.blue.signingConfig signingConfigs.blue } } }
4.4 參考資料
- Gradle For Android