美文网首页
ProductFlavor多渠道的神器

ProductFlavor多渠道的神器

作者: 诡异的叶子 | 来源:发表于2021-06-22 15:28 被阅读0次

    之前在浏览掘金的时候,看到有大佬写过一篇文章关于Android ProductFlavor的文章,原文链接:
    https://juejin.cn/post/6973570453629567012

    但是由于之前在公司项目也用过ProductFlavor,发现和大佬用的有些区别,自己就硬着头皮去看完了官网的文档(英文不好的痛),原文地址

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

    然后觉得应该记录下自己的学习历程

    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下就有如下几个编译条件(这里假设buildType只有debugrelease

    image.png

    1.2 dimension组合配置

    当一个module中定义了不同的dimension,并且在不同的Flavor下使用,那么会组合使用,也就是总共会有 dimension【0】...dimension【n-1】(每个代表dimension使用Flavor个数,如果没有使用,就不需要计入)buldType的个数;其中配置会相互交叉

    image.png

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

    flavorDimensions 'api', 'version'
    
        productFlavors {
            demo {
                dimension 'version'
            }
    
            full {
                dimension 'version'
    
            }
    
            minApi24 {
                dimension 'api'
            }
    
            minApi21 {
                dimension "api"
            }
        }
    

    那么build variant的环境会有:

    配置个数= api的flavor个数(2)* version的flavor个数*buildType个数(2) = 8个

    image.png

    2.提升使用

    前面已经讲清楚如何使用dimension配置,那么如何实现多渠道里面的不同配置,如app名,applicationIdicon图标,甚至mainifest下的配置参数呢。

    2.1 defaultConfig配置修改

    这就是ProductFlavor下的第一个特点了,就是可以动态修改moduledefaultConfig参数,包括:
    applicationIdminSdkVersiontargetSdkVersionversionCodeversionNamejavaCompileOptions等配置
    (具体有哪些可以查这个地址https://developer.android.google.cn/reference/tools/gradle-api/7.1/com/android/build/api/dsl/BaseFlavor?hl=en

    image.png

    首先默认的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()]
                }
            }
        }
    

    这个配置应用的运行结果如下

    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环境下的包配置如下

    image.png

    再看看,product环境下的包配置如下

    image.png

    完全生效的。

    2.2 使用不同res/java目录替换配置

    可以在app目录下根据不同的product,使用不同的java/res资源;然后根据不同的flavor,使用不同的配置

    image.png

    这里,更改两个参数,string里面的app_name

    这里举例更改:
    原main环境下

    image.png image.png

    dev环境下

    image.png image.png

    product环境下

    image.png image.png

    运行结果:

    image.png

    2.3 manifestPlaceholders 向mainifest注入资源

    在某些情况下,会需要根据不同的配置,更改mainifest下的部分参数配置,比如app的名字或者icon,这里就需要使用manifestPlaceholders,如果想看官网原文,连接如下,https://developer.android.google.cn/studio/build/manifest-build-variables.html?hl=en
    这里建议 和2.2使用不同res/java目录替换配置二选一,只使用其中一种

    同样的,可以使用manifestPlaceholders实现上面一样的效果;

    这里需要注意,flavor中使用mainifestPlaceholders一定要指定ENVIRONMENT,默认环境为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"
            }
        }
    

    运行结果如下

    image.png

    2.4 buildConfigField 配置资源

    在某些情况下,我们会需要根据不同的环境,加入以下不同的配置,这个也可以使用ProductFlavor中buildConfigField在编译时,动态配置。

    buildConfigField具备三个参数 type(类型,这里可用基本类型),name(这个在BuildConfig中的名称),value(这个参数在BuildConfig中的值);具体参数解析如下

    image.png

    如下的配置参数

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

    编译后 对应module的BuildConfig为

    image.png

    然后可以在代码中使用这些资源

    2.5 matchingFallbacks和missingDimensionStrategy

    这两个特性当时刚看的时候,看的头大,而且官网资料写的很少,最终在stackoverflow看到有人推荐的一篇博文,然后自己试着写了一些测试代码,终于是搞定了。文章地址https://kiranrao.in/blog/2020/03/31/gradle-missing-flavors/

    2.5.1 matchingFallbacks

    首先说matchingFallbacks的设计背景:在多module依赖的模式下,如module A依赖 module B ;如果AProductFlavor下有 devproductflavor,而B中只有dev;那么当mudule A编译devXXX的情况下,会正常通过编译;而编译product的情况下,会异常;理由就是B中找不到对应的product 条件的flavor;而matchingFallbacks就是用来解决这个问题的

    上面说这么多,不如直接代码来演示
    新建一个module名字叫flavor1,它build.gradle内容如下:

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

    然后app module依赖flavor1,它build.gradle 内容如下:

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

    这里 主module有 dev,product两个flavor;子module只有一个dev 的flavor

    image.png

    dev条件下是正常的

    image.png
    然而运行product就无法通过了 image.png
    以上错误信息就是背景描述的情况;
    其中matchingFallbacks格式如下

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

    对应主module下的flavor在子module会按照这个配置顺序去适配子moduleflavor

    所以修改主module配置(matchingFallbacks

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

    然后再次编译安装,ok了;总结一下,这里当子module有的flavor,而主module存在的flavor,(dimension需要一样)就需要配置matchingFallbacks使用子mudule中的flavor顺序。

    2.5.2 missingDimensionStrategy

    使用条件:当主module中不存在,而子module中存在的dimension,就需要在主module中定义使用哪个dimension下的哪一个flavor;其结构如下:

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

    首先,创建子module flavor2,其build.gradle下,主module依赖它

     flavorDimensions "nations"
        productFlavors{
            dev{
                dimension "nations"
    
            }
            product{
                dimension "nations"
            }
    
            user{
                dimension "nations"
            }
        }
    

    直接运行,运行告警


    cbae56292f318b7203ee2b052c6a7d8.png

    所以需要按照之前格式指定对应的dimension 使用子module中哪一个flavor
    所以这里可以在主 module配置

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

    完成配置运行成功

    参考

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

    google官网 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

    相关文章

      网友评论

          本文标题:ProductFlavor多渠道的神器

          本文链接:https://www.haomeiwen.com/subject/rbqmyltx.html