Environmental variables, API key and secret, BuildConfig and Android Studio

You wanna create an Android app that uses Twittet APIs, so yo need an API key and an API secrets only you and your apps know. Because you need these values inside you app, it’s easy and quick to write them down directly in your source code. But when you commit this code to GitHub (or any other public repo), practically you’re telling your secret keys to entire world. Seems uncommon? Unfortunately, not so much! Same for Dropbox SDK.

One simple way to avoid this bad practice is to store your values inside an environmental variable, so only your machine knows it, then read this values in some way and inject them in your code at build time.
Let’s see how to do that using Android Studio, Gradle, and BuildConfig.

First, we need to create these environmental vars. In Linux and Mac, create or edit the file ~/.gradle/gradle.properties (pay attention to the actual Gradle User Home directory position) and add some values:

#define your secret values
TwitterConsumerKeyProp=xxxxxx66666666634333333ddddddTwitterConsumerSecretProp=3nkl3sds3skmslSDF394asdk39dmasd

Second, in your module’s build.gradle file, add these lines

apply plugin: 'com.android.application'
 
//Add these lines
def TWITTER_CONSUMER_KEY = '"' + TwitterConsumerKeyProp + '"' ?: '"Define Twitter Consumer key"';def TWITTER_CONSUMER_SECRET = '"' + TwitterConsumerSecretProp + '"' ?: '"Define Twitter Consumer secret"';
 
android.buildTypes.each { type ->
    type.buildConfigField 'String', 'TWITTER_CONSUMER_KEY', TWITTER_CONSUMER_KEY    type.buildConfigField 'String', 'TWITTER_CONSUMER_SECRET', TWITTER_CONSUMER_SECRET
}

Please note the “TwitterConsumerKeyProp” and “TwitterConsumerSecretProp” have to be the same in both Gradle settings file and Gradle build file.
Finally, to use these values in your code, filled at runtime by Gradle in the build script for you, simply use:

ConfigurationBuilder cb = new ConfigurationBuilder()
    .setDebugEnabled(BuildConfig.DEBUG)
    .setApplicationOnlyAuthEnabled(true)
    .setOAuthConsumerKey(BuildConfig.TWITTER_CONSUMER_KEY)    .setOAuthConsumerSecret(BuildConfig.TWITTER_CONSUMER_SECRET);

That’s all, then it’s up to you how to create more elaborated configurations. For example, you can have different values based on different android.buildTypes types, or the gradle settings file in a common network folder used by the entire team or…

7 Comments

  1. Hi Alfredo, thanks for this post. Working on Windows, I created a gradle.properties file in c:users\.gradle
    Worked like a dream.

  2. Sorry for that, a bit got formatted out when posting. The correct path is c:usersme.gradlegradle.properties

  3. It’s not working for me, i’m try in different way, but get error:

    Error:(26, 0) No signature of method: static com.android.build.gradle.internal.dsl.BuildType.buildConfigField() is applicable for argument types: (java.lang.String, java.lang.String, java.lang.String) values: [String, API_KEY, LuzzaCqLceob5Xwz18xw]
    Possible solutions: buildConfigField(java.lang.String, java.lang.String, java.lang.String), getBuildConfigFields()
    Open File

  4. What if I have multiple projects with different TwitterConsumerKeyProp ?

    Should I use different names in the same ~\gradle.properties file like:
    App1TwitterConsumerKeyProp=aaaaa66666666634333333dddddd
    App2TwitterConsumerKeyProp=bbbbb66666666634333333dddddd
    App2TwitterConsumerKeyProp=ccccc66666666634333333dddddd

    or is there a way to define them in different files?

    Thank you

  5. Really good article. Its really good to store constant credentials in our own application without prior information providing to outside world. Thanks for sharing. :)

Leave a Reply