Using Gradle has many cool features, the one that I really like is the ability to change configurations based on build type (release or debug).

Background

One of the headaches of building Internet enabled applications is pointing your application to a different API service based on the stage of development. For instance, for a QA build of a product I have had the need to point an application to a QA API Instance, or during initial development of APIs, to a development server. There are many ways to accomplish this, from reading a configuration file loaded on the device or changing a string resource to a new host. But I have started using my Gradle configurations to point my Android applications to different API host servers.

Gradle

Common Configuration Switching

A common method for switching host configurations is a complicate if statements:

if (BuildConfig.Debug) {
… use host A
} else {
… use host B
}

Of course, using this approach has many downsides, one of which is ugly “if” statements scattered through out your code. And when you have multiple flavors of the product with different debug versus release host API’s, it can get really ugly.

Another method is to use string resources that are loaded per flavor of build. A debug resource string file could contain Host A URL, which Staging flavor could contain Host B URL. This keeps the complicated if statements to a simple string load. But now your URL’s are in different files, and maintaining the multiple files always leads to ‘which is getting loaded’, ‘what is the current host’, etc.

This is where Gradle configurations can help clean up the code, and to me the main benefit is there is one source of truth of the host configuration settings.

Gradle Setup

Here are the basic steps for setting up Gradle configurations. Within the application build.gradle file use the buildConfigField attribute. The build system will generate a special class called BuildConfig and adds these new fields.

Ex:
buildConfigField ‘String’, ‘hostAPI’, ‘”https://somehosst.com/rest/api”‘

To specify different values for Release and Debug build types, add the different config fields within the buildTypes.

buildTypes {
release {
..
buildConfigField 'String', 'hostAPI', '"https://prod.somehost.com/rest/api"'
..
}</pre>
debug {
..
buildConfigField 'String', 'hostAPI', '"https://dev.somehost.com/rest/api"'
..
}
}

Then to reference the value within your code is as simple as BuildConfig.hostAPI.

Example:

Log.d(“Application”, “The host is “ + BuildConfig.hostAPI );

Output
For Release build is

The host is https://prod.somehost.com/rest/api

For Debug build is

The host is https://dev.somehost.com/rest/api

Quick note: the configuration name is case sensitive. If you specify hostAPI within your Gradle file, then use BuildConfig.hostAPI. If you specify Host, then of course it is BuildConfig.Host.

Flavors of Build Config

Let’s take this a step further. Say you have different Flavors of builds, flavorFoo and flavorBar. Here is how you could setup the different flavors to use specific hosts.

productFlavors {

flavorFoo {
buildConfigField 'String', 'hostAPI’, '"http://somehost/foo"' dimension “foo”
}

flavorBar {
buildConfigField 'String', 'hostAPI', '"http://somehost/bar"' dimension “bar”
}

}

And of course, in your code you would reference the value by BuildConfig.hostAPI.

Example:

Log.d(“Application”, “The host is “ + BuildConfig.hostAPI + “ for flavor “ + BuildConfig.FLAVOR );

Output
For Flavor Foo

The host is http://somehost/foo for flavor foo

For Flavor Bar

The host is http://somehost/bar for flavor bar

Now you have multiple flavors of your product, wonderful. Let’s take this another step further, and you need to point your debug build of flavor ‘foo’ to a development host. Here is how, using the buildType.

productFlavors {

flavorFoo {

buildConfigField 'String', 'hostAPI’, '"http://somehost/foo"' dimension “foo”

buildTypes {
debug {
buildConfigField 'String', 'hostAPI', '"http://somedevelopmenthost:3030"'
}
}
}

flavorBar {
buildConfigField 'String', 'hostAPI', '"http://somehost/bar"' dimension “bar”
}

}

Example:

Log.d(“Application”, “The host is “ + BuildConfig.hostAPI + “ for flavor “ + BuildConfig.FLAVOR);

Output
For Flavor Foo Release

The host is http://somehost/foo for flavor foo

For Flavor Foo Debug

The host is http://somedevelopmenthost:3030 for flavor foo

For Flavor Bar

The host is http://somehost/bar for flavor bar

Conclusion

The main reason I lean toward placing API host references within my Gradle file is it gives me one place to reference the list of hosts used by my application. I do not have to look in multiple configurations files or look at the string resource of the development versus production flavors. One central place of reference. There are no complicated if statements to switch between debug or release builds, the build process sets what I need.

There is a downside to this approach, each time you change the values within the Gradle file, you have to sync your project with Gradle, which for larger projects, might take a few minutes. But you can always use those ‘sync’ times to get another cup of coffee.

Happy Coding.

Related Posts

Brock Davis

Brock Davis

Technical Project Manager - More than a decade of experience in leading engineering teams in the design and implementation of applications, applying technical knowledge to solve complex problems, building highly scalable online web applications, and seeking client focused solutions, while mentoring and training junior engineers.