On this page
ProGuard was the original Java shrinker and obfuscator. On Android it has been replaced by R8, which reads ProGuard-format rules but does more. It's integrated into the build, and it converts code to DEX while optimising it. You enable it for release builds, and occasionally you have to tell it what not to touch.
What R8 does
Enabling R8
android {
buildTypes {
release {
isMinifyEnabled = true // shrink + optimize + obfuscate code
isShrinkResources = true // remove unused resources (requires minify)
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro",
)
}
}
}When you need keep rules
Most modern libraries ship their own consumer rules, so you need few custom rules. Typical cases:
- Reflection: classes or members accessed by name.
- Serialization libraries that use reflection, for example Gson models. kotlinx.serialization and Moshi codegen generate code and need far fewer rules.
- JNI: native code calling Java/Kotlin methods by name.
- Classes named in non-manifest XML or strings and loaded dynamically.
# Keep models deserialized reflectively by Gson (fields read by name)
-keep class com.example.api.legacy.model.** { <fields>; }
# Keep a class loaded by name via reflection
-keep class com.example.plugins.PdfExporter { public <init>(); }
# Keep JNI-called methods
-keepclasseswithmembernames class * { native <methods>; }Broad rules like -keep class com.example.** { *; } disable most of R8's benefits for your code. Keep the minimum: the classes or members actually accessed reflectively.
"Works in debug, crashes in release"
- Reproduce with a release-like build locally (minified, debuggable off). Or create a
stagingbuild type with minify enabled. - Read the obfuscated stack trace and decode it with the mapping file (see below).
- Look for reflection at the crash site: missing class or method, null fields after JSON parsing, or
ClassNotFoundException. - Add a narrow keep rule or switch to a codegen-based library, then re-test.
Mapping files and readable crashes
Obfuscation renames classes (a.b.c), so crash reports need the mapping file (build/outputs/mapping/release/mapping.txt) to be readable:
- Upload it with each release. Google Play Console and Crashlytics deobfuscate automatically when the mapping is provided (Gradle plugins can upload it).
- Archive mapping files per version. You can't recreate them later.
- Decode traces manually with the
retracetool when needed.
What you gain
Smaller app
Unused library code and resources are removed, often a substantial size reduction.
Faster code
Inlining, class merging and dead-code removal reduce runtime work.
Harder to reverse engineer
Obfuscation raises the effort, but it is not security. Never rely on it to hide secrets.
Common mistakes
- Never testing a minified build before release.
- Disabling minification to "fix" a crash instead of writing a targeted rule.
- Losing mapping files, so production crashes become unreadable.
- Believing obfuscation protects API keys. It doesn't. See Secure API Keys.
Frequently asked questions
Is ProGuard still used?
R8 is the default for Android builds. It understands ProGuard rule syntax, so "ProGuard rules" files still apply.
What is R8 full mode?
A more aggressive optimisation mode that is now the default in recent AGP versions. It can expose reflection issues that older modes tolerated.
Should debug builds be minified?
Usually not, for build speed and debuggability. Test a minified build on CI or in a staging build type instead.
Conclusion
R8 shrinks, optimises and obfuscates release builds by keeping only reachable code. Enable it with resource shrinking, write narrow keep rules only for reflection and JNI, test minified builds before release, and archive and upload mapping files.
Next step: go further with How to Reduce Android App Size.
Official references
๐ฑ Apps built by Yunok Tech
Real Android apps on Google Play, free to download.
Walzi4K wallpapers for lock and home screenGet it โธ
NotiVaultNotification history: recover dismissed notificationsGet it โธ
Ready to build real Android applications?
Performance work starts with understanding how Android apps are built and how they behave at runtime. Strengthen those fundamentals and the profiling tools start to make sense.
Move beyond theory and strengthen your Android development skills with Yunoktech's Android course. Learn core concepts, practical implementation, modern Android development techniques, and the reasoning behind building maintainable applications.
Explore the Android course and take your next step as an Android developer.