Gradle Groovy多Flavor下BuildType配置被覆盖问题求解决方案
我之前也踩过这个Groovy Gradle的大坑!确实,当你在多个Product Flavor里嵌套配置BuildType的时候,最后一个Flavor的配置总是会覆盖前面所有的,导致推送串流这种严重问题——就像你说的,给麦当劳用户推的通知汉堡王用户也收到了,太闹心了。谷歌说这是预期行为,但在实际业务场景里完全不合理,而且很多开发者都反馈过这个问题。
问题根源
在Groovy版的Gradle DSL中,当你在productFlavors里写buildTypes闭包时,并不是为当前Flavor创建独立的BuildType配置,而是直接修改全局的buildTypes对象。所以你配置完mcDonalds的BuildType后,再配置burgerKing的BuildType时,相当于把全局的development和production配置给覆盖了,最后构建时自然只会用最后一次的设置。
可行解决方案(无需转KTS,无需新增维度)
下面两种方法都能解决你的问题,而且只会生成你需要的四个变体:mcDonaldsDevelopment、mcDonaldsProduction、burgerKingDevelopment、burgerKingProduction。
方案1:直接遍历所有变体,逐个配置
通过applicationVariants.all遍历每个生成的变体,针对特定的Flavor+BuildType组合单独设置变量,这样每个变体的配置都是独立的,不会互相覆盖:
android { buildTypes { development { initWith debug } production { initWith release } } productFlavors { mcDonalds { // 这里可以放Flavor的通用配置,比如applicationId之类的 } burgerKing { // 这里放burgerKing的通用配置 } } // 核心:逐个配置每个变体的manifestPlaceholders applicationVariants.all { variant -> def flavorName = variant.flavorName def buildTypeName = variant.buildType.name // 根据Flavor和BuildType的组合设置对应的参数 switch ("${flavorName}${buildTypeName.capitalize()}") { case "mcDonaldsDevelopment": variant.manifestPlaceholders = [ onesignal_app_id: "4b77f560-26f3-420d-b438-d7aeb9912d4d", onesignal_google_project_number: "REMOTE" ] break case "mcDonaldsProduction": variant.manifestPlaceholders = [ onesignal_app_id: "6b77f560-26f3-420d-b438-d7aeb9912d33", onesignal_google_project_number: "REMOTE" ] break case "burgerKingDevelopment": variant.manifestPlaceholders = [ onesignal_app_id: "8b77f560-26f3-420d-b438-d7aeb9912d44", onesignal_google_project_number: "REMOTE" ] break case "burgerKingProduction": variant.manifestPlaceholders = [ onesignal_app_id: "0b77f560-26f3-420d-b438-d7aeb9912456", onesignal_google_project_number: "REMOTE" ] break } } }
方案2:配合variantFilter确保无冗余变体
如果你担心不小心生成多余的变体,可以加上variantFilter来明确只保留你需要的四个组合,和方案1搭配使用更稳妥:
android { // ... 保留方案1中的buildTypes、productFlavors和applicationVariants配置 ... variantFilter { variant -> // 定义允许的变体名称 def allowedVariants = [ "mcDonaldsDevelopment", "mcDonaldsProduction", "burgerKingDevelopment", "burgerKingProduction" ] // 忽略不在允许列表里的变体 setIgnore(!allowedVariants.contains(variant.name)) } }
为什么这个方法有效?
applicationVariants.all是在Gradle生成所有变体之后,逐个对每个变体进行配置,每个变体都是独立的对象,所以不会有覆盖的问题。这种方式完全绕开了Groovy DSL中全局BuildType被覆盖的坑,而且不需要切换到KTS,也不需要新增产品维度,完美符合你的需求。
内容的提问来源于stack exchange,提问作者extmkv

