Skip to content

Android ProGuard/R8 Obfuscation Error Fix

DodaTech Updated 2026-06-24 4 min read

In this tutorial, you'll learn about Android ProGuard/R8 Obfuscation Error Fix. We cover key concepts, practical examples, and best practices to help you understand and apply this topic effectively.

Your Android build fails with Caused by: java.lang.ClassNotFoundException in release builds or Warning: there were 10 unresolved references to classes or interfaces — ProGuard or R8 obfuscation removed classes or methods that are accessed via Reflection or Serialization.

Step-by-Step Fix

1. Enable R8 with full debug info

// android/app/build.gradle
android {
    buildTypes {
        release {
            // Wrong: R8 with no keep rules (strips too much)
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'

            // Right: enable R8 with proper configuration
            minifyEnabled true
            shrinkResources true
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'

            // Add debug info for release builds (helps with crash reporting)
            buildConfigField "boolean", "ENABLE_CRASH_REPORTING", "true"
        }
        debug {
            minifyEnabled false
        }
    }
}

2. Add Gson/Moshi Serialization keep rules

# Wrong: no keep rules for serialization
# Model classes are stripped by ProGuard/R8

# Right: keep data classes used with Gson
-keepattributes Signature
-keepattributes *Annotation*
-keep class com.myapp.data.** { *; }

# Keep classes used with Gson serialization
-keepclassmembers class com.myapp.data.** {
    <fields>;
}
-keep class com.google.gson.** { *; }
-keepattributes EnclosingMethod

3. Add Retrofit keep rules

# Wrong: Retrofit interfaces are stripped
# Right: keep Retrofit service interfaces

-keep,allowobfuscation interface com.myapp.network.** {
    <methods>;
}

# Retrofit rules
-keep class retrofit2.** { *; }
-keepclasseswithmembers class * {
    @retrofit2.http.* <methods>;
}

# OkHttp rules
-keep class okhttp3.** { *; }
-keep interface okhttp3.** { *; }
-dontwarn okhttp3.**

4. Keep model classes with @Keep annotation

// Wrong: no annotation to protect the class
public class User {
    private String id;
    private String name;
    // Getters and setters
}

// Right: use @Keep annotation to prevent obfuscation
import androidx.annotation.Keep;

@Keep
public class User {
    private String id;
    private String name;

    @Keep
    public User() {}  // Keep default constructor for serialization

    public String getId() { return id; }
    public String getName() { return name; }
}

5. Handle Enum obfuscation

# Wrong: enums are obfuscated and break switch statements

# Right: keep enums and their values
-keep enum com.myapp.data.**
-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}

6. Log the full R8 mapping for debugging

// android/app/build.gradle
android {
    buildTypes {
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'

            // Generate mapping file for crash deobfuscation
            proguardFile 'proguard-rules.pro'
            // The mapping file is at build/outputs/mapping/release/mapping.txt
        }
    }
}

7. Use a comprehensive proguard-rules.pro

# Base rules
-keepattributes SourceFile,LineNumberTable
-keepattributes *Annotation*, InnerClasses
-dontnote android.net.http.*
-dontnote org.apache.http.**

# App specific
-keep class com.myapp.BaseApplication { *; }
-keep class com.myapp.BuildConfig { *; }

# Firebase
-keep class com.google.firebase.** { *; }

# Glide
-keep public class * implements com.bumptech.glide.module.GlideModule
-keep class com.bumptech.glide.** { *; }

# Room
-keep class * extends androidx.room.RoomDatabase
-keep @androidx.room.Entity class *
-dontwarn androidx.room.paging.**

Prevention

  • Test release builds with ProGuard/R8 enabled before deploying to Play Store.
  • Use @Keep annotation on data classes, models, and classes accessed via Reflection.
  • Keep a mapping file (mapping.txt) from each release build for crash deobfuscation.
  • Add keep rules for all third-party libraries as documented in their setup guides.
  • Use -whyareyoukeeping or -whyareyounotkeeping rules to debug specific issues.

Common Mistakes with proguard error

  1. Using head and tail instead of pattern matching, causing runtime errors on empty lists
  2. Forgetting that lazy evaluation defers computation until the value is forced, causing space leaks with unevaluated thunks
  3. Using return to exit a function early instead of wrapping a pure value in the monad

These mistakes appear frequently in real-world ANDROID code. DodaTech's contributors have identified these patterns through analysis of open-source projects and production systems.

Practice Exercise

Write a pure function that safely divides two integers using Maybe, then test it with edge cases like division by zero and negative numbers.

This exercise reinforces the concepts covered in this guide. Try implementing it before checking online solutions.

FAQ

What is the difference between ProGuard and R8?

R8 is Google's replacement for ProGuard that offers better performance and supports Kotlin-specific optimizations. ProGuard is the older open-source optimizer. Both minify and obfuscate code. |||How do I debug a crash caused by obfuscation? Upload the mapping.txt file from build/outputs/mapping/release/ to Firebase or your crash reporting tool. Use the retrace.sh tool with the mapping file to deobfuscate stack traces. |||Can I disable obfuscation but keep Minification? Yes, set useProguard false and minifyEnabled true in your build.gradle. This enables shrinking without obfuscation, making stack traces readable while still reducing APK size.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro