21

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.

Herrbert74
  • 2,578
  • 31
  • 51

2 Answers2

24

manifestPlaceHolders was changed to a val mutablemap in a recent gradle release

  manifestPlaceholders["appAuthRedirectScheme"] =  "whatever"
  manifestPlaceholders["appRedirectScheme"] =  "whatever"
    

That was the fix for me.

bsautner
  • 4,479
  • 1
  • 36
  • 50
15

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!

Herrbert74
  • 2,578
  • 31
  • 51
  • I was struggling there for hours! I couldn't find info about it, my applicacionVariants where not executing!! This part I think it should be highlighted `so instead of the closure you have to use the one that takes an Action.` For somebody with the same problem, check that the lambda does not require to return a boolean. – Ch4vi May 13 '20 at 08:21