Open In App

ProGuard in Android

Last Updated : 28 Jan, 2022
Improve
Improve
Like Article
Like
Save
Share
Report

While writing the code for your Android app, there may be some lines of code that are unnecessary and may increase the size of your app’s APK. Aside from useless code, there are numerous libraries that you may have incorporated in your program but did not use all of the functionalities that each library provides. Also, you may have developed some code that will be obsolete in the future and failed to delete it. These factors are to blame for the increased size of your application’s APK. Android has Proguard capability to minimize the size of the APK. ProGuard is a free Java app for Android that allows us to do the following:

  1. Reduce (minimize) the code: Unused code in the project should be removed.
  2. Code obfuscation: Rename the names of classes, fields, and so on.
  3. Improve the code: Inline the functions, for example.

In summary, ProGuard has the following effect on our project:

  1. It shrinks the application’s size.
  2. It removes unused classes and methods that contribute to an Android application’s 64K method count limit.
  3. By obfuscating the code, it makes it difficult to reverse engineer the application.

How does it help our application?

Proguard is a great tool for creating a production-ready application in Android. It assists us in reducing code and making apps faster. Proguard is included by default in Android Studio and can help in a variety of ways, a few of which are listed below.

  1. It obfuscates the code, which means that it changes the names to something smaller, such as A for MainViewModel. After obfuscating the app, reverse engineering becomes difficult.
  2. It shrinks the resources, ignoring resources that are not called by our Class files, are not used in our Android app, such as images from drawable, and so on. This will significantly reduce the app’s size. To keep your app light and fast, you should always shrink it.

How should we apply it to our project?

To enable Proguard in your project, build the app, then in the .gradle include:

buildTypes {
    release {
        minifyEnabled true
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
}

It’s in the release block, so it’ll only be applied to the release of the build we generate.

However, it can be too much at times when the proguard removes too much code, which may break your flow code. So, when configuring the code, we must add some custom rules to ensure that the set of code is no longer obfuscating. We can fix this by defining custom rules in our proguard, which will follow when generating the build. Let’s take a look at how we can create custom rules in Proguard.

1. Maintaining 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.

Kotlin




data class GFG(val course: String = "")


If we don’t want to obfuscate the class that generates the build, we can use the @Keep annotation to prevent it from obfuscating and update the code as follows:

Kotlin




@Keep
data class GFG(val course: String = "")


This annotation allows the class to be ignored when minified using proguard. This will keep the class and its member functions alive even when they are not being used.

We can also employ:

-keep

to keep class options while generating the build When we use -keep instead of @Keep, we have more control over what we preserve and what we don’t. However, we can also preserve the key of the id field in the data model class by using @SerializedName (when using the Gson library), as shown below.

Kotlin




data class GFG(@SerializedName("course")
                 val course: String = "")


2. Retaining members of a class

If we want to keep only the class members and not the entire class while shrinking, we can use,

-keepclassmembers

in the rule file for proguard This will allow us to ignore members of a particular class. Consider the User class described above; we want to keep all of its public methods. We write the rule as follows:

-keepclassmembers class com.gfg.sample.course
{
    public *;
}

3. Keeping track of the class’s and members’ names

Let’s say we want to keep all of the same courses of the class and members of a class if it’s used in the code, i.e. if the class isn’t used, it will be shrunk by proguard but not obfuscated because it has already been shrunk and there is no need for obfuscation. We use the following tools to complete the task outlined above:

-keepcourses

4. Making Use of Any Library in Android

We may want to write some custom rules for proguard when using any library. It is possible that the library will issue a warning in the logcat, or they may not even have their own proguard rules! To correct this, we must add custom rules to our application. For example, if we begin to receive warnings from any library, we can add:

-dontwarn com.someOtherLib.annotations.*

5. Only use obfuscation to hide your project

Consider a very rare use case in which you simply want to obfuscate the code without shrinking any resources. This is a very rare use case, but it may be useful for some small libraries; in this case, we write the flags as follows:

-dontshrink
-dontoptimize

6. Keeping annotations

ProGuard removes all annotations while building the app, but it may still work for some codes in your project. However, if we do not want the annotations to be removed, we have the option as follows:

-keepattributes *Annotation*

7. Enhancement

We may need to provide an additional layer of optimization for our app after writing these many rules in ProGuard. First, we modify the build.gradle file as follows:

android {
  buildTypes {
    release {
      proguardFiles getDefaultProguardFile('proguard-android-optimize.txt')
    }
  }
}

In general, we don’t use this option, but in this case, we need to perform an extra level of optimizations. To increase the number of optimization cycles, for example, if we want to check if the optimization is done properly or not, and if it isn’t, it will optimize it again until a certain number of times, we use:

-optimizationpasses 10

It will run the optimization up to 10 times, in this case, to make it more optimized. Consider the following example: If we want to optimize our final classes at a more granular level than we did previously, we use,

-optimizations class/marking/final

Conclusion

  1. 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.
  2. 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.


Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads