The requirement may change in 3.3.0.0 and later — check the release notes for your sealing version before applying these rules.
When Dex Protection is enabled, DoveRunner identifies your business code by locating packages declared in the APK/AAB manifest. If ProGuard or R8 has repackaged those classes elsewhere, DoveRunner may not be able to find them — and they won't be obfuscated.
The fix is a single rule that tells ProGuard/R8 to preserve your package structure while still obfuscating class and member names.
Required Rule
Add the following to your proguard-rules.pro, replacing com.example with your app's base package name:
-keeppackagenames 'com.example.**'This preserves the package path as-is while class, method, and field names are still obfuscated normally.
| Original | After obfuscation |
|---|---|
com.example.api.UserService.fetchUser() | com.example.api.a.b() |
com.example.model.Profile.userName | com.example.model.c.a |
Rules to Avoid
The following rules relocate or flatten package paths and will break the package structure that DoveRunner relies on. Avoid using them alongside -keeppackagenames:
-repackageclasses 'x'
-flattenpackagehierarchy 'x'These rules are not applied by R8 by default and are not included in
proguard-android-optimize.txt. You are safe unless you or a third-party library explicitly added them. Check your external library consumer-rules if you are unsure.Library Compatibility
-keeppackagenames only preserves package paths — class and member names are still obfuscated. Some libraries require additional ProGuard rules to function correctly at runtime (for example, libraries that rely on reflection or serialization).
If a library you use provides its own required ProGuard rules, apply them as-is. -keeppackagenames does not interfere with standard -keep rules for specific classes or members, so there is no conflict as long as you avoid the package-relocating rules listed above (-repackageclasses, -flattenpackagehierarchy).
Verifying the Setup
After a release build, open the mapping file and confirm that package paths are preserved while class names are obfuscated:
app/build/outputs/mapping/release/mapping.txtExpected output:
com.example.api.UserService - com.example.api.a:
void fetchUser() - b
com.example.model.Profile - com.example.model.c:
java.lang.String userName - aThe package path (com.example.api, com.example.model) must be intact, and class/member names must be replaced with short symbols.
AGP Version Compatibility
-keeppackagenames works correctly across all AGP versions. The main difference is how aggressively R8 optimizes in each mode.
| AGP Version | R8 Mode | Notes |
|---|---|---|
| < 3.4 | ProGuard | Works normally |
| 3.4 – 6.x | R8 compat mode | Existing rules work mostly as-is |
| 7.0 – 7.x | R8 full mode (opt-in) | Enable via android.enableR8.fullMode=true |
| 8.0+ | R8 full mode (default) | More aggressive: class merging, inlining |
| 9.x+ | R8 full mode + extra optimizations | See official release notes |
In R8 full mode, some classes inside a preserved package may disappear due to merging or inlining. This is expected behavior and does not affect DoveRunner's ability to identify and obfuscate the package — as long as surviving classes retain their package paths.