android配置混淆

2018-09-18 17:09:05 codekxx 阅读数 233

Glide图片加载框架混淆

# glide 的混淆代码
-keep public class * implements com.bumptech.glide.module.GlideModule
-keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** {
  **[] $VALUES;
  public *;
}

banner for youth5201314的混淆代码

# banner 的混淆代码
-keep class com.youth.banner.** {
    *;
 }

SmartRefreshLayout
没有使用到:序列化、反序列化、JNI、反射,所以并不需要添加混淆过滤代码,并且已经混淆测试通过,如果你在项目的使用中混淆之后出现问题,请及时通知我。

2013-07-26 12:37:53 hellohaifei 阅读数 4818

为了保护代码被反编译,android引入了混淆代码的概念

1.设置混淆

在工程下找到project.properties文件

在文件中加入proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt这个是系统的

也可以用自己的混淆文件(这样就可以配置一些自己的东西),去sdk.dir}/tools/proguard/ 下复制proguard-android.txt文件到本地工程中

然后设置成proguard.config=proguard-android.txt

project.properties文件:

#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
proguard.config=proguard-android.txt

# Project target.
target=android-17

2.配置自己的混淆文件proguard-android.txt

为了解决第三方包不被混淆,第三方包在混淆后,运行的时候会挂掉。我的错误是java.lang.ExceptionInInitializerError

E/AndroidRuntime( 9608): java.lang.ExceptionInInitializerError
E/AndroidRuntime( 9608):        at a.a.b.f.<init>(Unknown Source)
E/AndroidRuntime( 9608):        at a.a.b.e.<init>(Unknown Source)
E/AndroidRuntime( 9608):        at a.a.c.dg.b(Unknown Source)
E/AndroidRuntime( 9608):        at a.a.c.dg.a(Unknown Source)
E/AndroidRuntime( 9608):        at a.a.c.b.a(Unknown Source)
E/AndroidRuntime( 9608):        at a.a.c.ad.a(Unknown Source)
E/AndroidRuntime( 9608):        at a.a.a.a(Unknown Source)
E/AndroidRuntime( 9608):        at com.petsea.c.a(Unknown Source)
E/AndroidRuntime( 9608):        at com.petsea.c.a(Unknown Source)
E/AndroidRuntime( 9608):        at com.petsea.h.a(Unknown Source)
E/AndroidRuntime( 9608):        at com.petsea.h.onPostExecute(Unknown Source)
E/AndroidRuntime( 9608):        at android.os.AsyncTask.finish(AsyncTask.java:631)
E/AndroidRuntime( 9608):        at android.os.AsyncTask.access$600(AsyncTask.java:177)
E/AndroidRuntime( 9608):        at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:644)
E/AndroidRuntime( 9608):        at android.os.Handler.dispatchMessage(Handler.java:99)
E/AndroidRuntime( 9608):        at android.os.Looper.loop(Looper.java:137)
E/AndroidRuntime( 9608):        at android.app.ActivityThread.main(ActivityThread.java:5041)
E/AndroidRuntime( 9608):        at java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime( 9608):        at java.lang.reflect.Method.invoke(Method.java:511)
E/AndroidRuntime( 9608):        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
E/AndroidRuntime( 9608):        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
E/AndroidRuntime( 9608):        at dalvik.system.NativeStart.main(Native Method)
E/AndroidRuntime( 9608): Caused by: java.lang.ExceptionInInitializerError
E/AndroidRuntime( 9608):        at a.a.b.l.<clinit>(Unknown Source)
E/AndroidRuntime( 9608):        ... 22 more

最终我通过 加LOG的调试方法定位到是由于第三方jar包被混淆后的原因导致的。

3解决方法:

在proguard-android.txt文件最后加入了-keep class org.jsoup.**这样一句代码,就是保持这个类不被混淆

附上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.**

-keep class org.jsoup.**




2018-03-28 12:54:23 jungle_pig 阅读数 1008

首先要在build.gradle中开启混淆,也就是minifyEnabled true,我用的build.gradle具体如下所示:

def releaseTime() {
    return new Date().format("yyyy.MM.dd", TimeZone.getTimeZone("UTC"))
}

