Carlo Moretti
Carlo Moretti

Reputation: 2250

Combined BuildConfig variables in gradle flavor dimensions

In my Android application I have two flavor dimensions: "brand" (brand1, brand2) and "environment" (staging, production). I added the "environment" dimension after a while and I had previously defined some BuildConfig variables for the different brands. To be more specific, I defined the BASE_URL like this:

flavorDimensions 'brand'
productFlavors {

    brand1 {
        dimension 'brand'
        ...
        buildConfigField "String", "BASE_URL", "\"http://brand.one.api/\""
        ...
    }

    brand2 {
        dimension 'brand'
        ...
        buildConfigField "String", "BASE_URL", "\"http://brand.two.api/\""
        ...
    }
}

Now, I added the "environment" dimension and what I'd like to set are four different endpoints:

  1. Brand1-staging: "http://brand.one.staging.api/"
  2. Brand1-production: "http://brand.one.production.api/"
  3. Brand2-staging: "http://brand.two.staging.api/"
  4. Brand2-production: "http://brand.two.production.api/"

But I can't figure out how to create a BuildConfig variable for a specific combination of flavor dimensions. Is this even possible with bare gradle?

Thanks

Upvotes: 8

Views: 2367

Answers (3)

Alexey Bukin
Alexey Bukin

Reputation: 147

You can define one flavor dimension to have multiple values to choose one specific value later on. First, add those values to flavors:

productFlavors.all {
    ext.myAnalyticsUrl = [dev: null, test: null, production: null]
}

Then define all values for one flavor:

    flavor1 {
            dimension "region"
            myAnalyticsUrl = [
                    dev: *devUrl*,
                    test: *testUrl*,
                    production: *productionUrl*
            ]
    }

    dev {
            dimension "environment"
            ...
    }
    test {
            dimension "environment"
            ...
    }
    production {
            dimension "environment"
            ...
    }

Now outside of android scope:

android.applicationVariants.all { variant ->

    def regionFlavor = variant.productFlavors.find{ flavor -> flavor.getFlavorDimension() == "region" }
    def environmentFlavor = variant.productFlavors.find{ flavor -> flavor.getFlavorDimension() == "environment" }

    def analyticsUrl = regionFlavor.myAnalyticsUrl[environmentFlavor.name]
}

Hope it helps!

Upvotes: 1

Manohar
Manohar

Reputation: 23404

I did some thing like this , Having combination of flavour and brand together

flavorDimensions "brand", "server"
productFlavors {

    brand1 {
        dimension 'brand'
        ...
        buildConfigField "String", "BASE_URL_STAGING", "\"http://brand.one.staging.api/\""
        buildConfigField "String", "BASE_URL_PRODUCTION", "\"http://brand.one.production.api/\""
        ...
    }

    brand2 {
        dimension 'brand'
        ...
        buildConfigField "String", "BASE_URL_STAGING", "\"http://brand.two.staging.api/\""
        buildConfigField "String", "BASE_URL_PRODUCTION", "\"http://brand.two.production.api/\""
        ...
    }

    staging {
        dimension 'server'
        buildConfigField "String", "BASE_URL", 'BuildConfig.BASE_URL_STAGING'
    }

     production {
       dimension 'server'
       buildConfigField "String", "BASE_URL", 'BuildConfig.BASE_URL_PRODUCTION'

    }


}

Upvotes: 2

Carlo Moretti
Carlo Moretti

Reputation: 2250

After some further investigation I found a similar question here.

It seems you need to add a function to iterate build variant names and check if they match some desired name.

My problem was that actually I had 3 dimensions: "brand", "environment" and "api" (15 for production and 21 for debugging with instant run). So the variants name would look like brand1Api15StagingDebug, ..., brand2Api21ProductionRelease, ... etc.

What I needed here was some groovy regex matching combined with the linked question above. Finally the function I made looks like this:

android.applicationVariants.all { variant ->
    if (variant.getName() ==~ /brand1Api[0-9]{2}Staging.*/) {
        variant.buildConfigField "String", "BASE_URL", "\"http://brand.one.staging.api//\""
    } else if(variant.getName() ==~ /brand1Api[0-9]{2}Production.*/){
        variant.buildConfigField "String", "BASE_URL", "\"http://brand.one.production.api/\""
    } else if(variant.getName() ==~ /brand2Api[0-9]{2}Staging.*/) {
        variant.buildConfigField "String", "BASE_URL", "\"http://brand.two.staging.api//\""
    } else if(variant.getName() ==~ /brand2Api[0-9]{2}Production.*/){
        variant.buildConfigField "String", "BASE_URL", "\"http://brand.two.production.api/\""
    } else {
        throw new Exception("Unexpected variant name: " + variant.getName())
    }
}

I added an exception throw at the end of the chain so if anyone changes the variant names to ones unchecked here, the build would fail. This is important to avoid building applications with wrong endpoints.

Works like a charm.

Upvotes: 2

Related Questions