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*
结束。