I very rarely need to touch pro guard rules so when I do I always struggle with the most basics. Here’s my reference guide to quickly get back up to speed.
Proguard
Proguard is a tool used to shrink and obfuscate code. The two most basic ways it achieves this are removing unused code and renaming classes and methods.
Note: modern android actually uses a tool called R8 under the hood to do the shrinking/obfuscation but R8 still relies on and is configured by the same proguard files which is why we still have files like proguard-rules.pro
in our android projects.
Enabling Proguard
To enable code shrinking and obfuscation (and other R8 code optimisations) we set the minifyEnabled
flag to true in you app modules build.gradle
file.
android {
buildTypes {
release {
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
...
}
}
...
}
Code language: JavaScript (javascript)
In most cases when you see minifyEnabled true
you will also see shrinkResources true
. When shrink resources is set the build process will remove all unused resources from the project (eg images or strings) which also helps reduce the app size.
The proguardFiles
line tells proguard/R8 where to find the configuration settings.
The first part, getDefaultProguardFile'proguard-android-optimize.txt')
is the default android configuration that contains rules every android project needs such as ensuring no activity or classes referenced from xml get removed.
The second part, 'proguard-rules.pro'
is the configuration file specific to our project and is where you would add any custom rules you require for your project. Note that you can change the file name to anything you want so long as it matches what you specify here.
Proguard -keep rules
Proguard removes classes and members that aren’t used in order to shrink the app size but it doesn’t understand every scenario so sometimes we have to specify rules to ensure proguard doesn’t remove or obfuscate classes and members we need. For example when using gson
to serialise json we need to keep the field names of our models because gson
is using those names for the field names in json.
Here are the basic keep rules you’re likely to see and use in your proguard-rules.pro
files.
First the most basic keep rule
-keep class com.example.MyClass
Code language: Gradle (gradle)
Keeps (doesn’t remove or rename) the class MyClass
.
-keep class com.example.MyClass {*;}
Code language: Gradle (gradle)
Keeps the class and all members (fields/methods etc).
-keep com.example.* {*;}
Code language: Gradle (gradle)
Keeps all classes and their members that are in the com.example
directory. I.e. will keep com.example.MyClass
but will not keep com.example.models.MyModelClass
because that is in a sub directory.
-keep com.example.** {*;}
Code language: Gradle (gradle)
Keeps all classes and their members in the com.example
package and all sub directories. So in this case both com.example.MyClass
and com.example.models.MyModelClass
will be kept.
Note: Be careful using such a broad rule as this because you loose the whole advantage of using proguard.
There is a lot more you can do with proguard, e.g. -keepClassMembers
, -keepNames
or keeping classes that contain a particular method signature. See the references at the bottom of the page for some good places to get started with understanding these more advanced features.
Proguard with modules
When you create a separate module (android library) in your project you should place your pro guard rules in the consumer pro guard file, by default called consumer-rules.pro
. These consumer rules get automatically applied when the consuming application performs the proguard step during build, the consuming application being your app module and potentially multiple different apps. By using proguard in this way it will be able to remove any classes in the module that aren’t used by the app being built (whereas if we used the normal proguard file we would have to keep all classes because we don’t know which ones are used by the app).
To use this file you need to add consumerProguardFiles "consumer-rules.pro"
to your separate modules build.gradle
file. consumer-rules.pro
is the default filename but you can specify any name so long as the file matches what’s set for consumerProguardFiles
.
You should also disable the standard proguard rules by ensuring minifyEnabled = false
in the separate modules build.gradle
file. These setup steps are already done for you when creating a separate android library module in android studio.
Proguard with libraries
When including a new dependency in your project you should check if they specify any proguard rules that you need to add. Often this won’t be necessary but when it is the required proguard rules are usually included in the setup steps in their readme, e.g. for retrofit
Debugging Proguard issues
Using proguard takes a long time in the build process so in a standard android project it is used for production builds only and not applied to debug builds. In order to test and debug with the full proguard rules applied it is useful to setup a new debug build variant that matches what is applied to the production variant. e.g. in build.gradle
of your app module:
buildTypes {
debugMinified {
initWith debug
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
matchingFallbacks = ['debug']
}
}
Code language: Gradle (gradle)
De-obfuscation files
If you start seeing crazy stack traces in crash reports such as lc.f$c.i(
MyClass.kt:797)
and your MyClass
file only has 132 lines it’s because proguard has obfuscated your files. In order to get a readable stack trace you need to upload the proguard mapping file to google play. These files tell the play store how to decode the crazy names in the stack trace back to their original names so you can track down that pesky crash.
To learn how to upload mapping files see https://support.google.com/googleplay/android-developer/answer/9848633?hl=en
References
Proguard tips and examples: https://medium.com/androiddevelopers/practical-proguard-rules-examples-5640a3907dc9
Different keep options: https://jebware.com/blog/?p=418
Consumer-rules: https://medium.com/android-news/proguard-r8-in-the-world-of-modularity-f599650b4553
Android code shrinking documentation: https://developer.android.com/studio/build/shrink-code
I don’t use comments on my site but you can reply on Mastodon: https://fosstodon.org/@MonkeyMatt/109397496304875562