Android Studio 自從升級到 3.0 之后,gradle 的玩法也隨之變得更加豐富起來,今天就來講講有關 flavorDimensions (官網(wǎng)翻譯過來是風味維度)的配置。
Android Studio3.0 之前,進行多模塊依賴開發(fā)的情況下,項目是正常運行的,然而把 studio 升級到 3.0 之后,原本的項目就出現(xiàn)了問題,具體問題如下:
Error:All flavors must now belong to a named flavor dimension.Learn more at
https://d.android.com/r/tools/flavorDimensions-missing-error-message.html
項目是沒問題的,那么就應該是配置上出了問題,但這又是什么鬼?
經(jīng)過了一番的折騰,終于明白了是怎么回事。直譯過來的話就是所有的風味現(xiàn)在必須屬于一個已命名的風味維度。官網(wǎng)提供的解決方式是:
// Specifies a flavor dimension.
flavorDimensions "color"
productFlavors {
red {
// Assigns this product flavor to the 'color' flavor dimension.
// This step is optional if you are using only one dimension.
dimension "color"
...
}
blue {
dimension "color"
...
}
}
在 defaultConfig 里面加入 flavorDimensions ,定義風味維度(也就是命名風味維度)。
然后在產(chǎn)品風味中指定所屬的風味維度。
好了,以上只是針對出現(xiàn)的問題進行解決,接下來就是針對 flavorDimensions 進行一些驗證。
多維度理解
其實這涉及到了版本差異化打包的內容,如果說 3.0 以前的版本差異化打包更多的是為了廠商定制的,那么 3.0 以后的版本差異化打包就是在廠商的基礎之上加入了機型,渠道等一些參數(shù),變成了多個維度的產(chǎn)品。
也就是說之前的一個產(chǎn)品只有一個參數(shù)進行描述的話,現(xiàn)在就可以為其增加多個參數(shù)進行配置,比如 A 廠商的 A 渠道的A機型、 A 廠商的 B 渠道的 C 機型等,維度越多,產(chǎn)品的樣式越發(fā)豐富。
好了,理論說完,接下來就是進行通俗易懂的一些示例了,只有實踐才能讓自己檢驗到真理。
新建項目,然后在 app/build.gradle 文件里配置兩個風味維度(“company”,“channel”),如下:
defaultConfig {
applicationId "com.voctex.flavorsapp"
minSdkVersion 18
targetSdkVersion 27
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
flavorDimensions "company","channel"
}
然后進行產(chǎn)品的多維度配置(完整配置在文章下面):
productFlavors{
//隨便命名,建議根據(jù)該維度的具體信息進行命名
companyA{
dimension "company"
}
companyB{
dimension "company"
}
channelA{
dimension "channel"
}
channelB{
dimension "channel"
}
}
配置完之后進行 gradle 構建,如果用 Terminal 命令直接構建打包的話,用如下命令:
//windows
gradlew :app:assembleRelease
//mac
./gradlew :app:assembleRelease
也可以直接用 studio 進行打包,在最右邊有個 Gradle,里面有很多 task,直接選擇 assembleRelease,如圖:

打包構建之后就會出現(xiàn)多個維度的產(chǎn)品,對應如下,如圖:

可以理解為總共有兩個維度,公司(company)和渠道(channel),這里公司的維度排前面(排序先后有要求,下面會講到),所以所有的產(chǎn)品就是,A 公司的 A 渠道產(chǎn)品,A 公司的 B 渠道產(chǎn)品,B 公司的 A 渠道產(chǎn)品,B 公司的 B 渠道產(chǎn)品。
可見,增加維度之后,版本差異化的內容就更為豐富了。
上面說了,維度的定義先后是有要求的,不可隨便,下面為了驗證這個說法進行了一項測試,我們在 productFlavors 里給每一個特點產(chǎn)品定義一個常量,常量的值就是該特點產(chǎn)品的名字。如下:
productFlavors{
companyA{
dimension "company"
buildConfigField "String","FLAVOR_NAME","\"companyA\""
}
companyB{
dimension "company"
buildConfigField "String","FLAVOR_NAME","\"companyB\""
}
channelA{
dimension "channel"
buildConfigField "String","FLAVOR_NAME","\"channelA\""
}
channelB{
dimension "channel"
buildConfigField "String","FLAVOR_NAME","\"channelB\""
}
}
這里有個要注意的點就是在 BuildConfig 定義 String 的常量時,需要把雙引號也加進去。
然后進行跟剛才一樣的構建,對比幾個風味維度的 BuildConfig 文件里的這個 FLAVOR_NAME 常量,會發(fā)現(xiàn)總是顯示第一維度 company 的值,而第二維度 channel 的值并不存在,所以當產(chǎn)生多維度的產(chǎn)品時,定義的一些常量總是以第一維度的配置為準。結果如下:
BuildConfig.java 文件生成后會在app/build/generated/source/buildConfig/companyAChannelA/release/com/voctex/flavorsapp/BuildConfig.java

-------------------------------------------圖片分割線------------------------------------------

-------------------------------------------圖片分割線------------------------------------------

-------------------------------------------圖片分割線------------------------------------------

實驗證明,當你在各個維度各自定義了同一個常量的值,總是以第一維度的為準,只有第一維度的定義或者說是修改才是有效的。
對了,忘記加上完整的配置信息,重新貼上:
apply plugin: 'com.android.application'
android {
compileSdkVersion 27
defaultConfig {
applicationId "com.voctex.flavorsapp"
minSdkVersion 18
targetSdkVersion 27
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
flavorDimensions "company","channel"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
productFlavors{
companyA{
dimension "company"
buildConfigField "String","FLAVOR_NAME","\"companyA\""
}
companyB{
dimension "company"
buildConfigField "String","FLAVOR_NAME","\"companyB\""
}
channelA{
dimension "channel"
buildConfigField "String","FLAVOR_NAME","\"channelA\""
}
channelB{
dimension "channel"
buildConfigField "String","FLAVOR_NAME","\"channelB\""
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:27.1.1'
implementation 'com.android.support.constraint:constraint-layout:1.1.0'
// testImplementation 'junit:junit:4.12'
// androidTestImplementation 'com.android.support.test:runner:1.0.2'
// androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}
因此,在項目中可以通過如下方式分別實現(xiàn)代碼邏輯(以下通過FLAVOR變量控制,也可使用或搭配其他變量):
比如本地工具類 Utils.java 中定義了對應的字符串變量,對應 BuildConfig.java中生成的值:
...
public static final String COMPANYA_CHANNELA= "companyAchannelA";
public static final String COMPANYA_CHANNELB= "companyAchannelB";
...
然后其它功能類的代碼中就可以通過判斷當前的配置變量實現(xiàn)對應型號的邏輯:
...
if (Utils.COMPANYA_CHANNELA.equals(BuildConfig.FLAVOR)) {
//公司 A 產(chǎn)品 A 想實現(xiàn)的代碼邏輯
} else if (Utils.COMPANYA_CHANNELB.equals(BuildConfig.FLAVOR)) {
//公司 A 產(chǎn)品 B 想實現(xiàn)的代碼邏輯
} else {
//默認配置平臺想實現(xiàn)的代碼邏輯
}
...