7

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

Carlo Moretti
  • 2,213
  • 2
  • 27
  • 41

3 Answers3

2

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.

Community
  • 1
  • 1
Carlo Moretti
  • 2,213
  • 2
  • 27
  • 41
  • 1
    Please, have a look at my solution, I think it takes the best part of your solution and makes it a bit more readable. – Alexey Bukin Apr 10 '23 at 21:29
1

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'

    }


}
Manohar
  • 22,116
  • 9
  • 108
  • 144
1

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!

Alexey Bukin
  • 137
  • 10