R8, shrinking and keep rules

Runtime, build and Gradle Mid-level Kotlin 2.0+ API 24+ Reviewed By Best Latest Apps

Pick the fix

A release build crashes parsing JSON with Gson; debug works. Best fix?

Options
Hint 1 of 1

How does Gson find field names?

Choose an answer, then open Show answer below to check it.

Show answer

Answer: A Add narrow keep rules for the model classes, or move to a reflection-free serializer like kotlinx.serialization

Correct. R8 renamed fields that Gson finds by reflection.

Why not the others?
  • B Disable minification. Throws away size and speed gains.
  • C Keep every class in the app. Same as turning R8 off.
  • D Ship the debug build. Never.

30-second answer

R8 shrinks (removes unused code and resources), optimises (inlining, removing dead branches), and obfuscates names in release builds. It reads ProGuard-format keep rules. Crashes happen when code is reached through reflection, such as serialisation or JNI, and R8 removed or renamed it. Fix with targeted keep rules or reflection-free libraries; libraries ship their own consumer rules.

Practise saying it · 30 s. No recording, just a timer

Explain R8.

Say your answer out loud, then check which of these points you covered:

  • Shrink, optimise, obfuscate
  • Keep rules
  • Reflection breaks
  • Mapping file
  • Not a security tool

Deep dive

isMinifyEnabled = true plus isShrinkResources = true turns it on.

Full mode is the default in recent AGP versions and optimises more aggressively.

Upload the mapping file so crash stack traces can be de-obfuscated.

Obfuscation slows reverse engineering but doesn't hide secrets.

Turning on R8 in a module
android {
    buildTypes {
        release {
            isMinifyEnabled = true
            isShrinkResources = true
            proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
        }
    }
}

Common mistakes

  • -keep class com.example.** { *; } everywhere, which turns R8 off in practice.
  • Forgetting to upload mapping.txt.
  • Only testing debug builds.

Senior take & follow-ups

Explain the three jobs, then the reflection cause of crashes and narrow fixes.

Follow-up questions

Think of your answer first, then open the hint.

  1. Why are code-generated serializers R8-friendly?

    Show hint

    They don't need reflection, so R8 can see all usages.

  2. What's a consumer rule?

    Show hint

    A keep rule a library ships that applies to apps using it.

Suggest a fix if something here is wrong or out of date.