android {
    .... 

    buildTypes {
        release {
            // 混淆
            minifyEnabled true
            // Zipalign优化
            zipAlignEnabled true
            // 移除无用的resource文件
            shrinkResources true
            // 前一部分代表系统默认的android程序的混淆文件,该文件已经包含了基本的混淆声明,后一个文件是自己的定义混淆文件
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

            applicationVariants.all { variant ->
                variant.outputs.each { output ->
                    def outputFile = output.outputFile
                    if (outputFile != null && outputFile.name.endsWith('.apk')) {
                        // 输出apk名称为appname-1.0-beta1-xxxx-xx-xx.apk
                        def fileName = "app-${defaultConfig.versionName}-beta1-${releaseTime()}.apk"
                        output.outputFile = new File(outputFile.parent, fileName)
                    }
                }
            }
        }
    }
    ....
}

  上面注释中写到proguard-Android.txt文件,这是系统默认的混淆文件,具体在../sdk/tools/proguard/目录下,其中包含了android最基本的混淆,一般不需要改动,我们需要配置的是项目中app下的proguard-rules.pro文件,在此提供一份混淆模板。

#############################################
#
# 对于一些基本指令的添加
#
#############################################
# 代码混淆压缩比,在0~7之间,默认为5,一般不做修改
-optimizationpasses 5

# 混合时不使用大小写混合,混合后的类名为小写
-dontusemixedcaseclassnames

# 指定不去忽略非公共库的类
-dontskipnonpubliclibraryclasses

# 这句话能够使我们的项目混淆后产生映射文件
# 包含有类名->混淆后类名的映射关系
-verbose

# 指定不去忽略非公共库的类成员
-dontskipnonpubliclibraryclassmembers

# 不做预校验,preverify是proguard的四个步骤之一,Android不需要preverify,去掉这一步能够加快混淆速度。
-dontpreverify

# 保留Annotation不混淆
-keepattributes *Annotation*,InnerClasses

# 避免混淆泛型
-keepattributes Signature

# 抛出异常时保留代码行号
-keepattributes SourceFile,LineNumberTable

