Android中关于Proguard的一些记要

Android中关于Proguard的一些记录

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目录下面,如下:

Android中关于Proguard的一些记要

所以,当然,我们也可以自己创建一个配置文件,放在指定的任意位置上,然后将改变这份配置文件就好,如下:

#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目录,其下面有几个文件:

Android中关于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*

结束。