Proguard 是Android tools包中提供用来对代码进行压缩,优化和进行混淆的工具,它能够移除无用的代码,对类名,方法名,字段名进行重命名,但不改变代码的结构,从而达到对代码混淆的作用。而这样做的好处是我们可以得到一个更小的apk文件和一份更难以被反编译的代码。
在项目中使用Proguard,必须在project.properties修改如下:
# This file is automatically generated by Android Tools. # Do not modify this file -- YOUR CHANGES WILL BE ERASED! # # This file must be checked in Version Control Systems. # # To customize properties used by the Ant build system edit # "ant.properties", and override values to adapt the script to your # project structure. # # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): proguard.config=${sdk.dir}/tools/proguard/proguard-android-optimize.txt:proguard-project.txt ...
Android本身已经提供了两份关于proguard的配置文件,放在sdk目录下面,如下:
所以,当然,我们也可以自己创建一个配置文件,放在指定的任意位置上,然后将改变这份配置文件就好,如下:
#proguard.config=${sdk.dir}/tools/proguard/proguard-android-optimize.txt:proguard-project.txt proguard.config=proguard-project.cfg
下面是Android 提供的 proguard-android.txt文件,如下:
# This is a configuration file for ProGuard. # http://proguard.sourceforge.net/index.html#manual/usage.html -dontusemixedcaseclassnames -dontskipnonpubliclibraryclasses -verbose # Optimization is turned off by default. Dex does not like code run # through the ProGuard optimize and preverify steps (and performs some # of these optimizations on its own). -dontoptimize -dontpreverify # Note that if you want to enable optimization, you cannot just # include optimization flags in your own project configuration file; # instead you will need to point to the # "proguard-android-optimize.txt" file instead of this one from your # project.properties file. -keepattributes *Annotation* -keep public class com.google.vending.licensing.ILicensingService -keep public class com.android.vending.licensing.ILicensingService # For native methods, see http://proguard.sourceforge.net/manual/examples.html#native -keepclasseswithmembernames class * { native <methods>; } # keep setters in Views so that animations can still work. # see http://proguard.sourceforge.net/manual/examples.html#beans -keepclassmembers public class * extends android.view.View { void set*(***); *** get*(); } # We want to keep methods in Activity that could be used in the XML attribute onClick -keepclassmembers class * extends android.app.Activity { public void *(android.view.View); } # For enumeration classes, see http://proguard.sourceforge.net/manual/examples.html#enumerations -keepclassmembers enum * { public static **[] values(); public static ** valueOf(java.lang.String); } -keep class * implements android.os.Parcelable { public static final android.os.Parcelable$Creator *; } -keepclassmembers class **.R$* { public static <fields>; } # The support library contains references to newer platform versions. # Don‘t warn about those in case this app is linking against an older # platform version. We know about them, and they are safe. -dontwarn android.support.**
其实基本上上面提供的也是Android不建议进行混淆的代码,所以我们的如果要对自己使用的类进行混淆,可以在这份文档的基本上进行加工就可以。
前面说过,Proguard其实做的不只混淆,还有压缩优化代码(移除掉一些无用的代码和重命名类名,方法名,字段名等),当进行过Proguard之后,会在项目的根目录生成一个proguard目录,其下面有几个文件:
其中seeds是我们上面配置中不进行proguard的文件,其内容如下:
android.support.v4.accessibilityservice.AccessibilityServiceInfoCompat android.support.v4.accessibilityservice.AccessibilityServiceInfoCompat: android.support.v4.accessibilityservice.AccessibilityServiceInfoCompat$AccessibilityServiceInfoVersionImpl IMPL android.support.v4.accessibilityservice.AccessibilityServiceInfoCompat: int CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT android.support.v4.accessibilityservice.AccessibilityServiceInfoCompat: int CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION android.support.v4.accessibilityservice.AccessibilityServiceInfoCompat: int CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY android.support.v4.accessibilityservice.AccessibilityServiceInfoCompat: int CAPABILITY_CAN_FILTER_KEY_EVENTS android.support.v4.accessibilityservice.AccessibilityServiceInfoCompat: int FEEDBACK_BRAILLE android.support.v4.accessibilityservice.AccessibilityServiceInfoCompat: int FEEDBACK_ALL_MASK而mapping.txt则是进行过proguard,被重新命名过的文件,其内容如下:
com.xxx.xxx.xxx.xxx.xxx.xxxActivity$Get~~~~Task -> com.xxx.activity.xx.aa com.xxx.xxx.xxx.xxx.xxx.activity.account.xxxActivity this$0 -> a void onPreExecute() -> onPreExecute android.util.SparseArray doInBackground$7d5cdb5d() -> a void onPostExecute(android.util.SparseArray) -> a java.lang.Object doInBackground(java.lang.Object[]) -> doInBackground18002240500可以看到 类名会变成a,b等无明显意义的字母表示。
在进行proguard之后,应用可能运行起来会有或多或少,这样那样的问题,所以每一次进行过proguard之后,可以将这个seeds和mapping.txt给保存起来,前后进行比对,从而快速定位到在proguard中出现的问题。
在我们的应用中,有很多情况下是需要使用到第三方的jar包的,别的不说,本身 support包就已经是以第三方jar包形式存在了。
在应用这些第三方jar包的时候,最好不要对这些jar包进行proguard,尤其是跟第三方系统有接口交互的时候,因为混淆了话,两边类名,或者字段名,或者方法名不一致,就有可能出现问题,所以对第三方jar包进行开放,在配置文件中配置如下:
-dontwarn com.thoughtworks.xstream.** -keep class com.thoughtworks.xstream.** {*; } -keep interface com.thoughtworks.xstream.** {*; }
-keep options,顾名思义,就是保持那些文件,不进行代码混淆。
不过有一点要注意的是,如果在开放的代码中有应用到泛型的话,我们还必须开放下面的属性,如下:
# The "Signature" attribute is required to be able to access generic types when compiling in JDK 5.0 and higher. -keepattributes Signature
而如果用到注释annotation的话,下面的属性也是要放开的,
-keepattributes *Annotation*
结束。