详解Gradle之flavor

文章详细介绍了如何在AndroidStudio中使用productFlavors进行不同环境的配置,包括设置不同的包名、资源文件、BuildConfig常量,以及在AndroidManifest.xml中配置渠道变量。此外,还提到了如何引用不同的module和处理不同维度的flavor匹配问题。
摘要由CSDN通过智能技术生成

flavor配置不同包名

productFlavors {
    dev {
        applicationId "com.lyl.dev"
    }
 
    stage {
        applicationId "com.lyl.stage"
    }
 
    prod {
        applicationId "com.lyl.prod"
    }
}

productFlavors 设置的不同环境包名会覆盖 defaultConfig 里面的设置的包名。

falvor配置不同资源文件

productFlavors {
    dev {
        resValue "string", "app_name", "dev_myapp"
        resValue "bool", "isrRank", 'false'
    }
    stage {
        resValue "string", "app_name", "stage_myapp"
        resValue "bool", "isrRank", 'true'
    }
    prod {
        resValue "string", "app_name", "myapp"
        resValue "bool", "isrRank", 'true'
    }
}

利用 resValue 来定义资源的值,顾名思义 res 底下的内容应该都可以创建,最后用 R.xxx.xxx 来引用。
注意:这里是添加,不是覆盖,不能与res文件中已有的资源文件冲突。

flavor配置BuildConfig常量

productFlavors {
    dev {
        buildConfigField "String", "ENVIRONMENT", '"dev"'
    }
    stage {
        buildConfigField "String", "ENVIRONMENT", '"stage"'
    }
    prod {
        buildConfigField "String", "ENVIRONMENT", '"prod"'
    }
}

flavor配置AndroidManifest.xml 里渠道变量

1.AndroidManifest.xml设置占位符

<application
    android:icon="${app_icon}"
    android:label="@string/app_name"
    android:theme="@style/AppTheme">
    ...
    <meta-data
        android:name="UMENG_CHANNEL"
        android:value="${ENVIRONMENT}" />
    ...
</application>

2.build.gradle中填充占位符的值

productFlavors {
    dev {
        manifestPlaceholders = [ENVIRONMENT: "dev",
                                app_icon   : "@drawable/icon_dev"]
    }
    stage {
        manifestPlaceholders = [ENVIRONMENT: "stage",
                                app_icon   : "@drawable/icon_stage"]
    }
    prod {
        manifestPlaceholders = [ENVIRONMENT: "prod",
                                app_icon   : "@drawable/icon_prod"]
    }
}

flavor引用不同的module

xxxCompile 代表 各个渠道的名称(gradle3.0后改为xxxImplementation)。

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
 
    // 引用本的项目
    devCompile project(':devModule')
    stageCompile project(':stageModule')
    prodCompile project(':prodModule')
 
    // 也可以分渠道引用网络的。因为这里都相同,所以地址也就都一样了
    devCompile 'com.roughike:bottom-bar:2.0.2'
    stageCompile 'com.roughike:bottom-bar:2.0.2'
    prodCompile 'com.roughike:bottom-bar:2.0.2'
}

在子module中使用flavor

在子module中也有使用flavor的诸多场景,如在网络请求的module中对测试版和正式版的服务器地址会有区别,此时可以通过flavor来区别配置。现有实现如下。
注意本文配置均是基于gradle4.6,gradle3.0前后配置有些许差别。
主module中buid.gradle

android {
    ...
    flavorDimensions ""
    productFlavors{
        rel {
            dimension ""
        }


        dev {
            dimension ""
        }
    }
  ...
}


dependencies {
  ...
    relImplementation project(path: ':mylib2')
    devImplementation project(path: ':mylib2')
  ...
}

“relImplementation”表示flavor为rel时的依赖,“devImplementation”表示flavor为dev时的依赖。

子module的build.gradle

flavorDimensions ""
    productFlavors{
        rel {
            buildConfigField("String", "env", "\"正式服务器地址\"")
            dimension ""
        }


        dev {
            buildConfigField("String", "env", "\"测试服务器地址\"")
            dimension ""
        }
    }

