根据不同的口味和构建类型来构建配置字段

20

我正在尝试根据flavor+buildType来定义一个buildConfigVariable。理想情况下,这就是我想要的。

productFlavors {
    strawberry {
        buildConfigField "String", "WS_API_KEY", name + variant.buildType.name
    }
    ... more flavors ..
}
< p >< em > name 包含 "strawberry",但我不知道是否可以访问 < em > variant 的 < em > buildType 。< / p> < p >放在 < em > Android 闭包外部,我可以访问 < em > BuildType 和 < em > variant ,但是我无法调用 < code > buildConfigField 。< / p>
android.applicationVariants.all { variant ->
    println "****************************"
    println "variant: ${variant.name}"
    println "flavor: ${variant.flavorName}"
    println "****************************"

    if (variant.buildType.name == 'release') {
        if (variant.flavorName == 'strawberry') {
            buildConfigField "String", "WS_API_KEY", '"strawberry_release"'
        } else {
            buildConfigField "String", "WS_API_KEY", '"chocolate_release"'
        }
    } else if(variant.buildType.name == 'debug') {
        if (variant.flavorName == 'strawberry') {
            buildConfigField "String", "WS_API_KEY", '"strawberry_debug"'
        } else {
            buildConfigField "String", "WS_API_KEY", '"chocolate_debug"'
        }
    }


****************************
variant: strawberryRelease
flavor: strawberry
****************************
org.gradle.api.internal.MissingMethodException: 
    Could not find method buildConfigField() 
    for arguments [String, WS_API_KEY, "strawberry_release"]

我可以轻松地创建一个Java工厂,并根据一些BuildConfig常量返回适当的API_KEY,但我宁愿保持代码配置无关。


这可能会有帮助。https://dev59.com/JV0a5IYBdhLWcg3waYGM#50983681 - abitcode
2个回答

17
编辑2:0.14.2之后的版本将允许这样做:
applicationVariants.all { variant ->
    variant.buildConfigField "int", "VALUE", "1"
}

因此,您将能够执行类似于以下操作(以匹配原始问题):

applicationVariants.all { variant ->
    variant.buildConfigField "String", "WS_API_KEY", variant.productFlavors.get(0).name + '_' + variant.buildType.name
}

编辑:目前无法实现。API缺失。 Bug:https://code.google.com/p/android/issues/detail?id=67416

尝试这个:

applicationVariants.all { variant ->
    variant.mergedFlavor.buildConfigField "String", "NAME", '"VALUE"'
}


这会抛出一个错误MissingMethodException: com.android.builder.DefaultProductFlavor.buildConfigField()方法的签名不适用于参数类型:(java.lang.String, java.lang.String, java.lang.String)值:[String, NAME, "VALUE"] 可能的解决方案是:getBuildConfigFields()。 - Maragues
我有自己的解决方案,但可能不太稳定,所以我很乐意看到更好的解决方案。我将在5分钟内发布它。 - Maragues
哦,mergedFlavor不是这个合适的类型。让我看看。 - Xavier Ducrohet
嗨Xavier,我已经更新了我的答案并提供了一个可行的版本,但我很好奇是否有更好的方法(我猜应该有)。感谢你的工作! - Maragues
3
看起来很丑,但我想现在还没有更好的方法。我们必须加以改进。 https://code.google.com/p/android/issues/detail?id=67416 - Xavier Ducrohet
显示剩余2条评论

0

警告:这可能是一个脆弱的解决方案,请自行承担风险。请参见https://code.google.com/p/android/issues/detail?id=67416

这就是我实现想要的功能的方法。您需要在任务执行之前更改值,因此我需要一种将我的代码挂钩在那里的方法。

final projectName = project.name
gradle.taskGraph.beforeTask { Task task ->
    if (task.path ==~ /:$projectName:generate.*BuildConfig/) {
        //extracts flavor and buildType name. See https://dev59.com/BWsz5IYBdhLWcg3w48Cm#7594052 for regex
        final values = task.name.replace("generate","").replace("BuildConfig","").split("(?<!(^|[A-Z]))(?=[A-Z])|(?<!^)(?=[A-Z][a-z])")

        final flavorName = values[0].toLowerCase()
        final buildTypeName = values[1].toLowerCase()

        com.android.build.gradle.api.ApplicationVariant variant;
        android.applicationVariants.all { currentVariant ->
            if (currentVariant.getVariantData().getVariantConfiguration().getBuildType().getName() == buildTypeName) {
                if (currentVariant.getVariantData().getVariantConfiguration().getFlavorName() == flavorName) {
                    variant = currentVariant;
                }
            }
        }

        if(variant != null) {
            com.android.builder.internal.ClassFieldImpl apiKeyField
            if (flavorName == 'strawberry') {    
                if (buildTypeName == 'release') {
                    apiKeyField = new com.android.builder.internal.ClassFieldImpl("String", "WS_API_KEY", '"strawberry_release"')
                } else {
                    apiKeyField = new com.android.builder.internal.ClassFieldImpl("String", "WS_API_KEY", '"strawberry_debug"')
                }
            } else if (flavorName == 'chocolate') {                        
                if (buildTypeName == 'release') {
                    apiKeyField = new com.android.builder.internal.ClassFieldImpl("String", "WS_API_KEY", '"chocolate_release"')
                } else {
                    apiKeyField = new com.android.builder.internal.ClassFieldImpl("String", "WS_API_KEY", '"chocolate_debug"')
                }
            }

            variant.getVariantData().getVariantConfiguration().getFlavorConfigs().get(0).addBuildConfigField(apiKeyField)
        }
    }
}

要理解为什么这样可以,请下载AOSP源代码并检查VariantConfiguration.getBuildConfigItems() 使用Xavier的答案会抛出MethodMissingError。如果我使用variant.mergedFlavor.addBuildConfigField(),就不会有错误,但变量也不会被添加。

您可以使用公共API,无需使用ClassFieldImplcom.android.builder.model.ClassField apiKeyField,然后声明def createClassField = com.android.builder.core.AndroidBuilder.&createClassField,然后不再调用new ClassFieldImpl(...),而是直接调用createClassField(...) - TWiStErRob

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接