Kevin Schultz

Mobile Engineering

ProGuard With Gradle

The official Android developer documentation has a nice overview of why you should use Proguard when building your application. However, that documentation does not yet cover the new Gradle build system.

Android’s Gradle build system has had a built-in task for running ProGuard for a while now. The Android Tools site has a small section about ProGuard, but it misses a few crucial details.

The first step is to enable the ProGuard task on a particular buildType by setting the minifyEnabled flag. By default, ProGuard is disabled on the debug build type. I personally make this explicit, but it is not strictly necessary.

Next, use one of the two default Android files as the basis of your ProGuard configuration. Depending on the age of your Android project, you may have a stale base configuration file. I found the newer files work much better. The safest option is the non-optimized file, I have had trouble with the optimized one in the past.

Base ProGuard files
1
2
3
proguardFile getDefaultProguardFile('proguard-android.txt')
// or
proguardFile getDefaultProguardFile('proguard-android-optimized.txt')

Next add the required ProGuard rules for the project dependencies. I personally prefer to keep each library’s rules in a separate file so that I can re-use the ProGuard configurations between projects easily. The simplest location for these files is in the top level of the project next to the build.gradle file. I have started a collection of ProGuard files for common libraries on GitHub. Using this approach also untangles the ProGuard configuration when removing unused dependencies from a project.

Dependency ProGuard Rules
1
2
proguardFile 'proguard-google-play-services.txt'
proguardFile 'proguard-gson.txt'

Finally, add one ProGuard configuration file that is a catch-all for the truly project specific rules. Common candidates are any classes that require GSON for parsing (or reflection in general). See the ProGuard manual for more detail on actual configuration rules.

Example proguard-project.txt
1
2
-keep class com.kevinrschultz.sample.BuildConfig { *; }
-keep class com.kevinrschultz.sample.model.User { *; }

When you put it all together, a basic ProGuard configuration looks like the code sample below.

Example Gradle ProGuard Configuration
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
android {

    ...

    buildTypes {
        debug {
            debuggable true
            minifyEnabled false
        }

        release {
            debuggable false
            minifyEnabled true
            proguardFile 'proguard-bugsense.txt'
            proguardFile 'proguard-eventbus.txt'
            proguardFile 'proguard-google-play-services.txt'
            proguardFile 'proguard-gson.txt'
            proguardFile 'proguard-project.txt'
            proguardFile getDefaultProguardFile('proguard-android.txt')
        }

    }
}

One final note, make sure to keep the mapping.txt file produced by each build to de-obfuscate stack traces. It is located in the build/{appname}/proguard/{buildvariant} folder. You will have to upload the mapping.txt file to your crash reporter (BugSense, Crashlytics, etc). This file changes every time the build is run, so make sure you are careful with versioning the build artifacts (APK & mapping.txt).