Define buildconfigfield for an specific flavor AND buildType

AndroidGradleAndroid Gradle-PluginBuild Tools

Android Problem Overview


I have 2 flavors, lets say Vanilla and Chocolate. I also have Debug and Release build types, and I need Vanilla Release to have a field true, while the other 3 combinations should be false.

def BOOLEAN = "boolean"
def VARIABLE = "VARIABLE"
def TRUE = "true"
def FALSE = "false"

    VANILLA {

        debug {

            buildConfigField BOOLEAN, VARIABLE, FALSE

        }

        release {

            buildConfigField BOOLEAN, VARIABLE, TRUE

        }


    }

    CHOCOLATE {
        buildConfigField BOOLEAN, VARIABLE, FALSE
    }

I'm having an error, so I guess the debug and release trick doesnt work. It is possible to do this?

Android Solutions


Solution 1 - Android

Loop the variants and check their names:

productFlavors {
	vanilla {}
	chocolate {}
}

applicationVariants.all { variant ->
	println("Iterating variant: " + variant.getName())
	if (variant.getName() == "chocolateDebug") {
		variant.buildConfigField "boolean", "VARIABLE", "true"
	} else {
		variant.buildConfigField "boolean", "VARIABLE", "false"
	}
}

Solution 2 - Android

Here is a solution without lacks I've described under Simas answer

buildTypes {
    debug {}
    release {}
}

productFlavors {
    vanilla {
        ext {
            variable = [debug: "vanilla-debug value", release: "vanilla-release value"]
        }
    }
    chocolate {
        ext {
            variable = [debug: "chocolate-debug value", release: "chocolate-release value"]
        }
    }
}

applicationVariants.all { variant ->
    def flavor = variant.productFlavors[0]
    variant.buildConfigField "boolean", "VARIABLE", "\"${flavor.variable[variant.buildType.name]}\""
}

Solution 3 - Android

Within the Gradle build system, buildTypes and productFlavors are unfortunately two separate entities.

As far as I am aware, to complete what you want to achieve, you would need to create another build flavour as such:

buildTypes {
        debug{}
        release {}
    }

    productFlavors {
        vanillaDebug {
             buildConfigField BOOLEAN, VARIABLE, FALSE
        }
        vanillaRelease {
             buildConfigField BOOLEAN, VARIABLE, TRUE
        }
        chocolate {
             buildConfigField BOOLEAN, VARIABLE, FALSE
        }
    }

Solution 4 - Android

For your specific case, you can also just play with defaultConfig:

defaultConfig {
    buildConfigField BOOLEAN, VARIABLE, TRUE
}

buildTypes {
    debug {
        buildConfigField BOOLEAN, VARIABLE, FALSE
    }
    release {
    }
}

productFlavors {
    VANILLA {
    }
    CHOCOLATE {
        buildConfigField BOOLEAN, VARIABLE, FALSE
    }
}

The Default value is TRUE, but then you put FALSE to all Debug builds and all Chocolate builds. So the only remaining TRUE is VANILLA-release.

Solution 5 - Android

Here's how I solved this:

def GAME_DIMENSION = "game"
def BUILD_DIMENSION = "building"

flavorDimensions GAME_DIMENSION, BUILD_DIMENSION

productFlavors {
    lollipop {
        dimension BUILD_DIMENSION
        minSdkVersion 21
    }

    normal {
        dimension BUILD_DIMENSION
    }

    game_1 {
        dimension GAME_DIMENSION
        ext {
            fields = [
                    [type: 'String', name: 'TESTSTRING', values: [debug: 'debugstring', release: 'releasestring']],
                    [type: 'int', name: 'TESTINT', values: [debug: '1234', release: '31337']]
            ]
        }
    }

    game_2 {
        dimension GAME_DIMENSION
        ext {
            fields = []  // none for game_2
        }
    }
}

