19 April

Creating BuildVariants with Gradle

When creating an application, sometimes at some point we want to get several versions of our application that differ in some more or less important details. To easily obtain different versions of your application, just make a few changes in Gradle.

Android Studio and Gradle support creating different versions of applications by adding more BuildTypes and ProductFlavors. But before we talk about it more, we should mention what “different” versions we mean. For example, we might want to get a version that differs in applicationId, minimum supported sdk version, has a signature or not. Our versions may also differ internally in terms of used parameters, such as the url for the API.

BuildTypes

When creating a project in AndroidStudio in Gradle we have 2 default BuildTypes: debug and release. These types refer to a number of settings for building a project. It is also a good place to define things, e.g. location and name of generated builds:

buildTypes {
        release {
            applicationVariants.all { variant ->
                variant.outputs.each { output ->
                    def file = output.outputFile
                    output.outputFile = new File(file.parent, "releaseBuildHeader" + defaultConfig.versionName + ".apk")
                }
            }
        }

        debug { (...) }
}
ProductFlavors

ProductFlavors, in turn, allows us to define the parameters used in the application code, for example, we can distinguish between minSdkVersion. The example below shows how to differentiate between versions using various url addresses to the API, of which one requires a certificate and the other does not:

productFlavors {
        live {
            applicationId 'pl.holdapp.testapp'
            buildConfigField 'String', 'API_URL', '"https://some-api-url.com"'
            buildConfigField 'boolean', 'NEED_CERTIFICATE', "false"
        }
        dev {
            applicationId 'pl.holdapp.testapp.dev'
            buildConfigField 'String', 'API_URL', '"https://another-api-url.com"'
            buildConfigField 'boolean', 'NEED_CERTIFICATE', "true"
        }
    }

As you can see, here we use buildConfigField, where we specify 'defined constant type', 'name' and 'value' respectively. Okay, but there's still a question of how to use this value within our application code? As it turns out, it is just as easy. It's enough to reference the constant in the code as follows:

if (BuildConfig.NEED_CERTIFICATE)
            okHttpBuilder.sslSocketFactory((sslContext.getSocketFactory()));

With BuildTypes and ProductFlavors as we set them, after synchronizing the project (introducing the changes made in Gradle), we now have four BuildVariants:

Conclusions

As a result, we can freely switch between variants to create the right version of an application with basically no workload. This is a very practical and helpful solution that can save you a lot of valuable developer time. ;)