Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Build Configurations based on App Variant (BuildType + Flavor)

I am trying to set signingConfig, manifestPlaceholders, buildConfigField for Application variant. I can set them for each buildType or! productFlavor independently, but what i need is to set them based on both productFlavor and! buildType.

buildTypes{
  getByName("debug"){}
  getByName("release"){}
  create("staging"){}
}

productFlavors {
  create("global"){}
  create("local"){}
}

On the above example, there are 3 different buildTypes and 2 different productFlavors. That means 6 total APK variants. For each of this APK (globalRelease, globalStaging, globalDebug, localRelease, localStaging, localDebug), i want to use different signingConfig for example. How do i set it?

Tried:

  • If i set it in buildType, then there will be only 3 different signingConfigs
  • If i set it in flavor, then there will be only 2 different signingConfigs
  • If i try to set it in applicationVariants.all{}, there is no setter functions, only getters on Variant object (link)
  • setting fields on (variant.mergedFlavor as DefaultProductFlavor) does not add buildConfigField values to BuildConfig.java (link)
like image 878
Jemshit Iskenderov Avatar asked Apr 01 '20 15:04

Jemshit Iskenderov


1 Answers

After Gradle 7.x


Instead of applicationVariants.all{}, we now use androidComponents { onVariants{ .. }} outside android{} block. This code should work on Gradle 7.0.2 and AGP 7.0.1:

androidComponents {
    onVariants { variant ->
        variant.buildConfigFields.put("MY_CUSTOM_FIELD", BuildConfigField("String", "MyCustomValue", null))
        variant.manifestPlaceholders.put("MY_MANIFEST_FIELD", "MyManifestValue")
    }
}

On AGP 7.0.x, there is no way to set signingConfig for mergedFlavor (buildType+flavor). You can set for buildType or flavor individually, but not for combination.

On AGP 7.1.x, you can do it. But it requires AGP 7.1.0-alpha10, Gradle 7.2-rc-3, AndroidStudio BumbleBee 2021.1.1 alpha10:

androidComponents {
    onVariants { variant ->
        variant.signingConfig?.setConfig(android.signingConfigs.getByName("buildTypeXFlavorA"))
    }
}

‎‎ ‎

Before Gradle 7.x


To make changes on different variants (buildType+productFlavor), i had to use android.applicationVariants.all{}. But different paths used to achieve multiple signingConfig, manifestPlaceholders, buildConfigField

1) manifestPlaceholders

applicationVariants.all{
    val variant = this
}

There is no getter/setter for manifestPlaceholders on variant object. Following this, we can make variant.mergedFlavor mutable. Setting manifestPlaceholders on variant.mergedFlavor did work.

import com.android.builder.core.DefaultProductFlavor

applicationVariants.all{
    val manifestPlaceholders: Map<String, String>
    val variant = this
    val mutableMergedFlavor = variant.mergedFlavor as DefaultProductFlavor
    mutableMergedFlavor.addManifestPlaceholders(manifestPlaceholders)
}

2) buildConfigField

Using the same approach, calling addBuildConfigField(ClassFieldImpl(type, name, value)) on mutableMergedFlavor did not work. But instead, it can be set directly on variant.

import com.android.builder.internal.ClassFieldImpl

applicationVariants.all{
    val buildConfigFields: List<ClassFieldImpl>
    val variant = this
    buildConfigFields.forEach { 
        variant.buildConfigField(it.type, it.name, it.value) 
    }
}

3) signingConfig signingConfig can be set on mutableMergedFlavor shown above, except on debug variants. All debug variants use default signing options, even if you set it on variant.mergedFlavor. But if you set default as null, then you can override it as well.

import com.android.builder.core.DefaultProductFlavor

signingConfigs {
    create("myDebug") {}
}
buildTypes {
    getByName("debug") {
        signingConfig = null // to override
    }
}
applicationVariants.all{
    val variant = this
    val mutableMergedFlavor = variant.mergedFlavor as DefaultProductFlavor
    mutableMergedFlavor.signingConfig = signingConfigs.getByName("myDebug")
}

To put all together:

import com.android.build.gradle.api.ApplicationVariant
import com.android.builder.internal.ClassFieldImpl
import com.android.builder.model.SigningConfig
import com.android.builder.core.DefaultProductFlavor
import java.util.*

fun configureVariant(variant: ApplicationVariant,
                     signingConfig: SigningConfig,
                     buildConfigFields: List<ClassFieldImpl>,
                     manifestPlaceholders: Map<String, String>) {

    println("configureVariant: ${variant.name}")
    buildConfigFields.forEach {
        variant.buildConfigField(it.type, it.name, it.value)
    }

    val mutableMergedFlavor = variant.mergedFlavor as DefaultProductFlavor
    mutableMergedFlavor.signingConfig = signingConfig
    mutableMergedFlavor.addManifestPlaceholders(manifestPlaceholders)
}

android {
    signingConfigs {
        create("myDebug") {}
        create("myRelease") {}
    }

    flavorDimensions("region")
    productFlavors {
        create("global") {
            setDimension("region")
            setApplicationId("")
        }
        create("local") {
            setDimension("region")
            setApplicationId("")
        }
    }

    buildTypes {
        getByName("debug") {
            signingConfig = null
        }
    }

    applicationVariants.all {
        val variant = this
        when {
            variant.name.equals("localDebug", true) -> {
                configureVariant(
                        variant,
                        signingConfigs.getByName("localDebug"),
                        listOf(ClassFieldImpl("String", "NAME", "\"VALUE\"")),
                        mapOf("KEY" to "VALUE")
                )
            }
            variant.name.equals("globalStaging", true) -> {
                configureVariant(
                        variant,
                        signingConfigs.getByName("globalStaging"),
                        listOf(ClassFieldImpl("String", "NAME", "\"VALUE2\"")),
                        mapOf("KEY" to "VALUE2")
                )
            }
        }
    }
}

like image 113
Jemshit Iskenderov Avatar answered Sep 21 '22 15:09

Jemshit Iskenderov