tezvyn:

R8: Shrinking and Obfuscating Android Code

AI-drafted, machine-checkedSource: developer.android.comadvanced
R8: Shrinking and Obfuscating Android Code

R8 is a compile-time tool that shrinks and obfuscates your Android app. It removes unused code and renames classes to reduce APK size and deter reverse-engineering.

WHY IT EXISTS: Mobile apps need to be as small and fast as possible. Large APKs lead to slower downloads and higher user abandonment. Additionally, unprotected code is easy to decompile and reverse-engineer, exposing intellectual property. R8 was created to address both problems automatically during the build process.

THE MENTAL MODEL: Think of R8 as a highly aggressive editor and translator for your compiled code. First, it reads your entire app, including all its libraries, and figures out which parts are actually reachable from your app's entry points. Everything else is "dead code" and gets deleted. Then, it takes the remaining code and "translates" the human-readable names (like calculateTotalAmount) into short, meaningless ones (like a.b.c), making the code smaller and harder to understand.

HOW IT WORKS: R8 integrates into the Android build process and runs after your Java/Kotlin code is compiled to bytecode but before it's packaged into a DEX file. It performs a static analysis of your entire codebase, starting from entry points defined in your app's manifest and any keep rules. It builds a graph of all reachable code. Any class, method, or field not in this graph is considered unused and is stripped out (shrinking). For the code that remains, it renames identifiers to short, non-descriptive names (obfuscation). Finally, it can perform further optimizations, like inlining functions.

WHEN TO USE IT: R8 is enabled by default for Android release builds (minifyEnabled true in your build.gradle file). It's essential for any production app to reduce download size, improve cold start times, and provide a basic layer of protection against reverse-engineering. It's particularly effective in projects with many large library dependencies, where a significant portion of the library code may go unused.

WHEN NOT TO USE IT: You typically disable R8 for debug builds because the shrinking and obfuscation process slows down build times. More importantly, obfuscation makes debugging nearly impossible, as stack traces will contain the short, meaningless names instead of your original method names. If a bug only occurs in a release build, you can use a mapping file generated by R8 to de-obfuscate the stack trace and find the real source of the crash.

ONE CANONICAL EXAMPLE: A common failure point is with libraries that use reflection, like the JSON serializer Gson. Gson might need to access a data class's fields or constructor by name at runtime. R8's static analysis can't see this reflective usage, so it might think the class or its default constructor is unused and remove it. The app then crashes with a NoSuchMethodError. To fix this, you add a ProGuard/R8 rule like -keep class com.example.MyDataClass { *; } to tell R8 to preserve that class and all its members.

Read the original → developer.android.com

Get five bites like this every day.

Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.