How to secure API key in android

Security cant be guaranteed 100%. One way or another it can be breakable. The questions is how much you can make it difficult to break it.

So guys today we will learn how to secure the api key in android. You will notice that if you decompile the android app the resources becomes open. There you can find the string value which is used as api key. This post basically explains a way to secure a key in android, so that it wont be disclosed after decompile. Lets go:

Open your gradle.properties file. Add your key value in this format:


ApiKey = 123456asdfzxc

# Project-wide Gradle settings.

# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.

# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html

# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx1536m

# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true

# AndroidX package structure to make it clearer which packages are bundled with the
# Android operating system, and which are packaged with your app's APK
# https://developer.android.com/topic/libraries/support-library/androidx-rn
android.useAndroidX=true
# Automatically convert third-party libraries to use AndroidX
android.enableJetifier=true

Obviously you can add as many variables as you want.

Now open your app level build.gradle file and add these lines at the top:

def API_KEY = '"' + ApiKey + '"' ?: '"Api key not found"'
def STRING = 'String'

You can change the name of this variables as per your need. Now in defaultConfig{} add this code:

each{type ->
    type.buildConfigField STRING, 'ApiKey', API_KEY
}

If you have multiple key and multiple variables, you can add it here. Total thing should be look like this:

apply plugin: 'com.android.application'

def API_KEY = '"' + ApiKey + '"' ?: '"Api key not found"'
def STRING = 'String'

android {
    compileSdkVersion 28
    defaultConfig {
        applicationId "club.tushar.secureapi"
        minSdkVersion 15
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

        each{type ->
            type.buildConfigField STRING, 'ApiKey', API_KEY
        }

    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'androidx.appcompat:appcompat:1.0.0-beta01'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.2'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test:runner:1.1.0-alpha4'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0-alpha4'
}

Now if you build your project you will notice that in BuildConfig.java class your api key is generated. You can find this class in:

app/ 
  build/
    generated/
       source/
          buildConfig/
             youPackage/
                BuildConfig

You can use this class to get the key in app from anywhere like this: BuildConfig.ApiKey. So this way you dont need to specify any key in string.xml or use any static string variable in any java class.