接着在代码中通过BuildConfig.env即可获取不同flavor下的服务器地址。
再在Build variants中选择想要调试的buildType。

d32581910090f8ca36c49b2cb7878393.jpeg

主module或子module中存在独有的flavor的处理方法

情况1:

app中有某个build type但module中没有
// In the app's build.gradle file.
android {
    buildTypes {
        debug {}
        release {}
        staging {
            // 下面[]中的qa、debug、release是module中配置的buildType,必须含有其中一个或更多,
            // 若module中buildType没有staging,gradle会根据matchingFallbacks的配置,
            // 依次按顺序去匹配
            // 注意:module与module之间存在依赖关系的话,也要在特定的build types中指定匹配关系
            matchingFallbacks = ['qa', 'debug', 'release']
        }
    }
}

注意:module中有但app中没有的build type是不会报错的,因为gradle插件根本不会去module中请求build type

情况2:

在app和它的module中都有同一个维度(比如:flavorDimensions 'tier'),但你的app有的flavors在module中没有
flavorDimensions 'tier'
productFlavors {
    paid {
        // 因为依赖app的module在'tier'维度下也有'paid'这个flavor,所以你不用去管,
        // gradle会自动为你匹配
        dimension 'tier'
    }
    free {
        // 因为module在'tier'维度下没有'free'这个flavor,所以需要指定matchingFallbacks
        // 让gradle知道怎么去匹配
        // 像下面这样配置,gradle会按顺序依次去匹配module中'tier'维度下的flavor,
        // 直到匹配到,否则会报错
        matchingFallbacks = ['demo', 'trial']
    }
}

注意:对于在同一个维度下,module中有的flavors但app中没有是不会报错的,因为gradle插件根本不会去module中请求flavors。

情况3:

module中有某个dimension维度,但app中没有
// In the app's build.gradle file.
android {
    defaultConfig{
        // 下面这句话告诉gradle,当遇到一个module中有个app中没有的'minApi'维度时,
        // 它应该按照下面这个顺序去匹配这个维度的flavors
        missingDimensionStrategy 'minApi', 'minApi18', 'minApi23'
        // 若其他module中还有更多app中没有的维度,你必须为所有的维度定义回退策略
        missingDimensionStrategy 'abi', 'x86', 'arm64'
    }
    flavorDimensions 'tier'
    productFlavors {
        free {
            dimension 'tier'
            // 你可以在一个特定的flavor中覆盖defaultConfig的配置
            missingDimensionStrategy 'minApi', 'minApi23', 'minApi18'
        }
        paid { }
    }
}

注意:当一个维度app中有但module中没有的时候是不会报错,因为gradle插件只会匹配已经在module中存在的维度,比如module中没有abi这个维度,当app为freeX86Debug时,你的module就用freeDebug
missingDimensionStrategy 方法其他属性可以参考官方文档https://developer.android.com/reference/tools/gradle-api。

情况4:

若module中没有某个dimension,则app不需要在这个dimension下做任何处理

其他:

1、排除掉某些不需要的变体

variantFilter { variant ->
    def names = variant.flavors*.name
    def types = variant.buildType.name
    if (names.contains("abi") && types == "debug") {
        // Gradle ignores any variants that satisfy the conditions above.
        setIgnore(true)
    }
}

flavor打包

77fba9728fd0eb776d9ff545565058d3.jpeg

双击对应任务或terminal终端执行/gradlew xxx均能完成打包。

  • assembleADSgTt即打包单个flavor下的debug和release包。

  • assembleRelease即打包所有的release包。

最后打包的apk位置在xx\build\outputs\apk下。

1aafaf3d5b132b5d42935e51e3c2bc8f.jpeg

flavor编译

编译时在左下角BuildVariants中选择想要编译的type即可。

28ee757ea9606874d14b3d6e6195988e.jpeg

flavor更多变体

请参考:https://developer.android.google.cn/studio/build/build-variants?hl=zh-cn

关注我获取更多知识或者投稿

bde8f1a8c4ad46a1aa9ae8ca48e61dc9.jpeg

509f5173032d7875ddba7bb9cfeac794.jpeg

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值