Changing server URL based on flavor and build type on Android Gradle

When developing an Android app I had the need of setting different server URL for each flavor, because it has a server instance for each company that uses our product. Also we use a development server and a production server, so I came to this problem, because there is no way to set a buildConfigField for each variant (company1Debug, company1Release, company2Debug, …), but only for builtType OR productFlavor.

To achieve this goal, I found on web a similar config in David Medenjak’s blog, that uses flavors with ext values to dynamically config the value of BuildConfig.URL. But I prefer to keep using buildTypes as I feel it’s semantically more accurate than having development and production flavors too.

android {
    buildTypes {
        debug {
        }
        release {
        }
    }

    productFlavors {
        company1 {
            versionNameSuffix "-company1"
            ext {
                server = [debug: "https://dev.company1.com.br", release: "https://company1.com.br"]
            }
        }
        company2 {
            versionNameSuffix "-company2"
            ext {
                server = [debug: "https://dev.company2.com.br", release: "https://company2.com.br"]
            }
        }
    }
    ...
}

I don’t have much experience with Groovy (Gradle language), but I used David’s idea to have ext values in each flavor. I created a “server” variable that is a dictionary, where the key is the build type and the value is the server URL that this variant (flavor+buildType) must use.

Then, we need a task to use the ext.server dictionary and set the buildConfigValue accordingly:

android {
    ...
    applicationVariants.all { variant ->
        def flavor = variant.productFlavors[0]
        println "Setting up server URL ${flavor.ext.server[variant.buildType.name]} for variant [${variant.name}]"
        variant.buildConfigField "String", "SERVER_URL", "\"${flavor.ext.server[variant.buildType.name]}\""
    }
}

Note that this snippet runs when Gradle is evaluating tasks, so the println “Setting up…” will be printed for all variants. It’s like generating automatically the variants configuration.

Some thoughts about Groovy that I didn’t know:
– You can’t have a defined value on root (global variable) with the same name of any ext variable. I’m rookie in Groovy, but I imagine this is related with the language structure, because of variable names conflict. For example, I had ‘def defaultLocale = “pt”‘ (for some other implementation), then I added a variable with the same name inside ext, suddenly when trying to use the variable from ext ‘flavor.ext.defaultLocale’ the Gradle runner showed error telling that there is no variable named ‘defaultLocale’ inside ext. When removing the “def defaultLocale’ it worked as expected.

Full code solution:

android {
    buildTypes {
        debug {
        }
        release {
        }
    }

    productFlavors {
        company1 {
            versionNameSuffix "-company1"
            ext {
                server = [debug: "https://dev.company1.com.br", release: "https://company1.com.br"]
            }
        }
        company2 {
            versionNameSuffix "-company2"
            ext {
                server = [debug: "https://dev.company2.com.br", release: "https://company2.com.br"]
            }
        }
    }

    applicationVariants.all { variant ->
        def flavor = variant.productFlavors[0]
        println "Setting up server URL ${flavor.ext.server[variant.buildType.name]} for variant [${variant.name}]"
        variant.buildConfigField "String", "SERVER_URL", "\"${flavor.ext.server[variant.buildType.name]}\""
    }
}

If this solution helped you in some way, or if you know a better way to achieve this, please add a comment here below.

Deixe seu comentário