# 指定混淆是采用的算法,后面的参数是一个过滤器
# 这个过滤器是谷歌推荐的算法,一般不做更改
-optimizations !code/simplification/cast,!field/*,!class/merging/*


#############################################
#
# Android开发中一些需要保留的公共部分
#
#############################################

# 保留我们使用的四大组件,自定义的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
-keep public class * extends android.view.View
-keep public class com.android.vending.licensing.ILicensingService


# 保留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.**

# 保留R下面的资源
-keep class **.R$* {*;}

# 保留本地native方法不被混淆
-keepclasseswithmembernames class * {
    native <methods>;
}

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

# 保留枚举类不被混淆
-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}

# 保留我们自定义控件(继承自View)不被混淆
-keep public class * extends android.view.View{
    *** get*();
    void set*(***);
    public <init>(android.content.Context);
    public <init>(android.content.Context, android.util.AttributeSet);
    public <init>(android.content.Context, android.util.AttributeSet, int);
}

# 保留Parcelable序列化类不被混淆
-keep class * implements android.os.Parcelable {
    public static final android.os.Parcelable$Creator *;
}

# 保留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);
}

# 移除Log类打印各个等级日志的代码,打正式包的时候可以做为禁log使用,这里可以作为禁止log打印的功能使用
# 记得proguard-android.txt中一定不要加-dontoptimize才起作用
# 另外的一种实现方案是通过BuildConfig.DEBUG的变量来控制
#-assumenosideeffects class android.util.Log {
#    public static int v(...);
#    public static int i(...);
#    public static int w(...);
#    public static int d(...);
#    public static int e(...);
#}

#############################################
#
# 项目中特殊处理部分
#
#############################################

#-----------处理反射类---------------



#-----------处理js交互---------------



#-----------处理实体类---------------
# 在开发的时候我们可以将所有的实体类放在一个包内,这样我们写一次混淆就行了。
#-keep public class com.ljd.example.entity.** {
#    public void set*(***);
#    public *** get*();
#    public *** is*();
#}


#-----------处理第三方依赖库---------

  下面介绍常用第三方混淆配置(已按字母排序,不定期更新):

# AndroidEventBus
-keep class org.simple.** { *; }
-keep interface org.simple.** { *; }
-keepclassmembers class * {
    @org.simple.eventbus.Subscriber <methods>;
}

# 百度地图(jar包换成自己的版本,记得签名要匹配)
-libraryjars libs/baidumapapi_v2_1_3.jar
-keep class com.baidu.** {*;}
-keep class vi.com.** {*;}
-keep class com.sinovoice.** {*;}
-keep class pvi.com.** {*;}
-dontwarn com.baidu.**
-dontwarn vi.com.**
-dontwarn pvi.com.**

# Bugly
-dontwarn com.tencent.bugly.**
-keep class com.tencent.bugly.** {*;}

# ButterKnife
-keep class butterknife.** { *; }
-dontwarn butterknife.internal.**
-keep class **$$ViewBinder { *; } 
-keepclasseswithmembernames class * {
    @butterknife.* <fields>;
} 
-keepclasseswithmembernames class * {
    @butterknife.* <methods>;
}

# EventBus
-keepattributes *Annotation*
-keepclassmembers class ** {
    @org.greenrobot.eventbus.Subscribe <methods>;
}
-keep enum org.greenrobot.eventbus.ThreadMode { *; }

# Facebook
-keep class com.facebook.** {*;}
-keep interface com.facebook.** {*;}
-keep enum com.facebook.** {*;}

# FastJson
-dontwarn com.alibaba.fastjson.**
-keep class com.alibaba.fastjson.** { *; }
-keepattributes Signature
-keepattributes *Annotation*

# Fresco
-keep class com.facebook.fresco.** {*;}
-keep interface com.facebook.fresco.** {*;}
-keep enum com.facebook.fresco.** {*;}

# 高德相关依赖
# 集合包:3D地图3.3.2 导航1.8.0 定位2.5.0
-dontwarn com.amap.api.**
-dontwarn com.autonavi.**
-keep class com.amap.api.**{*;}
-keep class com.autonavi.**{*;}
# 地图服务
-dontwarn com.amap.api.services.**
-keep class com.map.api.services.** {*;}
# 3D地图
-dontwarn com.amap.api.mapcore.**
-dontwarn com.amap.api.maps.**
-dontwarn com.autonavi.amap.mapcore.**
-keep class com.amap.api.mapcore.**{*;}
-keep class com.amap.api.maps.**{*;}
-keep class com.autonavi.amap.mapcore.**{*;}
# 定位
-dontwarn com.amap.api.location.**
-dontwarn com.aps.**
-keep class com.amap.api.location.**{*;}
-keep class com.aps.**{*;}
# 导航
-dontwarn com.amap.api.navi.**
-dontwarn com.autonavi.**
-keep class com.amap.api.navi.** {*;}
-keep class com.autonavi.** {*;}

# Glide
-keep public class * implements com.bumptech.glide.module.GlideModule
-keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** {
  **[] $VALUES;
  public *;
}

# Gson
-keepattributes Signature-keepattributes *Annotation*
-keep class sun.misc.Unsafe { *; }
-keep class com.google.gson.stream.** { *; }
# 使用Gson时需要配置Gson的解析对象及变量都不混淆。不然Gson会找不到变量。
# 将下面替换成自己的实体类
-keep class com.example.bean.** { *; }

# Jackson
-dontwarn org.codehaus.jackson.**
-dontwarn com.fasterxml.jackson.databind.**
-keep class org.codehaus.jackson.** { *;}
-keep class com.fasterxml.jackson.** { *; }

# 极光推送
-dontoptimize
-dontpreverify
-dontwarn cn.jpush.**
-keep class cn.jpush.** { *; }

# OkHttp3
-dontwarn com.squareup.okhttp3.**
-keep class com.squareup.okhttp3.** { *;}
-dontwarn okio.**

# Okio
-dontwarn com.squareup.**  
-dontwarn okio.**  
-keep public class org.codehaus.* { *; }  
-keep public class java.nio.* { *; }

# OrmLite
-keepattributes *DatabaseField* 
-keepattributes *DatabaseTable* 
-keepattributes *SerializedName*  
-keep class com.j256.**
-keepclassmembers class com.j256.** { *; }
-keep enum com.j256.**
-keepclassmembers enum com.j256.** { *; }
-keep interface com.j256.**
-keepclassmembers interface com.j256.** { *; }

# Realm
-keep class io.realm.annotations.RealmModule
-keep @io.realm.annotations.RealmModule class *
-keep class io.realm.internal.Keep
-keep @io.realm.internal.Keep class * { *; }
-dontwarn javax.**
-dontwarn io.realm.**

# Retrofit
-dontwarn retrofit2.**
-keep class retrofit2.** { *; }
-keepattributes Signature
-keepattributes Exceptions

# Retrolambda
-dontwarn java.lang.invoke.*

# 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;
}

# 微信支付
-dontwarn com.tencent.mm.**
-dontwarn com.tencent.wxop.stat.**
-keep class com.tencent.mm.** {*;}
-keep class com.tencent.wxop.stat.**{*;}

# 信鸽
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep class com.tencent.android.tpush.**  {* ;}
-keep class com.tencent.mid.**  {* ;}
-keepattributes *Annotation*

# 新浪微博
-keep class com.sina.weibo.sdk.* { *; }  
-keep class android.support.v4.* { *; }  
-keep class com.tencent.* { *; }  
-keep class com.baidu.* { *; }  
-keep class lombok.ast.ecj.* { *; }  
-dontwarn android.support.v4.**  
-dontwarn com.tencent.**s  
-dontwarn com.baidu.**  

# 讯飞语音
-dontwarn com.iflytek.**
-keep class com.iflytek.** {*;}

# 银联
-dontwarn com.unionpay.**
-keep class com.unionpay.** { *; }

# 友盟统计分析
-keepclassmembers class * { public <init>(org.json.JSONObject); }
-keepclassmembers enum com.umeng.analytics.** {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}

# 友盟自动更新
-keepclassmembers class * { public <init>(org.json.JSONObject); }
-keep public class cn.irains.parking.cloud.pub.R$*{ public static final int *; }
-keep public class * extends com.umeng.**
-keep class com.umeng.** { *; }

# 支付宝钱包
-dontwarn com.alipay.**
-dontwarn HttpUtils.HttpFetcher
-dontwarn com.ta.utdid2.**
-dontwarn com.ut.device.**
-keep class com.alipay.android.app.IAlixPay{*;}
-keep class com.alipay.android.app.IAlixPay$Stub{*;}
-keep class com.alipay.android.app.IRemoteServiceCallback{*;}
-keep class com.alipay.android.app.IRemoteServiceCallback$Stub{*;}
-keep class com.alipay.sdk.app.PayTask{ public *;}
-keep class com.alipay.sdk.app.AuthTask{ public *;}
-keep class com.alipay.mobilesecuritysdk.*
-keep class com.ut.*
2018-11-21 09:36:29 Love667767 阅读数 399

目录

  1. 为什么要混淆
  2. Android Studio 混淆配置
  3. ProGuard的作用
  4. 规则
  5. 实操中需注意的问题
  6. 完整配置示例
  7. 错误日志的还原

原文链接: 5分钟搞定android混淆

一、为什么要混淆

混淆时,会使用 a, b, c, d 这种简短而无意义的名称,对类,字段和方法进行重新命名,从而达到保护源代码的目的。

二、Android Studio 混淆配置

Android Studio 集成了 Java 语言的 ProGuard 作为压缩,优化和混淆工具,配合Gradle构建工具使用需要两步:

  1. 在工程应用目录的 build.gradle 文件中设置 minifyEnabled 为 true 即可。
  2. proguard-rules.pro 文件中加入我们的混淆规则。
buildTypes {
    debug {
        // 如果没有提供混淆规则文件,则设置默认的混淆规则文件(SDK/tools/proguard/proguard-android.txt)
        pseudoLocalesEnabled true
        // 显示Log
        buildConfigField "boolean", "LOG_DEBUG", "true"
        //混淆
        minifyEnabled false
        //Zipalign优化
        zipAlignEnabled true
        // 移除无用的resource文件
        shrinkResources true
        //加载默认混淆配置文件
        proguardFiles getDefaultProguardFile('proguard-Android.txt'), 'proguard-rules.pro'
        //签名
        signingConfig signingConfigs.debug
    }
    
    release {
        // 如果没有提供混淆规则文件,则设置默认的混淆规则文件(SDK/tools/proguard/proguard-android.txt)
        pseudoLocalesEnabled true
        // 不显示Log
        buildConfigField "boolean", "LOG_DEBUG", "false"
        //混淆
        minifyEnabled true
        //Zipalign优化
        zipAlignEnabled true
        // 移除无用的resource文件
        shrinkResources true
        //加载默认混淆配置文件
        proguardFiles getDefaultProguardFile('proguard-Android.txt'), 'proguard-rules.pro'
        //签名
        signingConfig signingConfigs.relealse
    }
}

三、ProGuard的作用

  1. 压缩(shrink):默认开启,用于减小应用的体积,侦测并且移除代码中无用的类,字段,方法和特性。

    dontshrink 关闭压缩

  2. 优化(Optimization):默认开启,在字节码级别执行优化,让应用运行的更快。

    dontoptimize 关闭优化
    optimizationpasses n: 表示proguard对代码进行迭代优化的次数,Android一般为5;

  3. 混淆(Obfuscation):默认开启,a,b,c,d 这样简短而无意义的名称,对类,字段和方法进行重命名,增大反编译难度,除非用keep保护。

    dontobfuscate 关闭混淆
    混淆后默认会在工程目录 app/build/outputs/mapping/release 下生成一个
    mapping.txt 文件,这就是混淆规则,我们可以根据这个文件把混淆后的代码反推回源本的代码,所以这个文件很重要,注意保护好。

四、规则

  1. 先看如下两个比较常用命令的区别

     -keep class com.example.elson.**
     -keep class com.example.elson.*
    

    一个通配符: 表示只是保持该包下的类名,而子包下的类名还是会被混淆;
    两个通配符: 表示把本包和所含子包下的类名都保持;

  2. 用以上方法保持类后,发现类名虽然未混淆,但里面的具体方法和变量命名还是变了,这时如果既想保持类名,又想保持里面的内容不被混淆,我们就需要以下方法了

     -keep class com.example.elson.* {*;}
    
  3. 在此基础上,我们也可以 使用Java的基本规则来保护特定类不被混淆,如可以用 extend,implement 等这些Java规则。如下例子就避免所有继承Activity的类被混淆

    -keep public class * extends android.app.Activity
    
  4. 如保留一个类中的内部类不被混淆则需要用$符号,如保持 OuterClass 内部类 InnerClass 中的所有public内容不被混淆。

    -keepclassmembers class com.example.elson.OuterClass$InnerClass {
       public *;
    }
    
  5. 保持一个类中特定的内容不被混淆

    如果一个类中你不希望保持全部内容不被混淆,而只是希望保护类下的特定内容,就可以使用;

    <init>;     //匹配所有构造器
    <fields>;   //匹配所有域
    <methods>;  //匹配所有方法方法
    
  6. 还可以在前面加上 private 、public、native 等来进一步指定不被混淆的内容

    // 如下表示 Main 类下的所有 public 方法都不会被混淆
    -keep class com.example.elson.Main{
      public <methods>;
    }
    // 当然还可以加入参数,
    // 比如以下表示用 JSONObject 作为入参的构造函数不会被混淆;
    -keep class com.example.elson.Main {
      public <init>(org.json.JSONObject);
    }
    
  7. 不保持类名,只需要把该类下的特定方法保持不被混淆

    有时我们不需要保持类名,只需要把该类下的特定方法保持不被混淆,那你就不能用keep方法了,keep方法会保持类名,而需要用 keepclassmembers ,如此类名就不会被保持,为了便于对这些规则进行理解,官网给出了以下表格:

    保留 防止被移除或者被重命名 防止被重命名
    类和类成员 -keep -keepnames
    仅类成员 -keepclassmembers -keepclassmembernames
    如果拥有某成员,保留类和类成员
    -keepclasseswithmembers
    -keepclasseswithmembernames

    移除是指在压缩(Shrinking)时是否会被删除;以上内容是混淆规则中需要重点掌握的。此外,还需要以下几点注意事项。

五、实操中需注意的问题

  1. JNI 方法不可混淆

    JNI 方法不可混淆,这个方法需要和native方法保持一致;

    # 保持native方法不被混淆  
    -keepclasseswithmembernames class * {  
        native <methods>;
    }
    
  2. 反射用到的类不混淆(包名类名, 方法名, 变量名),如果你把类名混淆了, 下面的语句会出什么问题?

    if(obj.getClass().getName().equals("a.b.c.SomeClass")) {
        //do something
    }
    
  3. AndroidMainfest 中的类不混淆,如 四大组件、Application 的子类和 Framework 层下所有的类默认不会进行混淆。

  4. JSON 对象类不混淆

  5. 使用第三方开源库或者引用其他第三方的SDK包时,如果有特别要求,也需要在混淆文件中加入对应的混淆规则;

  6. 有用到 WebView 的 JS 调用也需要保证写的接口方法不混淆,原因同第1条;

  7. Parcelable 的子类和Creator静态成员变量不混淆,否则会产生 Android.os.BadParcelableException 异常;

    -keep class * implements Android.os.Parcelable { 
    	# 保持Parcelable不被混淆           
    	public static final Android.os.Parcelable$Creator *;
    }
    
  8. 使用 enum 类型时需要注意避免以下两个方法混淆,因为enum类的特殊性,以下两个方法会被反射调用,见第2条规则。

    -keepclassmembers enum * {  
      public static **[] values();
      public static ** valueOf(java.lang.String);
    }
    
  9. 发布一款应用除了设 minifyEnabled = ture,也应该设置 zipAlignEnabled = true,像 Google Play 强制要求开发者上传的应用必须是经过 zipAlign 的,zipAlign 可以让安装包中的资源按4字节对齐,这样可以减少应用在运行时的内存消耗。

六、完整配置示例

#-----------------------定制化区域----------------------------
#-------------1.实体类--------------

#-------------2.第三方包-------------

#-------------3.与js互相调用的类-------------

#-------------4.反射相关的类和方法--------------

#---------------------- 常规配置 ---------------------------
#----------------- 基本指令区 -----------------
-optimizationpasses 5
-dontskipnonpubliclibraryclassmembers
-printmapping proguardMapping.txt
-optimizations !code/simplification/cast,!field/*,!class/merging/*
-keepattributes *Annotation*,InnerClasses
-keepattributes Signature
-keepattributes SourceFile,LineNumberTable
#----------------------------------------------------------------------------

#------------------默认保留区------------------
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-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
-keep public class * extends android.view.View
-keep public class com.android.vending.licensing.ILicensingService
-keep class android.support.** {*;}

-keep public class * extends android.view.View{
    *** get*();
    void set*(***);
    public <init>(android.content.Context);
    public <init>(android.content.Context, android.util.AttributeSet);
    public <init>(android.content.Context, android.util.AttributeSet, int);
}
-keepclasseswithmembers class * {
    public <init>(android.content.Context, android.util.AttributeSet);
    public <init>(android.content.Context, android.util.AttributeSet, int);
}
-keepclassmembers class * implements java.io.Serializable {
    static final long serialVersionUID;
    private static final java.io.ObjectStreamField[] serialPersistentFields;
    private void writeObject(java.io.ObjectOutputStream);
    private void readObject(java.io.ObjectInputStream);
    java.lang.Object writeReplace();
    java.lang.Object readResolve();
}
-keep class **.R$* {
 *;
}
-keepclassmembers class * {
    void *(**On*Event);
}
#----------------------------------------------------------------------------

#---------------------------------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);
}
#----------------------------------------------------------------------------

七、错误日志的还原

问: 混淆之后出错了,如何处理?
混淆后的错误日志全是 a.b.c.d() 等等,需要通过mapping.txt文件还原;

操作步骤如下:

  1. cmd 进入sdk/tools/proguard/bin 目录。
  2. 将混淆后的日志和上文提到的 mapping 文件放入此目录中。
  3. 执行命令:retrace.bat mapping.txt XXX.txt。
2019-05-06 11:40:34 a740169405 阅读数 675

混淆文件基础配置

# 在这里添加项目的代码混淆规则

# 混淆规则请参考:http://proguard.sourceforge.net/index.html#manual/usage.html

##################### 一般使用默认 #####################

# 不使用大小写混合类名,混淆后的类名为小写

-dontusemixedcaseclassnames

# 混淆第三方库

-dontskipnonpubliclibraryclasses

# 混淆时记录日志,有助于排查错误

-verbose

# 代码混淆使用的算法.

-optimizations !code/simplification/arithmetic,!code/simplification/cast,!field/*,!class/merging/*

# 代码混淆压缩比,值在0-7之间,默认为5.

-optimizationpasses 5

# 优化时允许访问并修改有修饰符的类和类的成员

-allowaccessmodification

# native方法保留
-keepclasseswithmembernames,includedescriptorclasses class * {
    native <methods>;
}

# 保留枚举类不被混淆
-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}

# 保留行号
-keepattributes SourceFile,LineNumberTable

# 服务保留
-keep public class * extends android.app.Service