Android App 之ProGuard混淆

ProGuard原理

Android App 之ProGuard混淆_第1张图片

ProGuard能够对Java类中的代码进行压缩(Shrink),优化(Optimize),混淆(Obfuscate),预检(Preveirfy)。

  1. Shrink: 压缩,在这一步中,用于检测和删除无用的类,字段,方法和属性。
  2. Optimize: 优化,在这一步中,对字节码进行分析优化,并且移除无用指令。
  3. Obfuscate: 混淆,在这一步中,使用无意义的名称(a,b,c),对类、字段和方法进行重命名。
  4. Preveirfy: 预检,在这一步中,主要是在Java平台上对处理后的代码进行预检。

引用ProGuard混淆

在应用的app module 下的build.gradle文件中进行如下配置:

 buildTypes {
    release {
        //混淆
        minifyEnabled true
        //加载默认混淆配置文件
        proguardFiles getDefaultProguardFile('proguard-android.txt'),'proguard-rules.pro'
    }
}  

由上述配置可知引入了两个进行混淆的文件,proguard-android.txt与proguard-rules.pro。proguard-android.txt为官方推荐的默认混淆文件,proguard-rules.pro为根据应用情况,自己配置的混淆文件。

混淆原则:

  1. 实体类、enum类型、使用GSON、fastjson等框架时,所写的JSON对象类不能进行混淆
  2. WEBView的JS调用也需要保证写的接口方法不混淆
  3. 反射用到的类不混淆
  4. JNI方法,本地方法不混淆
  5. 序列化的类不混淆,包括Parcelable和Serializable。序列化的时候会找不到对应的名字
  6. AndroidMainfest中的类不混淆,四大组件和Application的子类和Framework层下所有的类不进行混淆
  7. 第三方开源库或第三方sdk包,加官方提供的混淆方法
  8. 自定义view

官方混淆文件

混淆文件选择

proguard_android.txt 位置
a、当前工程名/build/intermediates/proguard-files
b、~/Library/Android/sdk/tools/proguard/

Starting with version 2.2 of the Android plugin for Gradle, this file is distributed together with the plugin and unpacked at build-time. The files in $ANDROID_HOME are no longer maintained and will be ignored by new version of the Android plugin for Gradle。

到底哪一个proguard_android.txt 是有效的呢? 根据如上描述可知根据Gradle的Android plugin版本来区分,2.2版本之前时使用的sdk中的(上述b),2.2版本及其以后,使用的是当前Application工程下的(上述a)。

