美文网首页我爱编程
Android App 之ProGuard混淆

Android App 之ProGuard混淆

作者: bamboolmc | 来源:发表于2018-04-15 23:30 被阅读0次

    ProGuard原理


    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 <methods>;
    }
    
    # 自定义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 <fields>;
    }
    
    # WebView (混淆原则之2)
    -keepclassmembers class * {
        @android.webkit.JavascriptInterface <methods>;
    }
    
    # 排除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 <methods>;
    }
    
    #不混淆所有类及其类成员中的使用注解的字段
    -keepclasseswithmembers class * {
        @android.support.annotation.Keep <fields>;
    }
    
    # 不混淆所有类及其类成员中的使用注解的初始化方法
    -keepclasseswithmembers class * {
        @android.support.annotation.Keep <init>(...);
    }
    

    官方配置文件只进行了基础的部分配置,无法满足实际项目中所需要的所有配置,需要我们对其他个性配置在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 <init>(**, android.view.View); }
    -keep class butterknife.*
    -keepclasseswithmembernames class * { @butterknife.* <methods>; }
    -keepclasseswithmembernames class * { @butterknife.* <fields>; }
    
    #百度地图
    #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 <init> (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 <fields>;    !private <fields>;    !private <methods>;    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混淆

        本文链接:https://www.haomeiwen.com/subject/wuyjkftx.html