-
Notifications
You must be signed in to change notification settings - Fork 6.3k
Configuring ProGuard
ProGuard is a tool to help minify, obfuscate, and optimize your code. It is not only especially useful for reducing the overall size of your Android application as well as removing unused classes and methods that contribute towards the intrinsic 64k method limit of Android applications. This last aspect means that ProGuard is often recommended to be used both in development and production especially for larger applications.
ProGuard is normally only enabled for release builds and setup in your app/build.gradle
config. You can enable these settings on both your release and debug builds by enabling the minifyEnabled
option:
android {
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
dev {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
The Android SDK comes with ProGuard included as well as default settings file, which are specified as proguard-android.txt. It is important to include this file since it explicitly includes configuration settings such as explicitly stating that all View getter and setter methods should not be removed. The proguard-rules.pro
file is the file that you will use to configure.
Proguard can add a few minutes to your build cycle. If you can avoid using ProGuard in development, you should continue to do so. Once you begin to include enough libraries that causes the 64K method limit to be reached, you either need to remove extraneous dependencies or need to consider following the instructions for supporting a higher limit by using the multidex mode. Multidex compilation also takes additional time and requires extra work to support pre-Lollipop Android versions, so the recommendation is often to use ProGuard before using Multidex.
If you wish to check how close you are to the 64k limit, fork a copy of the dex-method-counts library. Inside this repo, type:
./gradlew assemble
Once this project compiles successfully, you can point this program to any of your .apk
files (normally located in app/build/outputs/apk
:
./dex-method-counts build/outputs/debug//myapp.apk # or .zip or .dex or directory
The program will generate a breakdown of the methods used across each library.
When using in development/debug testing, you may wish to turn on a few settings that may add to compile time as well as make it harder to troubleshoot. For instance, to ensure that no code optimizations or obfuscation is done, the following options should be declared in your ProGuard config:
# Workaround for ProGuard not recognizing dontobfuscate
# https://speakerdeck.com/chalup/proguard
-dontobfuscate
-dontoptimize
-optimizations !code/allocation/variable
One limitation in ProGuard is that dynamically generated classes such as those used in Butterknife, Otto, or Dagger 2 need to be explicitly declared. In many cases, compilation will not continue until these issues are resolved. In other cases, if you do not specify it, ProGuard will often strip these methods from being used and your app will often crash at run-time.
See this link for the standard set of library configs. It's important to check the documentation of each third-party library to see the most updated settings. You can often try to experiment too by incrementally adding the necessary lines to best understand the impact of each line configuration.
-keep class butterknife.** { *; }
-dontwarn butterknife.internal.**
-keep class **$$ViewBinder { *; }
-keepclasseswithmembernames class * {
@butterknife.* <fields>;
}
-keepclasseswithmembernames class * {
@butterknife.* <methods>;
}
-dontwarn retrofit.**
-keep class retrofit.** { *; }
-keepattributes Signature
-keepattributes Exceptions
-keepattributes Signature
-keepattributes *Annotation*
-keep class com.squareup.okhttp.** { *; }
-keep interface com.squareup.okhttp.** { *; }
-dontwarn com.squareup.okhttp.**
# Okio
-keep class sun.misc.Unsafe { *; }
-dontwarn java.nio.file.*
-dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement
-keep class sun.misc.Unsafe { *; }
-keep class com.google.gson.stream.** { *; }
keep class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}
-keep class org.parceler.Parceler$$Parcels
If you wish to confirm whether ProGuard is preserving certain annotations or classes, you can review the .apk
package that gets created to check. The first step is to download the dex2jar program and use it to decompile the Dalvik code (.dex
file) to a Java archive file (.jar
file).
wget http://sourceforge.net/projects/dex2jar/files/dex2jar-2.0.zip/download -O dex2jar-2.0.zip
unzip dex2jar-2.0.zip
chmod u+x ~/projects/dex2jar-2.0/*.sh
./d2j-dex2jar.sh <.apk file>
You can also use d2j-dex2jar.bat
if using a Windows machine:
> d2j-dex2jar.bat <.apk file>
Running the dex2jar
file directly on an APK file should convert it to a .jar
file. You can download JD-GUI and open this newly created file to review the Java class files. The UI allows you to double-check whether certain annotations were removed and whether certain classes were kept in the final compilation.
Created by CodePath with much help from the community. Contributed content licensed under cc-wiki with attribution required. You are free to remix and reuse, as long as you attribute and use a similar license.
Finding these guides helpful?
We need help from the broader community to improve these guides, add new topics and keep the topics up-to-date. See our contribution guidelines here and our topic issues list for great ways to help out.
Check these same guides through our standalone viewer for a better browsing experience and an improved search. Follow us on twitter @codepath for access to more useful Android development resources.