Cách khắc phục nhanhBản release của bạn có thể bị crash vì R8 đã loại bỏ các đoạn mã mà nó cho là "mã chết", mặc dù ứng dụng của bạn cần nó lúc runtime để thực hiện reflection hoặc parse JSON. Để ngăn chặn điều này, hãy thêm một quy tắc keep rule vào tệp proguard-rules.pro của bạn:
-keep class com.example.MyClass { *; }
Nếu bạn có cả một package chứa các data model (như dành cho GSON hoặc Moshi), hãy giữ lại toàn bộ thư mục đó:
-keep class com.example.models.** { *; }
Xóa cache bản build bằng lệnh Clean Project trước khi tạo APK hoặc App Bundle tiếp theo để đảm bảo các quy tắc được áp dụng.
Tại sao R8 lại làm hỏng mã đang hoạt độngKhi bạn bật isMinifyEnabled = true, R8 (người kế nhiệm của ProGuard) cố gắng thu nhỏ APK của bạn—thường giảm kích thước từ 30% đến 50%. Nó bắt đầu tại các "điểm truy cập" (entry points), như các Activity được liệt kê trong Manifest, và lần theo đường dẫn mã để xem cái gì thực sự được sử dụng.
Các vấn đề bắt đầu với Reflection. Nếu bạn tham chiếu một class bằng một String (ví dụ: Class.forName("MyClass")), R8 không thể "thấy" kết nối đó. Nó giả định class đó không được sử dụng và xóa nó đi. Trong các trường hợp khác, R8 có thể đổi tên MyClass thành a.b để tiết kiệm dung lượng, nhưng thư viện JSON của bạn vẫn tìm kiếm tên ban đầu, dẫn đến lỗi ClassNotFoundException.
Các trường hợp thường xảy ra- JSON Serialization: GSON và Moshi sử dụng reflection để map các key JSON vào các field Kotlin/Java của bạn.- JNI & Native Code: Mã C++ thường gọi các phương thức Java bằng các chuỗi class hardcode mà R8 không theo dõi.- WebView Interfaces: Bất kỳ class Java nào được expose cho JavaScript thông qua @JavascriptInterface.- Dependency Injection: Các thư viện như Dagger hoặc Hilt thường xử lý việc này, nhưng các cấu hình tùy chỉnh có thể làm mất mã được tạo ra.## Cách khắc phục### 1. Sử dụng Annotation @KeepThay vì chỉnh sửa các tệp văn bản, bạn có thể sử dụng annotation @Keep từ thư viện AndroidX. Đây là cách dễ đọc nhất để bảo vệ một class hoặc phương thức duy nhất.
@Keep
class UserProfile(
val username: String,
val email: String
)
2. Cập nhật proguard-rules.proĐối với các thư viện bên thứ ba mà bạn không thể thêm annotation, hãy sử dụng app/proguard-rules.pro. Dưới đây là ba pattern phổ biến:
Bảo vệ một bridge class cụ thể:
-keep class com.example.app.NativeBridge { *; }
Giữ lại tất cả các model (thiết yếu cho phản hồi API):
-keep class com.example.app.models.** { *; }
Giữ lại bất kỳ class nào thực thi một interface:
-keep class * implements com.example.app.MyPlugin { *; }
3. Giải mã Stack Trace đã bị làm xáo trộn (Obfuscated)Nếu log crash của bạn hiển thị một cái tên khó hiểu như ClassNotFoundException: a.b.c, bạn cần tệp mapping để dịch nó ngược lại thành class mà con người có thể đọc được. Tệp này được tạo ra mỗi khi bạn build.
Kiểm tra tại: app/build/outputs/mapping/release/mapping.txt
Tìm kiếm a.b.c trong tệp văn bản đó. Khi bạn tìm thấy tên gốc, hãy thêm nó vào keep rules của bạn.

