Optimizing the app APK is usually the last step of Android development. Google recommend using the open source ProGuard tool to optimize the apk for final delivery. Here we explore the benefits, issues, and suggest a proper configuration for optimizing your apk.
Benefit
- Reduced APK size
- Improve performance
- Obfuscation
Drawback
- Potential misconfiguration
- Additional testing required
- Stacktraces are difficult to read with obfuscated method names
The major drawback is that your app might crash when misconfigured.
Configuration for Android
There are many ways to configure the ProGuard tool for optimization. Google already provided a default configuration named “proguard.cfg” under the project root folder for newly created projects. However, this configuration is outdated due to the introduction of the Fragment API and the onClick XML attribute. Since the default configuration renames public method names, some java reflection might not work and, as a result, method/class not found exceptions might be thrown.
We have updated the configuration to accommodate the new Fragment classes (and the compatibility version) and tested several configuration with different level of optimization. The following table shows the resulted apk size when optimizing our AQuery demo app VikiSpot Reader:
Configuration | Notes | APK Size (kb) | Size % |
No Optimization | Original APK. | 323 | 100% |
Safest | Remove no classes and only rename private methods. | 266 | 82.4% |
Recommended | Remove unused classes and only rename private methods. | 205 | 63.5% |
Risky | Remove unused classes and rename most public/protected methods. | 203 | 62.8% |
Note: Size reduction % varies depends on your project structure and other factors.
The “Safest” configuration reduced our apk size by about 17%, whereas the “Recommended” configuration reduce the apk size by 36%.
The “Risky” configuration only reduce an additional 0.7% beyond the “Recommended” settings.
Therefore, we believe that the marginal benefit of renaming public and protected methods does not warrant its risk and maintenance overhead.
Recommended Configuration
Here’s a safe configuration that give most benefits. See source file.
1: -optimizationpasses 5
2: -dontusemixedcaseclassnames
3: -dontskipnonpubliclibraryclasses
4: -dontpreverify
5: -verbose
6: -optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
7:
8: -keep public class * extends android.app.Activity
9: -keep public class * extends android.app.Application
10: -keep public class * extends android.app.Service
11: -keep public class * extends android.content.BroadcastReceiver
12: -keep public class * extends android.content.ContentProvider
13: -keep public class * extends android.app.backup.BackupAgentHelper
14: -keep public class * extends android.preference.Preference
15: -keep public class com.android.vending.licensing.ILicensingService
16:
17: #keep all classes that might be used in XML layouts
18: -keep public class * extends android.view.View
19: -keep public class * extends android.app.Fragment
20: -keep public class * extends android.support.v4.Fragment
21:
22:
23: #keep all public and protected methods that could be used by java reflection
24: -keepclassmembernames class * {
25: public protected <methods>;
26: }
27:
28: -keepclasseswithmembernames class * {
29: native <methods>;
30: }
31:
32: -keepclasseswithmembernames class * {
33: public <init>(android.content.Context, android.util.AttributeSet);
34: }
35:
36: -keepclasseswithmembernames class * {
37: public <init>(android.content.Context, android.util.AttributeSet, int);
38: }
39:
40:
41: -keepclassmembers enum * {
42: public static **[] values();
43: public static ** valueOf(java.lang.String);
44: }
45:
46: -keep class * implements android.os.Parcelable {
47: public static final android.os.Parcelable$Creator *;
48: }
49:
50: -dontwarn **CompatHoneycomb
51: -dontwarn org.htmlcleaner.*
Line 17-20: We want to keep classes that can be referenced in XML layouts. Those classes include custom View and Fragment.
Line 23-26: We want to keep the method names for public/protected methods to avoid problems with onClick method names specified in XML.
Setup
Here we highlight the necessary steps to enable ProGuard optimization with Eclipse.
Enable ProGuard
Open the “default.properties” file under the project root.
Enter “proguard.config=proguard.cfg”, like this:
# Project target.
target=android-12
proguard.config=proguard.cfg
Note that the file comments says not to edit this file. Ignore that outdated comment.
Next, make sure your SDK location path has no space in it, like this:

There is a bug in the SDK that causes ProGuard to fail when there’s a space in the SDK path. If you are developing on Windows and installed the SDK to the default location, you most likely will need to fix the SDK path.
Configuration
Create or edit the file “proguard.cfg” under the project folder. We recommend using our updated recommended configuration to accommodate the new Fragments and onClick listeners.
Export APK
With the above setup, ProGuard will silently run when the APK is generated. Pay attention to the console and make sure there’s no ProGuard related errors.
For testing, you can export the APK to the project /bin folder.
Test APK
Install the APK to a test device. If you export the APK to the /bin folder, just run the project like normal development testing and the optimized APK will be deployed. Note that you might need to uninstall the development version of the app in your device, because the optimized APK will be signed and the dev app must be removed first.
Feedback
We hope our guide help your Android development.
If you have issues or have other insights regarding Android ProGuard optimization, please feel free to leave a comment!
Also, take a look at our open source framework Android Query for more Android goodies.