applicationVariants.all { variant ->

    // get the GAME dimension flavor
    def game = variant.getProductFlavors()
            .findAll({ flavor -> flavor.dimension == GAME_DIMENSION})
            .get(0)

    println "Adding " + game.ext.fields.size() + " custom buildConfigFields for flavor " + variant.name

    // loop over the fields and make appropriate buildConfigField
    game.ext.fields.each { field ->
        def fldType = field['type']
        def fldName = field['name']
        def fldValues = field['values']

        // get debug/release specific value from values array
        def fldSpecificValue = fldValues[variant.getBuildType().name]

        // add quotes for strings
        if (fldType == 'String') {
            fldSpecificValue = '\"' + fldSpecificValue + '\"'
        }

        println "    => " + fldType + " " + fldName + " = " + fldSpecificValue
        variant.buildConfigField fldType, fldName, fldSpecificValue
    }
}

(I have not yet been able to determine whether or not ext.fields exists on a flavor)

Solution 6 - Android

You can try this for multiple products flavors:

productFlavors {
        demo {
            applicationId "com.demo"
            versionCode 1
            versionName '1.0'
            ext {
                APP_BASE_URL = [debug: "${BASE_URL_DEV}", release: "${BASE_URL_PRODUCTION}"]
            }
        }
        demo1 {
            applicationId "com.demo1"
            versionCode 1
            versionName '1.2'
            ext {
                APP_BASE_URL = [debug: "${BASE_URL_DEV}", release: "${BASE_URL_PRODUCTION}"]
            }
        }

    
    applicationVariants.all { variant ->
            def flavor = variant.productFlavors[0]
            variant.buildConfigField "String", "BASE_URL", "${flavor.ext.APP_BASE_URL[variant.buildType.name]}"
        }

Solution 7 - Android

@Simas Aswer is correct, but it might look a little bit better with switch case:

android {

    defaultConfig {
       ...
    }

    buildTypes {
        debug {
            ...
        }

        release {
            ...
        }

    }

    flavorDimensions "type"
    productFlavors {

        vanilla {
            dimension "type"
           ...
        }


        chocolate {
            dimension "type"
            ...
        }
    }

    applicationVariants.all { variant ->
        switch (variant.getName()) {
            case "vanillaDebug":
                variant.buildConfigField 'String', 'SDK_API_KEY', "\"$vanillaSdkApiKeyDebug\""
                break

            case "vanillaRelease":
                variant.buildConfigField 'String', 'SDK_API_KEY', "\"$vanillaSdkApiKeyRelease\""
                break

            case "chocolateDebug":
                variant.buildConfigField 'String', 'SDK_API_KEY', "\"$chocolateSdkApiKeyDebug\""
                break

            case "chocolateRelease":
                variant.buildConfigField 'String', 'SDK_API_KEY', "\"$chocolateSdkApiKeyRelease\""
                break

            default:
                throw new GradleException("The values are unknown for variant: ${variant.getName()}")
                break
        }
    }
}

Solution 8 - Android

productFlavors {
    vanilla {}
    chocolate {}
}

buildTypes {
		release {
			productFlavors.vanilla {
				//your configuration for vanilla flavor with release buildType
			}
		}
		debug {
			productFlavors.chocolate{
				//your configuration for chocolate flavor with debug buildType
			}
		}
	}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJesusSView Question on Stackoverflow
Solution 1 - AndroidSimasView Answer on Stackoverflow
Solution 2 - AndroidAlex KucherenkoView Answer on Stackoverflow
Solution 3 - AndroidEd GeorgeView Answer on Stackoverflow
Solution 4 - AndroidArnaud SmartFunView Answer on Stackoverflow
Solution 5 - AndroidxorgateView Answer on Stackoverflow
Solution 6 - AndroidAlok SinghView Answer on Stackoverflow
Solution 7 - AndroidKLMView Answer on Stackoverflow
Solution 8 - AndroidPahaView Answer on Stackoverflow