ProductFlavor多渠道的神器

之前在瀏覽掘金的時候,看到有大佬寫過一篇文章關(guān)于Android ProductFlavor的文章,原文鏈接:
https://juejin.cn/post/6973570453629567012

但是由于之前在公司項目也用過ProductFlavor,發(fā)現(xiàn)和大佬用的有些區(qū)別,自己就硬著頭皮去看完了官網(wǎng)的文檔(英文不好的痛),原文地址

https://developer.android.google.cn/reference/tools/gradle-api/7.1/com/android/build/api/dsl/ProductFlavor

然后覺得應(yīng)該記錄下自己的學(xué)習(xí)歷程

image.png

1.ProductFlavor的簡單使用

1.1 dimension簡單使用

首先,是在module的目錄下(可以是application,library)中build.gradle中,配置信息如下

 flavorDimensions "nation"
    productFlavors{
        dev{
            dimension "nation"
        }
        product{
            dimension "nation"       
        }

        user{
            dimension "nation"
        }
    }

其中,productFlavors下每個flavor都必須有一個dimension(Android Gradle Plugin 3.0.0以后引入);這樣build variant下就有如下幾個編譯條件(這里假設(shè)buildType只有debugrelease

image.png

1.2 dimension組合配置

當(dāng)一個module中定義了不同的dimension,并且在不同的Flavor下使用,那么會組合使用,也就是總共會有 dimension【0】...dimension【n-1】(每個代表dimension使用Flavor個數(shù),如果沒有使用,就不需要計入)buldType的個數(shù);其中配置會相互交叉

image.png

新建一個module,其中ProductFlavor的配置如下

flavorDimensions 'api', 'version'

    productFlavors {
        demo {
            dimension 'version'
        }

        full {
            dimension 'version'

        }

        minApi24 {
            dimension 'api'
        }

        minApi21 {
            dimension "api"
        }
    }

那么build variant的環(huán)境會有:

配置個數(shù)= api的flavor個數(shù)(2)* version的flavor個數(shù)*buildType個數(shù)(2) = 8個

image.png

2.提升使用

前面已經(jīng)講清楚如何使用dimension配置,那么如何實現(xiàn)多渠道里面的不同配置,如app名,applicationId,icon圖標(biāo),甚至mainifest下的配置參數(shù)呢。

2.1 defaultConfig配置修改

這就是ProductFlavor下的第一個特點了,就是可以動態(tài)修改moduledefaultConfig參數(shù),包括:
applicationId,minSdkVersion,targetSdkVersionversionCode,versionName,javaCompileOptions等配置
(具體有哪些可以查這個地址https://developer.android.google.cn/reference/tools/gradle-api/7.1/com/android/build/api/dsl/BaseFlavor?hl=en

image.png

首先默認(rèn)的defaultConfig配置

 defaultConfig {
        applicationId "com.example.myandroidkotlin"
        minSdkVersion 18
        targetSdkVersion 30
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        multiDexEnabled true

        missingDimensionStrategy 'consumer', 'consumed'

        javaCompileOptions {
            annotationProcessorOptions {
                arguments += ["room.schemaLocation":
                                      "$projectDir/schemas".toString()]
            }
        }
    }

這個配置應(yīng)用的運(yùn)行結(jié)果如下

image.png

接下來,就是使用ProductFlavor的情況

image.png
flavorDimensions "nation"
    productFlavors{
        dev{
            dimension "nation"
            //defaultconfig
            applicationId "com.example.myandroidkotlin.dev"
            minSdkVersion 18
            targetSdkVersion 30
            versionCode 101
            versionName "1.0.1"
        }
        product{
            dimension "nation"
            //defaultconfig
            applicationId "com.example.myandroidkotlin.product"
            minSdkVersion 16
            targetSdkVersion 29
            versionCode 120
            versionName "1.2.0"
        }
    }

首先,dev環(huán)境下的包配置如下

image.png

再看看,product環(huán)境下的包配置如下

image.png

完全生效的。

2.2 使用不同res/java目錄替換配置

可以在app目錄下根據(jù)不同的product,使用不同的java/res資源;然后根據(jù)不同的flavor,使用不同的配置

image.png

這里,更改兩個參數(shù),string里面的app_name

這里舉例更改:
原main環(huán)境下

image.png
image.png

dev環(huán)境下

image.png
image.png

product環(huán)境下

image.png
image.png

運(yùn)行結(jié)果:

image.png

2.3 manifestPlaceholders 向mainifest注入資源

在某些情況下,會需要根據(jù)不同的配置,更改mainifest下的部分參數(shù)配置,比如app的名字或者icon,這里就需要使用manifestPlaceholders,如果想看官網(wǎng)原文,連接如下,https://developer.android.google.cn/studio/build/manifest-build-variables.html?hl=en
這里建議 和2.2使用不同res/java目錄替換配置二選一,只使用其中一種

同樣的,可以使用manifestPlaceholders實現(xiàn)上面一樣的效果;

這里需要注意,flavor中使用mainifestPlaceholders一定要指定ENVIRONMENT,默認(rèn)環(huán)境為main(也就是資源目錄下main文件)
引入新的icon

image.png

mainifest文件

image.png

string.xml

image.png

build.gradle 配置信息

 flavorDimensions "nation"
    productFlavors{
        dev{
            dimension "nation"
            manifestPlaceholders=[ENVIRONMENT:"main",
                                  app_icon: "@mipmap/newlogo",
                                  app_name:"@string/app_name_dev"]
        }
        product{
            dimension "nation"
            manifestPlaceholders=[ENVIRONMENT:"main",
                                  app_icon: "@mipmap/newlogo",
                                  app_name:"@string/app_name_product"
        }
    }

運(yùn)行結(jié)果如下

image.png

2.4 buildConfigField 配置資源

在某些情況下,我們會需要根據(jù)不同的環(huán)境,加入以下不同的配置,這個也可以使用ProductFlavor中buildConfigField在編譯時,動態(tài)配置。

buildConfigField具備三個參數(shù) type(類型,這里可用基本類型),name(這個在BuildConfig中的名稱),value(這個參數(shù)在BuildConfig中的值);具體參數(shù)解析如下

image.png

如下的配置參數(shù)

 flavorDimensions "nation"
    productFlavors{
        dev{
            dimension "nation"
            //buildConfigField
            buildConfigField "String", "TAG", '"apple"'
            buildConfigField "int", "BASE_PORY", '12'
            buildConfigField "Boolean", "IS_OK", 'true"

        }
      }

編譯后 對應(yīng)module的BuildConfig為

image.png

然后可以在代碼中使用這些資源

2.5 matchingFallbacks和missingDimensionStrategy

這兩個特性當(dāng)時剛看的時候,看的頭大,而且官網(wǎng)資料寫的很少,最終在stackoverflow看到有人推薦的一篇博文,然后自己試著寫了一些測試代碼,終于是搞定了。文章地址https://kiranrao.in/blog/2020/03/31/gradle-missing-flavors/

2.5.1 matchingFallbacks

首先說matchingFallbacks的設(shè)計背景:在多module依賴的模式下,如module A依賴 module B ;如果AProductFlavor下有 devproductflavor,而B中只有dev;那么當(dāng)mudule A編譯devXXX的情況下,會正常通過編譯;而編譯product的情況下,會異常;理由就是B中找不到對應(yīng)的product 條件的flavor;而matchingFallbacks就是用來解決這個問題的

上面說這么多,不如直接代碼來演示
新建一個module名字叫flavor1,它build.gradle內(nèi)容如下:

flavorDimensions "nation"
    productFlavors{
        dev{
            dimension "nation"
        }
    }

然后app module依賴flavor1,它build.gradle 內(nèi)容如下:

 flavorDimensions "nation"
    productFlavors{
        dev{
            dimension "nation"
        }
        product{
            dimension "nation"
        }
    }

這里 主module有 dev,product兩個flavor;子module只有一個dev 的flavor

image.png

dev條件下是正常的

image.png

然而運(yùn)行product就無法通過了

image.png

以上錯誤信息就是背景描述的情況;
其中matchingFallbacks格式如下

matchingFallbacks["子module使用flavor1","子module 的使用flavor2",...]

對應(yīng)主module下的flavor在子module會按照這個配置順序去適配子moduleflavor

所以修改主module配置(matchingFallbacks

 flavorDimensions "nation"
    productFlavors{
        dev{
            dimension "nation"
        }
        product{
            dimension "nation"
             //matchingFallbacks 多module匹配條件
            matchingFallbacks = ['dev']
        }
    }

然后再次編譯安裝,ok了;總結(jié)一下,這里當(dāng)子module有的flavor,而主module存在的flavor,(dimension需要一樣)就需要配置matchingFallbacks使用子mudule中的flavor順序。

2.5.2 missingDimensionStrategy

使用條件:當(dāng)主module中不存在,而子module中存在的dimension,就需要在主module中定義使用哪個dimension下的哪一個flavor;其結(jié)構(gòu)如下:

missingDimensionStrategy["dimension","子module dimension 下的使用flavor"]

首先,創(chuàng)建子module flavor2,其build.gradle下,主module依賴它

 flavorDimensions "nations"
    productFlavors{
        dev{
            dimension "nations"

        }
        product{
            dimension "nations"
        }

        user{
            dimension "nations"
        }
    }

直接運(yùn)行,運(yùn)行告警


cbae56292f318b7203ee2b052c6a7d8.png

所以需要按照之前格式指定對應(yīng)的dimension 使用子module中哪一個flavor
所以這里可以在主 module配置

 flavorDimensions "nation"
    productFlavors{
        dev{
            dimension "nation"         
            missingDimensionStrategy 'nations', 'dev'
        }
        product{
            dimension "nation"         
            missingDimensionStrategy 'nations', 'product'

        }

完成配置運(yùn)行成功

參考

尾巴大不掉 https://juejin.cn/post/6973570453629567012?utm_source=gold_browser_extension

google官網(wǎng) https://developer.android.google.cn/reference/tools/gradle-api/7.1/com/android/build/api/dsl/ProductFlavor

missingDimensionStrategy https://kiranrao.in/blog/2020/03/31/gradle-missing-flavors/

項目地址:

https://github.com/jiaoery/MyAndroidKotlin

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

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容