Mobile Development 23 min read

Android Code Obfuscation: ProGuard, R8, D8 and Build Process Deep Dive

This article provides a comprehensive guide to Android code obfuscation, covering the purpose and benefits of minification, detailed ProGuard/R8 configuration, resource shrinking, desugaring, D8/R8 internals, custom obfuscation dictionaries, and modular ProGuard rules for multi‑module projects.

Sohu Tech Products
Sohu Tech Products
Sohu Tech Products
Android Code Obfuscation: ProGuard, R8, D8 and Build Process Deep Dive

0x0 Introduction

Code obfuscation is a common practice in Android development; before releasing a production APK you should enable minification, which shortens class, method and field names, reduces APK size, and can improve runtime performance.

0x1 Daily Usage

Enable minifyEnabled true in the app module's build.gradle and add a proguard-rules.pro file. A simple example project demonstrates a Kotlin activity that loads a URL, then builds a release APK with gradle assemble . After building, the debug APK can be inspected with jadx-gui , showing readable code, while the release APK shows obfuscated class names such as abcd . Loading the mapping file ( mapping.txt ) restores original names.

0x2 Obfuscation Rule Details

Obfuscation rules are additive and can come from multiple sources: the module's proguard-rules.pro , the default proguard-android-optimize.txt , AAPT generated rules, and library‑specific rules ( /proguard.txt , /META-INF/proguard/ ). To view the full merged configuration, add -printconfiguration ./build/outputs/mapping/full-config.txt to the main proguard-rules.pro .

Common rule syntax includes:

-keep class cn.coderpig.myapp.example.Test { *; }
-keep class cn.coderpig.myapp* { *; }
-keep class **.*entity*.** { *; }
-keepclassmembers class **.R$* { public static
; }

Important notes: do not obfuscate JNI methods, reflection‑used classes, Android components, WebView JS interfaces, annotation classes, serialization classes, or third‑party SDKs unless explicitly required.

0x3 From Desugaring to ProGuard, DX, D8, R8

The Android runtime evolved from Dalvik (register‑based .dex ) to ART (AOT compilation). Modern toolchains use D8 for desugaring and converting .class files to .dex , while R8 performs code shrinking, optimization, and obfuscation in a single step, replacing the older ProGuard + DX workflow.

Key steps:

Desugaring transforms Java 8+ language features into bytecode compatible with older Android runtimes.

D8 compiles the desugared bytecode to .dex files.

R8 (or ProGuard) then applies shrinking, optimization, and obfuscation based on the provided rules.

0x4 ProGuard vs R8

R8 is the default since AGP 3.4.0, offering faster builds, better Kotlin support, and full compatibility with existing ProGuard rules. To force ProGuard, set android.enableR8=false and android.enableR8.libraries=false in gradle.properties , and add -ignorewarnings to the rules if needed.

Both tools generate output files in build/outputs/mapping/release such as mapping.txt , seeds.txt , usage.txt , and resources.txt .

0x5 What D8 Does

D8 performs desugaring and converts .class bytecode to .dex . The process is orchestrated by Gradle tasks like transformClassesWithDexBuilderForDebug , transformDexArchiveWithExternalLibsDexMergerForDebug , and transformDexArchiveWithDexMergerForDebug . The D8 command line options are documented at the Android developer site.

0x6 What R8 Does

R8 creates three optional transforms: Java code shrinking, resource shrinking, and dex splitting (for multidex). The Java shrinking step removes unused code, performs optimizations, and applies obfuscation according to the ProGuard configuration. Resource shrinking rewrites the .ap_ archive, removing unused resources and generating a resources.txt report. Dex splitting divides the final dex files when multidex is enabled.

0x7 Custom Obfuscation Dictionary

You can supply a custom dictionary file (e.g., dictionary ) and reference it in proguard-rules.pro with:

-obfuscationdictionary ./dictionary
-classobfuscationdictionary ./dictionary
-packageobfuscationdictionary ./dictionary

Building the release APK and inspecting it with jadx will show class names replaced by characters from the dictionary.

0x8 Modular Obfuscation

Obfuscation is controlled by the app module; library modules can provide their own consumerProguardFiles or share common rules via the app's proguard-rules.pro . When removing a module, remember to delete its associated rules.

Conclusion

The Android build pipeline—from Gradle configuration, through desugaring, D8 conversion, R8 shrinking/obfuscation, to resource compression—is complex but manageable once each step is understood. Custom dictionaries and modular rule management further empower developers to fine‑tune their APK size and security.

mobile developmentAndroidR8Gradlecode obfuscationProGuardD8
Sohu Tech Products
Written by

Sohu Tech Products

A knowledge-sharing platform for Sohu's technology products. As a leading Chinese internet brand with media, video, search, and gaming services and over 700 million users, Sohu continuously drives tech innovation and practice. We’ll share practical insights and tech news here.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.