优化(Optimizing)应用程序APK通常是Android应用开发的最后一步。Google推荐使用ProGuard开源工具来优化APK。这篇文章我们将探索使用ProGuard的优势、问题以及给出一个优化你的APK的合适的配置文件。
优势
减少Apk的大小
提升Apk的性能
混淆
缺陷
潜在的错误配置
需要更多的测试
调试中堆栈跟踪难以阅读混淆后的方法名
其实最大的缺陷是当ProGuard配置错误或许将直接导致你的App崩溃。
Android ProGuard配置
有很多中方法来配置ProGuard的优化工具。Google在新创建的Android项目的根目录下也提供了一个默认的配置文件"proguard.cfg"。然而,由于引进了Fragment API 和 the onClick XML attribute,该配置文件已经过时了。由于该默认的配置文件重新命名public method names,一些Java反射(java reflection)或许不能工作,程序会抛出"method/class not found"异常。
我们已经更新了配置,以适应新的Fragment类(和兼容版本),并测试了几种具有不同级别的优化配置。下面的表单将展示使用不同级别的优化配置优化某App的结果。
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% |
注意: Size 减少(reduction) % 变量依赖于你项目结构等因素
"Safest"配置将我们的Apk大小减少了大约17%,然而"Recommended"配置将Apk的大小减少了36%。"Risky"配置仅仅比"Recommended"配置减少了0.7%。因此,重命名public and protected methods 不能保证其风险,而且维护开销增大。
推荐配置(Recommended Configuration)
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 #keep all public and protected methods that could be used by java reflection 23 -keepclassmembernames class * { 24 public protected <methods>; 25 } 26 27 -keepclasseswithmembernames class * { 28 native <methods>; 29 } 30 31 -keepclasseswithmembernames class * { 32 public <init>(android.content.Context, android.util.AttributeSet); 33 } 34 35 -keepclasseswithmembernames class * { 36 public <init>(android.content.Context, android.util.AttributeSet, int); 37 } 38 39 -keepclassmembers enum * { 40 public static **[] values(); 41 public static ** valueOf(java.lang.String); 42 } 43 44 -keep class * implements android.os.Parcelable { 45 public static final android.os.Parcelable$Creator *; 46 } 47 48 -dontwarn **CompatHoneycomb 49 -dontwarn org.htmlcleaner.*
17-20行:我们需要keep可能在XML布局(layout)文件中使用到的class,这些类包括自定义的View和Fragment。
23-26行:我们需要keep public/protected方法,以避免在XML文件中指定的onClick方法抛错
外文连接:http://blog.androidquery.com/2011/06/android-optimization-with-proper.html