Little more about | ProGuard for Android
(I am not going into the level of How to steps for ProGuard. Instead I am jumping directly to talk about some interesting facts that I have learned about ProGuard throughout my experience. So, I assume, most of you know — How to steps about ProGuard in Android).
ProGuard Facts:
- Helps to remove unused classes, members & fields. It removes unused codes from your libraries as well. (Which means, any method or field that is not referenced anywhere will be removed by ProGuard Shrinker).
- Helps to reduce the build size by obfuscating the classes, methods, & fields with short names.
Note: Which makes the reverse engineering tough for anyone who tries to get around your code by extracting the build file.
- shrinkResources — If you have enabled it by adding
“shrinkResources true”
then it will remove the unreferenced resource files under /res directory. This will work after the code Shrinker completes it’s process, So that it can know better about the unreferenced resource files.
As per Android docs, shrinkResources will not remove the unreferenced files kept under /values folder.
What happens after ProGuard applied:
Each time you build, proguard generates three new files and places it under /build/outputs/release(or)debug/
- mapping.txt
This file contains the mapping of the renamed class, methods, & fields after Obfuscating.
2. seeds.txt
Whatever is not obfuscated as per the proguard keep rules will be listed in this file. This will be useful to make sure the specified ProGuard keep rules has any effect or not.
3. usage.txt
This file will have the code that is removed while preparing the build. Basically the unused code.
This file is helpful to cross verify, whether any unexpected code is been removed or not.
We will be always safe until things works as expected. If something happens to ProGuard enabled build, then these files will play an important role in debugging process.
NOTE: Most of the time If anything breaks only in ProGuard enabled build and the same is working fine in debug build, then there may be only two reasons.
- ProGuard rules should be cross checked.
- MultiDex related issue.
Multiple ProGuard file for multiple builds & flavours:
- We can create separate proguard-rules.pro for each flavours & each build types as well. As the Shrinking-Obfuscating takes time, it is not recommended to have a proguard-rules.pro for debug build type.
- I always have it commented in my debug build type and enable it whenever I want to test it out.
Decoding the obfuscated code:
- For making the decoding easy, we need the above mentioned mapping.txt file. As the classes, members & fields obfuscated short names are mapped in this file, it is required to decode and get on the exact code in the codebase.
- This is why Google Play Console requires mapping file for each build that we submit. It is a good practice to submit the mapping file in Google Play Console to Deobfuscate later in case of ANR or Crash report through Android Vitals.
Keep part of the code away from Shrinking:
There are certain cases, we need to write our custom proguard rules to keep the code untouched while making a build.
- JavascriptInterface — Whenever we have some methods created to communicate to WebView through JavascriptInterface, we need to let proguard know do not shrink it.
- Event bus classes — If the code is going to be invoked at runtime, then we need to let proguard know explicitly to keep it as it is. Because proguard will remove the fields, methods and classes if it is not referenced anywhere in the app.
- Starting from Android N, Request model classes are important to keep away from Obfuscation. As we use these classes to pass data over http, this should have the same field name to be used. If it is Obfuscated, then the field names will be changed as a,b,c something like that and we will not get any exception as well.
To keep the classes as it is, all of us might be familiar with adding a progaurd rule in the proguard-rules.pro file like the following,
We can also add annotation using Annotation Support Library to keep the classes and it’s members.
- If you are enabling proguard for first time, it is going to be hectic job. Enabling it is an easiest step, but immediately after enabling your build will start see crashes. It is again one time end to end testing and adding some custom rules in order to get rid of the crashes.
While adding library dependencies:
Note: If you enabled ProGuard, Always you need to add proguard rules also while adding any new library dependency. While introducing new library dependencies, check any proguard rules also added by the developer or by the community.
- Some libraries will bundle the proguard rules config with the library itself.
In such case, the libraries will have a file named consumer-proguard-rules.pro. - If it is added, then we don’t need to copy the rules to our proguard-rules.pro file anymore, while building the app, the rules will be automatically added to it from the consumer-proguard-rules.pro file.