Android ProGuard/R8 Obfuscation Error Fix
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
@Keepannotation 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
-whyareyoukeepingor-whyareyounotkeepingrules to debug specific issues.
Common Mistakes with proguard error
- Using
headandtailinstead of pattern matching, causing runtime errors on empty lists - Forgetting that lazy evaluation defers computation until the value is forced, causing space leaks with unevaluated thunks
- Using
returnto 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
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro