Skip to content

Configuring ProGuard

Mitchell Bryson edited this page Aug 5, 2026 · 44 revisions

By Balwinder Singh

ProGuard is a tool to help minify, obfuscate, and optimize your code. It is not only especially useful for reducing the overall size of your Android application as well as removing unused classes and methods that contribute towards the intrinsic 64k method limit of Android applications. Because of the latter issue, ProGuard is often recommended to be used both in development and production especially for larger applications.

ProGuard can be enabled by using the minifyEnabled option for any build type. If you intend to use it for production, it is highly recommended you also enable it on your development. Without fully testing ProGuard on your development builds, you may encounter unexpected crashes or situations where the app does not function as expected.

android {
   buildTypes {
      dev {
          minifyEnabled true  // enables code shrinking/obfuscation
          proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
      }
   }
}

Note: Since Android Gradle Plugin 3.4.0, R8 is the default code shrinker and replaces ProGuard. R8 understands the same -keep rules as ProGuard, so the configuration below still applies, but the standalone ProGuard tool is no longer integrated into AGP (ProGuard support was fully removed in AGP 8.0). See the AGP 3.4.0 release notes for details.

The default rules file (proguard-android-optimize.txt) ships with the Android tooling and contains baseline keep rules — for example, ensuring View getter and setter methods are not stripped. The Shrink, obfuscate, and optimize your app guide recommends proguard-android-optimize.txt because the non-optimizing proguard-android.txt variant includes -dontoptimize; AGP 9.0 dropped getDefaultProguardFile support for the non-optimizing file entirely. On modern AGP, the underlying shrinker is R8 rather than ProGuard, but R8 consumes the same rule-file syntax, so this default is still pulled in via getDefaultProguardFile(...). The proguard-rules.pro file is where you add project-specific rules.

Caveats

ProGuard can add a few minutes to your build cycle. If you can avoid using ProGuard in development, you should try to do so. Once you begin to include enough libraries that causes the 64K method limit to be reached, you either need to remove extraneous dependencies or need to consider following the instructions for supporting a higher limit by using the multidex mode. Multidex compilation also takes additional time and requires extra work to support pre-Lollipop Android versions, so the recommendation is often to use ProGuard before using Multidex.

Checking method limit

If you wish to check how close you are to the 64k limit, use the APK Analyzer by going to Build=>Analyze APK.... Click on the respective APK file and you can see a breakdown of the methods by package.

Development

When using in development/debug testing, you may wish to turn on a few settings that may add to compile time as well as make it harder to troubleshoot. For instance, to ensure that no code optimizations or obfuscation is done, the following options should be declared in your ProGuard config:

# Workaround for ProGuard not recognizing dontobfuscate
# https://speakerdeck.com/chalup/proguard
-dontobfuscate
-dontoptimize
-optimizations !code/allocation/variable

An alternative is to request only to remove unwanted code (shrink) but not obfuscate. Details here.

On modern AGP (3.4.0+), R8 is the only shrinker — the historical useProguard flag has been removed. To skip obfuscation in a specific build type, include a build-type-specific rules file that sets -dontobfuscate:

buildTypes {
  debug {
    minifyEnabled true  // shrink, but don't obfuscate (see proguard-rules-debug.pro)
    proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'),
                  'proguard-rules.pro',
                  'proguard-rules-debug.pro'
  }

  release {
    minifyEnabled true  // shrink + obfuscate (R8 default)
    proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'),
                  'proguard-rules.pro'
  }
}

Then in proguard-rules-debug.pro, add -dontobfuscate (and -dontoptimize if you also want to skip optimization). The older useProguard true/false flag is no longer recognized and will be ignored or rejected, depending on AGP version.

Third-Party Libraries

Before you start adding any ProGuard rules, check whether the libraries you use already ship their own shrinker rules — most actively maintained libraries do, and R8 picks them up automatically. Android libraries (.aar files) bundle them as a consumer-proguard-rules.pro file; plain Java/Kotlin libraries (.jar files) bundle them under META-INF/proguard/. For example, OkHttp bundles its rules inside the published JAR ("If you use OkHttp as a dependency in an Android project which uses R8 as a default compiler you don't have to do anything"), and Gson ships META-INF/proguard/gson.pro — as does Retrofit (see below). Only add hand-written rules for libraries that do not bundle any.

To see the full merged rule set R8 actually applied (defaults + your files + every library's bundled rules), add -printconfiguration ~/tmp/full-r8-config.txt to proguard-rules.pro and inspect the output file — details in the shrink-code guide.

Common ProGuard configs

Some annotation-processing and reflection-heavy libraries generate or look up classes at runtime that the shrinker cannot see, so they need explicit keep rules. This was common in the 2015-era library stack — ButterKnife (now deprecated in favor of view binding) and Square's Otto event bus (repository archived since 2018) both required the hand-written rules that used to circulate in collections like android-proguard-snippets (itself archived and predating R8). The per-library rules below are retained for legacy projects only — for anything actively maintained, prefer the library's own documentation and bundled rules.

ButterKnife (legacy)

Note: ButterKnife is deprecated — its README directs new code to view binding, which needs no keep rules. The following rules apply to ButterKnife v7.0 and are kept only for projects still carrying the library:

-keep class butterknife.** { *; }
-dontwarn butterknife.internal.**
-keep class **$$ViewBinder { *; }

-keepclasseswithmembernames class * {
    @butterknife.* <fields>;
}

-keepclasseswithmembernames class * {
    @butterknife.* <methods>;
}

Retrofit

Retrofit 2 ships bundled R8/ProGuard rules under META-INF/proguard/retrofit2.pro that are picked up automatically. If you also obfuscate models used in request/response bodies, keep their fields explicitly (see the Gson / Moshi sections of your converter library). Hand-written rules were only needed for Retrofit 1 (retrofit.* package); Retrofit 2 uses the retrofit2.* package and the bundled rules cover it without further configuration.

OkHttp3

OkHttp bundles its shrinker rules inside the published JAR, so no configuration is needed when building with R8 (the default on modern AGP). Only if you shrink with standalone ProGuard instead of R8 do you need to apply the rules from the library's okhttp3.pro file manually, plus the rules for its Okio dependency. Avoid the old blanket -keep class okhttp3.** { *; } rules that used to circulate — keeping the entire package defeats the point of shrinking.

Gson

Gson bundles baseline rules in its JAR under META-INF/proguard/gson.pro. You still need to keep the fields of your own model classes if you obfuscate, because Gson looks them up reflectively by name — see the Code obfuscation section below.

Parceler library

-keep interface org.parceler.Parcel
-keep @org.parceler.Parcel class * { *; }
-keep class **$$Parcelable { *; }

Retrolambda (legacy)

Retrolambda predates the Android toolchain's built-in Java 8+ language support — the Android Gradle Plugin has desugared lambdas and other Java 8 language features itself since AGP 3.0 — and it is no longer needed in modern builds. Projects still using it need:

-dontwarn java.lang.invoke.*

Code obfuscation

If you plan on enabling code obfuscation by removing the dontobfuscate line, make sure to check for any third-party libraries that may be performing reflection such as RxJava 1 and Gson. The classes that depend on reflection cannot be renamed because of the intrinsic need to inspect the classes. See this link for the rules that should be used for RxJava.

If you are planning to enable code obfuscation for Gson, make sure to avoid obfuscating the field names:

-keepclassmembers class com.codepath.models** { <fields>; }

Troubleshooting

If you wish to confirm whether ProGuard is preserving certain annotations or classes, you can review the .apk package that gets created to check. The first step is to download the dex2jar program and use it to decompile the Dalvik code (.dex file) to a Java archive file (.jar file). Releases are listed on the GitHub releases page.

./d2j-dex2jar.sh <.apk file>

You can also use d2j-dex2jar.bat if using a Windows machine:

d2j-dex2jar.bat <.apk file>

Running the dex2jar file directly on an APK file should convert it to a .jar file. You can download JD-GUI and open this newly created file to review the Java class files. The UI allows you to double-check whether certain annotations were removed and whether certain classes were kept in the final compilation.

Since Android Studio 3.0 release there is an APK Analyzer tool which can view dex files and also helps to debug ProGuard-related changes. See here for more details https://developer.android.com/studio/debug/apk-analyzer

References

Finding these guides helpful?

We need help from the broader community to improve these guides, add new topics and keep the topics up-to-date. See our contribution guidelines here and our topic issues list for great ways to help out.

Check these same guides through our standalone viewer for a better browsing experience and an improved search. Follow us on twitter @codepath for access to more useful Android development resources.

Clone this wiki locally