We may have used ProGuard in our project when developing Android applications. In this blog, all of the features and how to use ProGuard effectively on Android.
What is ProGuard?
ProGuard is a free java tool in Android, which helps us to do the following:
- Shrink(Minify) the code: Remove unused code in the project.
- Obfuscate the code: Rename the names of class, fields, etc.
- Optimize the code: Do things like inlining the functions.
In short, ProGuard has the following impact on our project:
- It reduces the size of the application.
- It removes the unused classes and methods that contribute to the 64K method count limit of an Android application.
- It makes the application difficult to reverse engineer by obfuscating the code.
How to use it in our project?
To enable Proguard in your project, in the app’s build.gradle add,
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
Here, we have minfyEnabled as true. It activates the proguard which takes from the file,
proguard-android.txt
It is under the release block, which means that it will only be applied to the release of the build we generate.
But it can be too much sometimes when the proguard removes too much code and it might break your code for the flow.
So, configuring the code we have to add some custom rules to make sure we remove the set of code from obfuscating. We can fix this by writing out custom rules in our proguard and it will respect while generating the build.
Now, let us see how we can write customs rules in proguard.
1. Keeping class files
Assume we have a data class that is required by some API but that we obfuscate by generating a build. We have a User data class, for example.
data class User(val id: String = "")
and we want not to obfuscate the class which generating build then to ignore it from obfuscating we use @Keep annotation and update the code like,
@Keep
data class User(val id: String = "")
This annotation allows the class to be ignored when minified using proguard. The class and its member functions will be preserved even when not in use.
-keep
to preserve options of class while generating the build. Using -keep over @Keep we get more control over what to preserve and what not to.
2. Keeping a class’s members
If we want to keep only the class members and not the entire class while shrinking, we can use,
-keepclassmembers
in the proguard rule file. This will help us to ignore members of a specific class.
Consider the above User class, and we want to preserve all the public methods inside it. We write the rule like,
-keepclassmembers class com.mindorks.sample.User{
public *;
}
3. Keeping names of the class and members
Let’s say we want to keep all of the same class names and members if they are used in the code, i.e. if the class is not used, it will be shrunk by proguard but will not be obfuscated because it has already been shrunk and there is no need for obfuscation.
-keepnames
Practical use of it looks like,
-keepnames class com.mindorks.sample.GlideModule
Here, if the GlideModule would keep all of its names of the class and the member function.
Note:-
As a fragment TAG, do not use something like MainFragment.class.getSimpleName().
While obfuscating, Proguard may assign the same name (A.class) to two different fragments in different packages. Two fragments will have the same TAG in this case. It will result in a bug in your application.
Keep your Proguard mapping file in order to trace back to the original code. You may need to upload it to different locations, such as the PlayStore Console, to see the original stack-trace of the crashes.