无论上述哪种情况,我们均可发现在文件夹中同时存在有proguard_android.txt 和proguard-android-optimize.txt 两种,一种是带optimize的,一种是不带optimize的,对比发现两种的区别就是 proguard-android-optimize.txt多了一下几项配置:

    -optimizations !code/simplification/arithmetic,!code/simplification/cast,!field/*,!class/merging/*
    -optimizationpasses 5
    -allowaccessmodification
    -dontpreverify

并且有说明,如果不想优化,就使用proguard-android.txt (默认使用配置文件),如果想进行优化,就可以使用proguard-android-optimize.txt ,代码优化并不是只有配置proguard时进行优化,android本身生成dex文件是同样会进行优化。由于ProGuard优化并非在所有版本的Dalvik中能够正常工作,因此在ProGuard中进行优化会有一定风险。而上述的四项配置是至今为止能够解决由ProGuard优化产生的问题,但不保证能够解决所有由ProGuard优化产生的问题。因此官方文档提示如果使用proguard-android-optimize.txt 则必须保证在自己的应用中经过反复测试通过。因此默认的配置也就是使用proguard-android.txt。

官方配置文件详解(proguard-android.txt)

#混淆时不区分大小写,混淆后统一为小写
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-verbose

# 不做优化(proguard过程之二)
-dontoptimize
# 不做预检(proguard过程之四)
-dontpreverify

# 保存反射可能需要的某些属性
-keepattributes *Annotation*,Signature,InnerClasses,EnclosingMethod

# 不混淆如下三个谷歌服务类
-keep public class com.google.vending.licensing.ILicensingService
-keep public class com.android.vending.licensing.ILicensingService
-keep public class com.google.android.vending.licensing.ILicensingService
-dontnote com.android.vending.licensing.ILicensingService
-dontnote com.google.vending.licensing.ILicensingService
-dontnote com.google.android.vending.licensing.ILicensingService

# native方法不被混淆(混淆原则之4)
-keepclasseswithmembernames class * {
    native ;
}

# 自定义view (混淆原则之9)
-keepclassmembers public class * extends android.view.View {
    void set*(***);
    *** get*();
}

# 保留在Activity中的方法参数是view的方法,这样以来我们在layout中写的onClick就不会被影响
-keepclassmembers class * extends android.app.Activity {
    public void *(android.view.View);
}

# enum类型(混淆原则之1)
-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}

# 序列化类(混淆原则之5)
-keepclassmembers class * implements android.os.Parcelable {
    public static final ** CREATOR;
}
#保留R下面的资源
-keepclassmembers class **.R$* {
    public static ;
}

# WebView (混淆原则之2)
-keepclassmembers class * {
    @android.webkit.JavascriptInterface ;
}

# 排除support的警告
-dontnote android.support.**
-dontwarn android.support.**

# 保留keep注解
-keep class android.support.annotation.Keep

# 不混淆指定的类及其类成员
-keep @android.support.annotation.Keep class * {*;}

# 不混淆所有类及其类成员中的使用注解的方法
-keepclasseswithmembers class * {
    @android.support.annotation.Keep ;
}

#不混淆所有类及其类成员中的使用注解的字段
-keepclasseswithmembers class * {
    @android.support.annotation.Keep ;
}

# 不混淆所有类及其类成员中的使用注解的初始化方法
-keepclasseswithmembers class * {
    @android.support.annotation.Keep (...);
}

官方配置文件只进行了基础的部分配置,无法满足实际项目中所需要的所有配置,需要我们对其他个性配置在proguard-rules.pro进行配置。

个人配置混淆文件

常用第三方库混淆配置

如下为常用的第三方库混淆配置,每个配置后均配有官方地址,实际使用时,可根据具体的地址进行查询,便于随时更新混淆配置。

#ARouter路由混淆
#https://github.com/alibaba/ARouter
-keep public class com.alibaba.android.arouter.routes.**{*;}
-keep class * implements com.alibaba.android.arouter.facade.template.ISyringe{*;}
-keep interface * implements com.alibaba.android.arouter.facade.template.IProvider
-keep class * implements com.alibaba.android.arouter.facade.template.IProvider

#Retrofit2 混淆
#http://square.github.io/retrofit/
-dontwarn retrofit2.**
-keep class retrofit2.** { *; }
-keepattributes Signature
-keepattributes Exceptions

#okhttp
#https://github.com/square/okhttp
-dontwarn okhttp3.**
-dontwarn okio.**
-dontwarn javax.annotation.**
-dontwarn org.conscrypt.**
-keepnames class okhttp3.internal.publicsuffix.PublicSuffixDatabase

#Gson
#https://github.com/google/gson/blob/master/examples/android-proguard-example/proguard.cfg
-keepattributes Signature
-keepattributes *Annotation*
-dontwarn sun.misc.**
-keep class com.google.gson.examples.android.model.** { *; }
-keep class * implements com.google.gson.TypeAdapterFactory
-keep class * implements com.google.gson.JsonSerializer
-keep class * implements com.google.gson.JsonDeserializer

#ButterKnife
#https://github.com/JakeWharton/butterknife/blob/master/butterknife/proguard-rules.txt
-keep public class * implements butterknife.Unbinder { public (**, android.view.View); }
-keep class butterknife.*
-keepclasseswithmembernames class * { @butterknife.* ; }
-keepclasseswithmembernames class * { @butterknife.* ; }

#百度地图
#http://lbsyun.baidu.com/index.php?title=androidsdk/guide/buildproject
-keep class com.baidu.** {*;}
-keep class vi.com.** {*;}
-dontwarn com.baidu.**

#umeng
#http://dev.umeng.com/analytics/android-doc/integration
-keepclassmembers class * {
 public  (org.json.JSONObject);
}

#RxJava RxAndroid
-dontwarn sun.misc.**
-keepclassmembers class rx.internal.util.unsafe.*ArrayQueue*Field* {
    long producerIndex;
    long consumerIndex;
}
-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueProducerNodeRef {
    rx.internal.util.atomic.LinkedQueueNode producerNode;
}
-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueConsumerNodeRef {
    rx.internal.util.atomic.LinkedQueueNode consumerNode;
}

如上第三方库,在实际项目使用的过程中随时添加与更新。

其他配置

如上仅为部分基础设置,其他还需要根据自己项目实际使用过程中进行配置,由于部分配置已经在proguard_android.txt中进行了配置,现提供个人项目中所引用的配置,目前暂未发现问题。

#apk 包内所有 class 的内部结构
-dump class_files.txt
#未混淆的类和成员
-printseeds seeds.txt
#列出从 apk 中删除的代码
-printusage unused.txt
#混淆前后的映射
-printmapping mapping.txt
# 混淆时所采用的算法
-optimizations !code/simplification/cast,!field/*,!class/merging/*
#保留我们使用的四大组件,自定义的Application等等这些类不被混淆# 因为这些子类都有可能被外部调用
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Appliction
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider
-keep public class * extends android.app.backup.BackupAgentHelper
-keep public class * extends android.preference.Preference
# 保留support下的所有类及其内部类
-keep class android.support.** {*;}
# 保留继承的
-keep public class * extends android.support.v4.**
-keep public class * extends android.support.v7.**
-keep public class * extends android.support.annotation.**
# 保留Serializable序列化的类不被混淆
-keepclassmembers class * implements java.io.Serializable {    static final long serialVersionUID;    private static final java.io.ObjectStreamField[] serialPersistentFields;    !static !transient ;    !private ;    !private ;    private void writeObject(java.io.ObjectOutputStream);    private void readObject(java.io.ObjectInputStream);    java.lang.Object writeReplace();    java.lang.Object readResolve();}
# 对于带有回调函数的onXXEvent、**On*Listener的,不能被混淆
-keepclassmembers class * {    void *(**On*Event);    void *(**On*Listener);}
# webView处理,项目中没有使用到webView忽略即可
-keepclassmembers class fqcn.of.javascript.interface.for.webview {
   public *;
}
-keepclassmembers class * extends android.webkit.webViewClient {
    public void *(android.webkit.WebView, java.lang.String, android.graphics.Bitmap);
    public boolean *(android.webkit.WebView, java.lang.String);
}
-keepclassmembers class * extends android.webkit.webViewClient {
    public void *(android.webkit.webView, jav.lang.String);
}

注意

确保混淆不会对项目产生影响

建议从一开始就进行ProGuard混淆处理,并随时维护proguard-rules.pro文件,在debug模式下也进行ProGuard处理,这样就能够在我们的开发中进行处理ProGuard所造成的影响。

个人开源项目 “知趣” 及其“ProGuard配置”

ProGuard文档

你可能感兴趣的:(Android App 之ProGuard混淆)