flavorDimensions 多維度理解(版本差異化打包)

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)的代碼邏輯
                }
...

最后,轉載自:

Android Studio3.0 flavorDimensions多維度理解(版本差異化打包)

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容