Search code examples
androidgradle-kotlin-dsl

How to update the manifestPlaceholders in applicationVariants in Kotlin Gradle DSL?


I try to convert this to Kotlin:

applicationVariants.all { variant ->
    def flavor = variant.productFlavors[0]
    def mergedFlavor = variant.getMergedFlavor()
    mergedFlavor.manifestPlaceholders = [applicationLabel: "${variant.buildType.appName[flavor.name]}"]
}

But the manifestPlaceholder is a val and cannot be reassigned, so this results in an error:

applicationVariants.forEach {variant->
    val flavor = variant.productFlavors[0]
    val mergedFlavor = variant.mergedFlavor
    variant.mergedFlavor.manifestPlaceholders = mapOf("applicationLabel" to "${variant.buildType.appName[flavor.name]}")
}

Normally I could set this in the buildTypes closure, but I cannot do it here, because appName is a map in the buildTypes, where the key is the flavor name, so the applicationLabel depends both on the build type and the flavor. And I think you cannot access the flavors in the buildTypes, that's why you need applicationVariants.


Solution

  • I had to change a few things in the above to make it work:

    1. The flavor map (appLabelMap here) has to go into applicationVariants, so you can use it straight away.
    2. ManifestPlaceHolders is indeed a val, but you can replace the values in the map. :)
    3. applicationVariants.forEach is not executed, so you have to use applicationVariants.all. But beware that it's clashing (sort of) with koltin.collections.all(), so instead of the closure you have to use the one that takes an Action.

    This is the final result:

    applicationVariants.all {
        val appLabelMap = when (this.buildType.name) {
            "debug" -> mapOf("flavorA" to "FlavorA Debug", "flavorB" to "FlavorB Debug")
            ...
            else -> mapOf("flavorA" to "FlavorA", "flavorB" to "FlavorB")
        }
        val flavor = this.productFlavors[0]
        this.mergedFlavor.manifestPlaceholders["applicationLabel"] = "${appLabelMap[flavor.name]}"
    }
    

    You also have to set a default for applicationLabel in android.defaultConfig:

    android.defaultConfig { manifestPlaceholders["applicationLabel"] = "FlavorA"}
    

    This is the relevant part of AndroidManifest.xml, just in case it's not clear:

    <application
         android:label="${applicationLabel}"
         ...
         <activity
         ...>
         ...
         </activity>
         ...
    </application>
    

    Once you know how to do it, it looks easy!