buildVariants

I’m ashamed to admit this, but, I rarely test against release variants before going to production. I build a signed APK and test that instead. And between you and I, this generally happens just before pushing to the Play Store.

Not good.

But then we hired a smart QA guy. One of the first things he asked, dumbfounded: “Why are you killing my freedom by making me manually build signed APKs every time I need to test something?”

He had a good point. Especially considering that you can add signing configurations to the build.gradle file. It’s pretty simple and Google shows you how to do it in an article called Signing Your Applications:

...
android {
    ...
    defaultConfig { ... }
    signingConfigs {
        release {
            storeFile file("myreleasekey.keystore")
            storePassword "password"
            keyAlias "MyReleaseKey"
            keyPassword "password"
        }
    }
    buildTypes {
        release {
            ...
            signingConfig signingConfigs.release
        }
    }
}
...

Easy! But then your company grows up. What was a three person team doubles in size. You hire more QA guys. You hire contractors. And then you realize: “Shit. We probably shouldn’t give everyone access to our production signing configurations.” Which is why Google gives this sage advice:

Note: Including the passwords for your release key and keystore inside the build file is not a good security practice. Alternatively, you can configure the build file to obtain these passwords from environment variables or have the build process prompt you for these passwords.

Source: http://developer.android.com/tools/publishing/app-signing.html

Easy! Except for one small thing: Every developer on your team needs to set up and manage their own environment variables. And don’t forget to configure your build server. And then do it for every single app your growing team is working on. Then–and this is the most important part–don’t forget to document everything you just did.

OK. So, there has to be an easier way. And there is.

Step one: Create a signing configuration

This is pretty simple. Create a new file in your project’s root directory. I typically name this file release.gradle, but you can name it whatever you like. In the file, add the same signingConfigs block that you would have added to your build.gradle file. It should look something like this:

android.signingConfigs {
    release {
        keyAlias 'com.example.app'
        keyPassword 'key password'
        storeFile rootProject.file('release.keystore')
        storePassword 'store password'
    }
}

Two things to point out here. First, we prepend android to signingConfigs on line 1. At build time, this file will be added to build.gradle outside of the android { [...] } block. Using android.signingConfigs will allow the android plugin to pick it up.

Second, the keystore is called release.keystore on line 5. It’s stored in the project’s root.

Since a major point of this exercise is to keep signing configurations outside of source control, don’t forget to add both release.keystore and release.gradle to .gitignore.

This bears repeating: Don’t check in release.keystore or release.gradle.

Step two: Change the build file

Now we need to change build.gradle so that release.gradle is added at build time:

apply from: rootProject.file('release.gradle')
...
android {
    ...
    buildTypes {
        release {
            ...
            signingConfig signingConfigs.release
        }
    }
}
...

Let’s compare this to Google’s suggested solution above. Since signingConfigs was moved to release.gradle, we don’t need it in build.gradle anymore. So take that out.

The key to this whole endeavor is apply from: on line 1. Here we are loading our release.gradle file as a plugin.

Script plugins can be applied from a script on the local filesystem or at a remote location. Filesystem locations are relative to the project directory, while remote script locations are specified with an HTTP URL. Multiple script plugins (of either form) can be applied to a given build.

Source: https://docs.gradle.org/current/userguide/plugins.html

This is exactly the same idea as apply plugin: 'com.android.application'. The distinction is that the Android Gradle plugin is a binary, whereas our plugin is a script.

Step three: Create a keystore

I’m not going to go into any detail here because Google adequately covers it in Signing Your Applications. The only things I’ll add are that you should put the keystore in your project’s root, and you should name it the same thing you put in release.gradle above.

Step four: Build your app

Open up the Build Variants dialog located on the bottom left of Android Studio (also available by going to View > Tool Windows > Build Variants). All the project’s modules will be listed. Select the release variant from the dropdown next to your app’s module. Build then run your app.

Epilogue

Share the release.gradle and release.keystore files with developers you trust. The developers you don’t trust will have to create their own ‘dummy’ versions of these files. It really doesn’t get any easier.

About The Author

A little biographical info.

Close