目錄
1、前言
2、flavorDimensions 的意義
3、productFlavors的意義
4、productFlavor
5、寫在最後
html
有了前兩篇博客的鋪墊,咱們能夠來分享下另外兩個參數了 flavorDimensions
和 productFlavors
,而這兩個參數成對出現,能夠作一些差分化定義。java
前兩篇博客爲:
一、defaultConfig——安卓gradle
二、buildTypes——安卓gradle
android
須要事先說明的是,接下來所說的 「意義」 並不是官方文檔翻譯,而是結合了小盆友本身的理解,會比較口語化。git
flavorDimensions 從單詞字面理解知道是 「風味維度」,是須要結合 「產品風味(即productFlavors)」 來一塊兒使用的。程序員
flavorDimensions 的使用會定義出維度,供接下來的 productFlavors 使用。咱們舉個例子github
android {
// 省略其餘參數
flavorDimensions('abi', 'version')
}
複製代碼
使用上面代碼,則會定義出兩個維度:version 和 abi。一個參數一個維度,咱們把它形象化,就能夠當作下面這樣一張圖。而他有什麼做用,咱們看下一小節。 後端
若是三個參數就能夠當作一個三維的空間座標系,這裏的座標系只是一個形象化的體現。bash
productFlavors 從字面瞭解是「產品風味」。他須要和一個風味維度對接,不然會報錯。微信
接着咱們上面的例子,使用 productFlavors 定義維度上的風味,使用 dimension
關聯。架構
android{
// 其餘參數
flavorDimensions('abi', 'version')
// 建立產品風味
productFlavors {
v1 {
// 關聯緯度
dimension 'version'
}
v2 {
dimension 'version'
}
v3 {
dimension 'version'
}
x86 {
dimension 'abi'
}
armV7 {
dimension 'abi'
}
}
}
複製代碼
經過上面這段代碼,會造成下面這張圖。在 abi 維度上關聯了兩個產品,即 「armV7」 和 「x86」,在 version 的維度上關聯了三個產品,即 「v1」、「v2」 和 「v3」。
而這些維度的交織就會造成最終的風味,即咱們上面所標出來的 「armV7V1」、「armV7V2」、「armV7V3」、「x86V1」、「x86V2」、「x86V3」。咱們能夠根據不一樣的風味,打出不一樣的apk包,即可以實現一套核心代碼打出多個有些差別的包。
更多的使用咱們在下篇博客講解,咱們先了解下他可配置的參數。
productFlavors
下的每一個項最終形式是 productFlavor
,即咱們上面說所的 「v1」,「v2」.....
咱們知道,每一個配置最終會被映射爲一個類,或是一個屬性、或一個方法。productFlavor 也不例外,他會被映射爲 com.android.build.gradle.internal.dsl.ProductFlavor
,繼承結構以下
咱們先來一個約定,避免使用的代碼過於冗長。
android {
productFlavors{
zincPower{
// 咱們下面的 「使用方法」 代碼都是基於這一塊,除非特殊說明。
}
}
}
複製代碼
defaultConfig
中配置的 applicationId
。從而可讓咱們打出不一樣的apk包。defaultConfig 的具體配置能夠看小盆友的另外一篇博文,傳送門。
zincPower {
// applicationId 應用的包名,會覆蓋 defaultConfig 中的 applicationId
// applicationId 會替換 AndroidManifest.xml 中的 manifest 標籤下 package 的 value
applicationId "com.zinc.power"
......省略其餘配置
}
複製代碼
zincPower {
applicationIdSuffix '.debug'
}
複製代碼
library
中,包括咱們以aar形式導入的 library ,或是直接建立的 library。它的做用是,負責該 library 被進行編譯時的混淆規則,咱們在 主App 的模塊下則能夠不用再管理各個 library 的混淆規則,會直接使用各個 library 的混淆規則文件。zincPower {
consumerProguardFiles 'consumer-rules.pro'
......省略其餘配置
}
// 由於該屬性是一個 List<File> 類型,若是須要多個文件配置,則以下所示
zincPower {
consumerProguardFiles 'consumer-rules.pro','zincPower-rules.pro'
......省略其餘配置
}
複製代碼
ERROR: Flavor 'v1' has no flavor dimension.
複製代碼
zincPower {
// 關聯緯度
dimension 'version'
......省略其餘配置
}
複製代碼
zincPower {
externalNativeBuild {
ndkBuild {
// Passes an optional argument to ndk-build.
arguments "NDK_MODULE_PATH+=../../third_party/modules"
}
// For ndk-build, instead use the ndkBuild block.
cmake {
// Passes optional arguments to CMake.
arguments "-DANDROID_ARM_NEON=TRUE", "-DANDROID_TOOLCHAIN=clang"
// Sets a flag to enable format macro constants for the C compiler.
cFlags "-D__STDC_FORMAT_MACROS"
// Sets optional flags for the C++ compiler.
cppFlags "-fexceptions", "-frtti"
// Specifies the library and executable targets from your CMake project
// that Gradle should build.
targets "libexample-one", "my-executible-demo"
}
}
}
複製代碼
annotationProcessor
時所須要的參數。zincPower {
javaCompileOptions {
annotationProcessorOptions{
arguments = []
classNames ''
....
}
}
......省略其餘配置
}
複製代碼
JavaCompileOptions 能夠配置的具體參數,請進傳送門
AndroidManifest.xml
中替換的參數,咱們可使用這個參數配置不一樣風味的 logo 和 app名字,以及友盟的參數,達到不一樣風味的差別化配置。咱們配置差別化的 logo 和 app名字,則能夠在 gradle 中使用下面這段
android {
flavorDimensions('abi', 'version')
productFlavors {
// 省略其餘的風味配置
x86 {
dimension 'abi'
// 配置不一樣的包名,達到能兩個風味能共存
applicationId 'com.zinc.bear'
manifestPlaceholders = [
logo : "@drawable/logo_bear",
appName : "bear",
]
// 配置簽名
signingConfig signingConfigs.jiangpengyong
}
armV7 {
dimension 'abi'
// 配置不一樣的包名,達到能兩個風味能共存
applicationId 'com.zinc.shark'
manifestPlaceholders = [
logo : "@drawable/logo_shark",
appName : "shark",
]
// 配置簽名
signingConfig signingConfigs.xiaopenyou
}
}
}
複製代碼
logo的資源圖
而後在 AndroidManifest.xml
中使用,使用 ${你配置的變量名}
<application android:allowBackup="true" android:icon="${logo}" android:label="${appName}" android:roundIcon="${logo}" android:supportsRtl="true" android:theme="@style/AppTheme">
......
複製代碼
最終分別運行後,咱們能夠看到以下效果
舉個例子: 咱們有一個 x86 的風味 在引入一個 library,而 library 中存在一樣的風味維度,可是沒有相同產品風味,這樣會致使無法匹配,此時,就須要用這個參數。代碼以下:
app 下的 build.gradle
android {
// 其餘配置
flavorDimensions('abi')
// 建立產品風味
productFlavors {
x86 {
dimension 'abi'
matchingFallbacks = ['pro']
}
}
dependencies {
// 引入 flavor_x86 library
x86Implementation project(':flavor_x86')
}
複製代碼
flavor_x86 下的 build.gradle
android {
// 存在相同的風味維度
flavorDimensions('abi')
// 沒有相同的產品風味,須要使用 matchingFallbacks 選擇須要的產品風味
productFlavors {
pro {
dimension 'abi'
}
free{
dimension 'abi'
}
}
}
複製代碼
小盆友在github上有個demo,有所幫助就給star吧。
64K 引用限制問題官方文檔 傳送門
爲了不篇幅過長,使用方法請看小盆友的另外一片博文:defaultConfig——安卓gradle 的 3.8小節
classs.dex
。咱們在第 2.9 小點,分享到使用了多 dex包處理,有時咱們須要將一些主要的類打包進主包,則可使用該屬性。zincPower {
multiDexKeepFile file('multidex-config.txt')
...
}
複製代碼
multidex-config.txt 中的書寫則以下,每個文件則爲一行
com/example/MyClass.class
com/example/TestClass.class
複製代碼
zincPower {
multiDexKeepFile file('multidex-config.pro')
...
}
複製代碼
multidex-config.pro 中的寫法以下
// 將會保留全部的在com.example package的類
-keep class com.example.** { *; }
複製代碼
armeabi-v7a
,不會包含其餘的架構,例如 "X86"。zincPower {
// ndk中,目前只有 abiFilter 一個屬性,因此 ndk 目前來講只用於 abi 的過濾
ndk {
abiFilter 'armeabi-v7a'
}
...
}
複製代碼
NdkOptions的具體可配參數見官方文檔 傳送門
minifyEnabled
設置爲 true 的時候會使用這個參數,文件中須要申明哪些文件不被優化和混淆。zincPower {
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
複製代碼
SigningConfig 的可配置參數 傳送門
(1)咱們須要先在項目根目錄下建立一個 keystore.properties 文件,在文件中寫入對應的配置,如圖所示
(2)在應用級的 build.gradle 中使用以下代碼// 引入咱們在(1)中建立的配置
def keystorePropertiesFile = rootProject.file("keystore.properties")
def keystoreProperties = new Properties()
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
android {
compileSdkVersion 28
buildToolsVersion "29.0.1"
defaultConfig {
// 省略一些配置...
}
signingConfigs {
xiaopenyou {
// 使用 keystoreProperties 獲取對應的參數
keyAlias keystoreProperties['keyAlias2']
keyPassword keystoreProperties['keyPassword2']
storeFile file(keystoreProperties['storeFile2'])
storePassword keystoreProperties['storePassword2']
}
// ...其餘簽名配置
}
buildTypes {
// 省略一些配置...
}
flavorDimensions('abi', 'version')
// 建立產品風味
productFlavors {
// 省略一些配置...
armV7 {
// 省略一些配置...
signingConfig signingConfigs.xiaopenyou
}
}
}
複製代碼
generatedDensities
和 useSupportLibrary
。分別的用處以下zincPower {
vectorDrawables {
// 若是 minSdkVersion 小於 21,只生成mdpi的png
generatedDensities 'mdpi'
// 設置爲 true,會忽略 generatedDensities ,會加入svg兼容包,不會再產生png
useSupportLibrary true
}
}
複製代碼
矢量圖的用法,能夠看小盆友的另外一片文章
versionName
的區別在小盆友看來,versionCode
是給程序員看的,versionName
是給產品經理和用戶看的。zincPower {
versionCode 1000
......
}
複製代碼
zincPower {
versionName "1.0.0"
.....
}
複製代碼
zincPower {
// 若是 versionName "1.0.0" ,則最終的版本名爲 1.0.0.test
versionNameSuffix ".test"
.....
}
複製代碼
// 值的注意的是 value 的值是原樣放置,咱們經過使用方法一節來了解
<type> <name> = <value>
複製代碼
productFlavors {
x86 {
// 能夠經過 BuildConfig 進行獲取
buildConfigField('String', 'name', '"XiaoPenYou"')
buildConfigField('int', 'age', '26')
.....
}
}
複製代碼
最終會生成以下圖的配置,咱們能夠經過下面代碼進行獲取
String name = BuildConfig.name;
int age = BuildConfig.age;
複製代碼
值的一提的是,咱們設置 String 類型的參數時,須要加上 "" 雙引號(如例子中的name屬性)。切記!
zincPower {
consumerProguardFile('consumer-rules.pro')
}
複製代碼
zincPower {
consumerProguardFile('consumer-rules.pro', 'zincPower-rules.pro',.....)
}
複製代碼
zincPower {
// 最高支持28版本
minSdkVersion 28
}
複製代碼
zincPower {
// 最低支持19版本
minSdkVersion 19
}
複製代碼
咱們的項目結構以下
在zinclibrary
的
build.gradle
中編寫了以下渠道配置
// 建立 風味維度
flavorDimensions('zinc', 'handsome')
// 建立產品風味
productFlavors {
minApi13{
dimension 'zinc'
}
minApi23{
dimension 'zinc'
}
x86{
dimension 'handsome'
}
arm64{
dimension 'handsome'
}
}
複製代碼
此時若是直接在 app
的 build.gradle
中添加依賴,同步時便會出錯
dependencies {
...忽略其餘依賴
implementation project(":zinclibrary")
}
複製代碼
因此咱們須要在 app
的 build.gradle
中使用這個參數進行忽略 library 中帶來的維度和風味,即便用以下代碼
zincPower {
missingDimensionStrategy 'zinc', 'minApi13', 'minApi23'
missingDimensionStrategy 'handsome', 'x86', 'arm64'
}
複製代碼
zincPower {
proguardFile 'proguard-rules.pro'
}
複製代碼
debug {
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
複製代碼
zincPower {
// 這樣咱們編譯出的apk中,只有 「默認」 和 「中文zh」 兩種資源
resConfig "zh"
}
複製代碼
zincPower {
// 這樣咱們編譯出的apk中,只有 「默認」 、 「中文zh」 和 「英文en」 兩種資源
resConfigs "zh","en"
}
複製代碼
zincPower {
// 添加至 res/value,經過 R.string.age 獲取
resValue('string', 'age', '12year')
}
複製代碼
zincPower {
consumerProguardFiles = [ 'consumer-rules.pro','zincPower-rules.pro' ]
}
複製代碼
zincPower {
proguardFiles = [getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro']
}
複製代碼
zincPower {
targetSdkVersion 28
}
複製代碼
Gradle 的配置文件看起來好像挺亂,實際上是由於咱們沒有進行總體的梳理,所謂 「無知最可怕」。
若是喜歡的話請給我一個贊,並關注我吧。文章中若有寫的不妥的地方,請評論區或加我微信與我討論吧,共同進步。
歡迎加我微信,進行更多的交流
若是以爲文章有很大的幫助,快來讚揚一次吧😄