• android 如何混淆以及排查混淆后不明Bug


    前言

    混淆是保护apk的必要手段,通过混淆,如果apk被反编译,会对一些关键词使用a,b,c之类的字符替换,加大解读难度

    如何混淆

    在build.gradle文件中配置如下代码:

    android {
        buildTypes {
        debug {
                ...
            }
            release {
                //混淆开关
                minifyEnabled true
                // 是否zip对齐
                zipAlignEnabled true
                // 移除无用的resource文件
                shrinkResources false
                // 是否打开debuggable开关
                debuggable false
                // 是否打开jniDebuggable开关
                jniDebuggable false
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
                signingConfig signingConfigs.myConfig
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    minifyEnabled为true,就是打开混淆。主要的配置规则是在proguard-rules.pro文件中进行,

    混淆规则

    混淆设置参数

    -optimizationpasses 5                       # 代码混淆的压缩比例,值介于0-7,默认5
    -verbose                                    # 混淆时记录日志
    -dontoptimize                               # 不优化输入的类文件
    -dontshrink                                 # 关闭压缩
    -dontpreverify                              # 关闭预校验(作用于Java平台,Android不需要,去掉可加快混淆)
    -dontoptimize                               # 关闭代码优化
    -dontobfuscate                              # 关闭混淆
    -ignorewarnings                             # 忽略警告
    -dontwarn com.squareup.okhttp.**            # 指定类不输出警告信息
    -dontusemixedcaseclassnames                 # 混淆后类型都为小写
    -dontskipnonpubliclibraryclasses            # 不跳过非公共的库的类
    -printmapping mapping.txt                   # 生成原类名与混淆后类名的映射文件mapping.txt
    -useuniqueclassmembernames                  # 把混淆类中的方法名也混淆
    -allowaccessmodification                    # 优化时允许访问并修改有修饰符的类及类的成员
    -renamesourcefileattribute SourceFile       # 将源码中有意义的类名转换成SourceFile,用于混淆具体崩溃代码
    -keepattributes SourceFile,LineNumberTable  # 保留行号
    -keepattributes *Annotation*,InnerClasses,Signature,EnclosingMethod # 避免混淆注解、内部类、泛型、匿名类
    -optimizations !code/simplification/cast,!field/ ,!class/merging/   # 指定混淆时采用的算法
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    保持不被混淆的设置

    [保持命令] [] {
        [成员] 
    }
    
    
    -keep                           # 防止类和类成员被移除或被混淆;
    -keepnames                      # 防止类和类成员被混淆;
    -keepclassmembers	            # 防止类成员被移除或被混淆;
    -keepclassmembernames           # 防止类成员被混淆;
    -keepclasseswithmembers         # 防止拥有该成员的类和类成员被移除或被混淆;
    -keepclasseswithmembernames     # 防止拥有该成员的类和类成员被混淆;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    具体的类
    访问修饰符 → publicprivateprotected
    通配符(*) → 匹配任意长度字符,但不包含包名分隔符(.)
    通配符(**) → 匹配任意长度字符,且包含包名分隔符(.)
    extends → 匹配实现了某个父类的子类
    implements → 匹配实现了某接口的类
    $ → 内部类
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    成员

    匹配所有构造器 → <init>
    匹配所有域 → <field>
    匹配所有方法 → <methods>
    访问修饰符 → publicprivateprotected
    除了 *** 通配符外,还支持 *** 通配符,匹配任意参数类型
    ... → 匹配任意长度的任意类型参数,如void test(...)可以匹配不同参数个数的test方法
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    常用自定义混淆规则范例

    # 不混淆某个类的类名,及类中的内容
    -keep class cn.coderpig.myapp.example.Test { *; }
     
    # 不混淆指定包名下的类名,不包括子包下的类名
    -keep class cn.coderpig.myapp*
     
    # 不混淆指定包名下的类名,及类里的内容
    -keep class cn.coderpig.myapp* {*;}
     
    # 不混淆指定包名下的类名,包括子包下的类名
    -keep class cn.coderpig.myapp**
     
    # 不混淆某个类的子类
    -keep public class * extends cn.coderpig.myapp.base.BaseFragment
     
    # 不混淆实现了某个接口的类
    -keep class * implements cn.coderpig.myapp.dao.DaoImp
     
    # 不混淆类名中包含了"entity"的类,及类中内容
    -keep class **.*entity*.** {*;}
     
    # 不混淆内部类中的所有public内容
    -keep class cn.coderpig.myapp.widget.CustomView$OnClickInterface {
        public *;
    }
     
    # 不混淆指定类的所有方法
    -keep cn.coderpig.myapp.example.Test {
        public <methods>;
    }
     
    # 不混淆指定类的所有字段
    -keep cn.coderpig.myapp.example.Test {
        public <fields>;
    }
     
    # 不混淆指定类的所有构造方法
    -keep cn.coderpig.myapp.example.Test {
        public <init>;
    }
     
    # 不混淆指定参数作为形参的方法
    -keep cn.coderpig.myapp.example.Test {
        public <methods>(java.lang.String);
    }
     
    # 不混淆类的特定方法
    -keep cn.coderpig.myapp.example.Test {
        public test(java.lang.String);
    }
     
    # 不混淆native方法
    -keepclasseswithmembernames class * {
        native <methods>;
    }
     
    # 不混淆枚举类
    -keepclassmembers enum * {
      public static **[] values();
      public static ** valueOf(java.lang.String);
    }
     
    #不混淆资源类
    -keepclassmembers class **.R$* {
        public static <fields>;
    }
     
    # 不混淆自定义控件
    -keep public class * entends android.view.View {
        *** get*();
        void set*(***);
        public <init>;
    }
     
    # 不混淆实现了Serializable接口的类成员,此处只是演示,也可以直接 *;
    -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();
    }
     
    # 不混淆实现了parcelable接口的类成员
    -keep class * implements android.os.Parcelable {
        public static final android.os.Parcelable$Creator *;
    }
     
    # 注意事项:
    # 
    # ① jni方法不可混淆,方法名需与native方法保持一致;
    # ② 反射用到的类不混淆,否则反射可能出问题;
    # ③ 四大组件、Application子类、Framework层下的类、自定义的View默认不会被混淆,无需另外配置;
    # ④ WebView的JS调用接口方法不可混淆;
    # ⑤ 注解相关的类不混淆;
    # ⑥ GSON、Fastjson等解析的Bean数据类不可混淆;
    # ⑦ 枚举enum类中的values和valuesof这两个方法不可混淆(反射调用);
    # ⑧ 继承ParceableSerializable等可序列化的类不可混淆;
    # ⑨ 第三方库或SDK,请参考第三方提供的混淆规则,没提供的话,建议第三方包全部不混淆;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100

    proguard-rules.pro

    ProGuard在AS中默认的配置文件是proguard-rules.pro
    我们常见的ProGuard文件主要包含如下几个部分:
    1.基本配置,设定混淆的规则等,基本配置是每个混淆文件必须存在的,并且此块内容大部分通用,可以直接copy。
    2.基本的keep项,多数Android工程都需要非混淆的内容,包括有四大组件等内容,此项内容也大部分通用,也可以直接copy。
    3.三方引入的lib包混淆,这个内容需要去各自的官网去查找对应的混淆添加代码。
    4.其他需要不混淆的内容,包括:实体类,json解析类,WebView及js的调用模块,与反射相关的类和方法。

    基本配置
    基本配置基本上变化不大,一般的项目可以直接copy

    #指定压缩级别
    -optimizationpasses 5
    
    #不跳过非公共的库的类成员
    -dontskipnonpubliclibraryclassmembers
    
    #混淆时采用的算法
    -optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
    
    #把混淆类中的方法名也混淆了
    -useuniqueclassmembernames
    
    #指定不去忽略非公共的库的类
    -dontskipnonpubliclibraryclasses
    
    #不做预检验,preverify是proguard的四大步骤之一,可以加快混淆速度
    #-dontpreverify
    
    # 忽略警告(?)
    #-ignorewarnings
    
    #混淆时不使用大小写混合,混淆后的类名为小写(大小写混淆容易导致class文件相互覆盖)
    -dontusemixedcaseclassnames
    
    #优化时允许访问并修改有修饰符的类和类的成员
    -allowaccessmodification
    
    #将文件来源重命名为“SourceFile”字符串
    #-renamesourcefileattribute SourceFile
    #保留行号
    -keepattributes SourceFile,LineNumberTable
    #保持泛型
    -keepattributes Signature
    # 保持注解
    -keepattributes *Annotation*,InnerClasses
    
    # 保持测试相关的代码
    -dontnote junit.framework.**
    -dontnote junit.runner.**
    -dontwarn android.test.**
    -dontwarn android.support.test.**
    -dontwarn org.junit.**
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    基本的项目配置
    多数是包括序列化,Android四大组件等基本内容的混淆keep,对于常规的项目而言区别不大,也可以进行copy

    # Parcelable
    -keep class * implements android.os.Parcelable {
      public static final android.os.Parcelable$Creator *;
    }
    # Serializable
    -keepnames class * implements java.io.Serializable
    -keepclassmembers class * implements java.io.Serializable {
        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();
    }
    
    # 保留R下面的资源
    -keep class **.R$* {*;}
    
    # 保留四大组件,自定义的Application,Fragment等这些类不被混淆
    -keep public class * extends android.app.Activity
    -keep public class * extends android.app.Fragment
    -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
    
    ## support
    -dontwarn android.support.**
    -keep class android.support.v4.app.** { *; }
    -keep interface android.support.v4.app.** { *;}
    -keep public class * extends android.support.v7.**
    -keep public class * extends android.support.annotation.**
    
    -keep public class * extends android.support.v4.view.ActionProvider {
        public <init>(android.content.Context);
    }
    
    # 保留枚举类不被混淆
    -keepclassmembers enum * {
        public static **[] values();
        public static ** valueOf(java.lang.String);
    }
    
    # 保留本地native方法不被混淆
    -keepclasseswithmembers class * {
        native <methods>;
    }
    
    # 对于带有回调函数的onXXEvent、**On*Listener的,不能被混淆
    -keepclassmembers class * {
        void *(**On*Event);
        void *(**On*Listener);
    }
    
    -keepclassmembers public class * extends android.view.View {
       void set*(***);
       *** get*();
    }
    
    #保留在Activity中的方法参数是view的方法,
    -keepclassmembers class * extends android.app.Activity {
       public void *(android.view.View);
    }
    
    # For XML inflating, keep views' constructoricon.png    自定义view
    -keep public class * extends android.view.View {
        public <init>(android.content.Context);
        public <init>(android.content.Context, android.util.AttributeSet);
        public <init>(android.content.Context, android.util.AttributeSet, int);
        public void set*(...);
    }
    
    # androidx 混淆
    -keep class com.google.android.material.** {*;}
    -keep class androidx.** {*;}
    -keep public class * extends androidx.**
    -keep interface androidx.** {*;}
    -dontwarn com.google.android.material.**
    -dontnote com.google.android.material.**
    -dontwarn androidx.**
    -printconfiguration
    -keep,allowobfuscation @interface androidx.annotation.Keep
    
    -keep @androidx.annotation.Keep class *
    -keepclassmembers class * {
        @androidx.annotation.Keep *;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88

    三方SDK的混淆
    三方SDK的混淆代码需要去各自的SDK官网上去查找,例如网易云信的

    ### nimlib
    -dontwarn com.netease.nim.**
    -keep class com.netease.nim.** {*;}
    
    -dontwarn com.netease.nimlib.**
    -keep class com.netease.nimlib.** {*;}
    
    -dontwarn com.netease.share.**
    -keep class com.netease.share.** {*;}
    
    -dontwarn com.netease.mobsec.**
    -keep class com.netease.mobsec.** {*;}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    其他混淆内容
    其他混淆内容比较杂,包括:实体类,json解析类,WebView及js的调用模块,与反射相关的类和方法。这个根据自己需要来做

    
    # WebView
    -dontwarn android.webkit.WebView
    -dontwarn android.net.http.SslError
    -dontwarn android.webkit.WebViewClient
    -keep public class android.webkit.WebView
    -keep public class android.net.http.SslError
    -keep public class android.webkit.WebViewClient
    -keep
     class com.mandala.healthserviceresident.vo.** { *; } #实体类不参与混淆
    -keep class com.mandala.healthserviceresident.http.** { *; } #实体类不参与混淆
    -keep class com.hacker.okhttputil.** { *; } #实体类不参与混淆
    -keep class net.sqlcipher.** { *; }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    -keep class 类所在的包.** { *; }
    log过滤

    -assumenosideeffects class android.util.Log {
        public static *** d(...);
        public static *** v(...);
    }
    
    • 1
    • 2
    • 3
    • 4

    混淆结果
    在添加混淆之后,在排查时我们可以对混淆和未混淆的类名进行记录和打印,在混淆文件中添加如下代码可以查看混淆编译的类及文件结构:

    # 混淆映射,生成映射文件
    -verbose
    -printmapping proguardMapping.txt
    #输出apk包内所有的class的内部结构
    -dump dump.txt
    #未混淆的类和成员
    -printseeds seeds.txt
    #列出从apk中删除的代码
    -printusage unused.txt
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    添加上述代码之后,会在生成release包时也同时生成三个日志文件,我们在排查混淆问题时可以以上述三个文件作为参考,快速排查。

    Bug排查

    我这边混淆完成以后,打包测试,发现网络能访问,但是提示失败,刚开始想的办法是抓包,然后发现实体类被设置成a,b之类的,这个是被混淆了,然后在混淆文件里keep一下,但是还有其他bug ,这样打包完成以后,如果没有有效的手段,只能是看着现象和混淆文件一个一个猜了,如果能在debug的时候发现Bug就很好排查了,排查方法就是在debug模式下,打开混淆
    打开方法很简单

      buildTypes {
            debug {
                minifyEnabled true
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            }
    
            release {
                zipAlignEnabled true
                shrinkResources true
                minifyEnabled true
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
                signingConfig signingConfigs.myConfig
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    就这样,然后debug进行排查就好了。正常开发的时候记得关掉,比较耗性能

    我用到的配置

    # Add project specific ProGuard rules here.
    # By default, the flags in this file are appended to flags specified
    # in D:\AndroidStudio\sdk/tools/proguard/proguard-android.txt
    # You can edit the include path and order by changing the proguardFiles
    # directive in build.gradle.
    #
    # For more details, see
    #   http://developer.android.com/guide/developing/tools/proguard.html
    
    # Add any project specific keep options here:
    
    # If your project uses WebView with JS, uncomment the following
    # and specify the fully qualified class name to the JavaScript interface
    # class:
    #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
    #   public *;
    #}
    
    
    
    # Optimizations: If you don't want to optimize, use the
    # proguard-android.txt configuration file instead of this one, which
    # turns off the optimization flags.  Adding optimization introduces
    # certain risks, since for example not all optimizations performed by
    # ProGuard works on all versions of Dalvik.  The following flags turn
    # off various optimizations known to have issues, but the list may not
    # be complete or up to date. (The "arithmetic" optimization can be
    # used if you are only targeting Android 2.0 or later.)  Make sure you
    # test thoroughly if you go this route.
    
    -optimizations !code/simplification/cast,!field/*,!class/merging/*
    -optimizationpasses 5
    -allowaccessmodification
    -dontpreverify
    
    
    # The remainder of this file is identical to the non-optimized version
    # of the Proguard configuration file (except that the other file has
    # flags to turn off optimization).
    -dontusemixedcaseclassnames
    -dontskipnonpubliclibraryclasses
    -verbose
    
    # 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.**
    
    -dontwarn org.apache.http.**
    -dontwarn com.amap.**
    -dontwarn com.alibaba.**
    -dontwarn com.netease.**
    -dontwarn io.netty.**
    -dontwarn com.autonavi.amap.**
    
    ### keep options
    #system default, from android example
    -keep public class * extends android.app.Activity
    -keep public class * extends androidx.fragment.app.Fragment
    -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
    
    -keepattributes *Annotation*,InnerClasses
    #-keepattributes SourceFile,LineNumberTable
    
    ### 3rd party jars
    -keep class android.support.** {*;}
    -keep class com.amap.** {*;}
    -keep class android.webkit.** {*;}
    
    
    ### 3rd party jars(lucene)
    -dontwarn java.nio.channels.SeekableByteChannel
    -dontwarn org.apache.lucene.**
    -keep class org.apache.lucene.** {*;}
    
    ### nimlib
    -dontwarn com.netease.nim.**
    -keep class com.netease.nim.** {*;}
    
    -dontwarn com.netease.nimlib.**
    -keep class com.netease.nimlib.** {*;}
    
    -dontwarn com.netease.share.**
    -keep class com.netease.share.** {*;}
    
    -dontwarn com.netease.mobsec.**
    -keep class com.netease.mobsec.** {*;}
    
    -keepclasseswithmembernames class * {
        native <methods>;
    }
    
    -keepclasseswithmembers class * {
        public <init>(android.content.Context, android.util.AttributeSet);
        public <init>(android.content.Context, android.util.AttributeSet, int);
    }
    
    -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 * 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 * {
       public <init> (org.json.JSONObject);
    }
    
    -keep   class com.amap.api.maps.**{*;}
    -keep   class com.amap.api.trace.**{*;}
    
    -keep class com.amap.api.location.**{*;}
    -keep class com.amap.api.fence.**{*;}
    
     -keep class com.alibaba.sdk.android.**{*;}
    
     -dontwarn demo.**
     -keep class demo.**{*;}
    
    # Bugly异常上报
     -dontwarn com.tencent.bugly.**
     -keep public class com.tencent.bugly.**{*;}
    
     -keep class com.umeng.** {*;}
     -keep class java.security.interfaces.*
     -keep class java.util.Base64
    
     -keep class org.repackage.** {*;}
    
     -keepclassmembers class * {
        public <init> (org.json.JSONObject);
     }
    
     -keepclassmembers enum * {
         public static **[] values();
         public static ** valueOf(java.lang.String);
     }
    
    -keep class org.greenrobot.greendao.**{*;}
    -keepclassmembers class * extends org.greenrobot.greendao.AbstractDao{
        public static java.lang.String TABLENAME;
    }
    -keep class **$Properties
    
    
    -keep class com.mandala.healthserviceresident.greendao.gen.**{*;}
    # If you do not use SQLCipher:
    -dontwarn org.greenrobot.greendao.database.**
    # If you do not use Rx:
    -dontwarn rx.**
    
    #Gson
    -keep class com.google.gson.** {*;}
    -keep class com.google.**{*;}
    -keep class com.google.gson.stream.** { *; }
    -keep class com.google.gson.examples.android.model.** { *; }
    #okhttp
    -dontwarn com.squareup.okhttp3.**
    -keep class com.squareup.okhttp3.** { *;}
    -dontwarn okio.**
    
    -keep class butterknife.** { *; }
    -dontwarn butterknife.internal.**
    -keep class **$$ViewBinder { *; }
    -keepclasseswithmembernames class * {
        @butterknife.* <fields>;
    }
    -keepclasseswithmembernames class * {
        @butterknife.* <methods>;
    }
    
    -keep class com.mandala.healthserviceresident.vo.** { *; } #实体类不参与混淆
    -keep class com.mandala.healthserviceresident.http.** { *; } #实体类不参与混淆
    -keep class com.hacker.okhttputil.** { *; } #实体类不参与混淆
    -keep class net.sqlcipher.** { *; }
    
    # WebView
    -dontwarn android.webkit.WebView
    -dontwarn android.net.http.SslError
    -dontwarn android.webkit.WebViewClient
    -keep public class android.webkit.WebView
    -keep public class android.net.http.SslError
    -keep public class android.webkit.WebViewClient
    
    -dontusemixedcaseclassnames
    -dontskipnonpubliclibraryclasses
    -verbose
    -ignorewarnings
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210

    重点看一下greendao的配置,如果没配置,会提示daoConfig出错

    -keep class org.greenrobot.greendao.**{*;}
    -keepclassmembers class * extends org.greenrobot.greendao.AbstractDao{
        public static java.lang.String TABLENAME;
    }
    -keep class **$Properties
    
    
    -keep class com.mandala.healthserviceresident.greendao.gen.**{*;}
    # If you do not use SQLCipher:
    -dontwarn org.greenrobot.greendao.database.**
    # If you do not use Rx:
    -dontwarn rx.**
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
  • 相关阅读:
    关于调参技巧的问题
    线程状态及线程之间通信
    【Audio】正弦波生成原理及C++代码
    银行业数据治理的实施路径——基于资产管理的视角
    6.DesignForPlacement\ExportHighlightedList
    海洋捕食者算法(Matlab代码实现)
    云服务器配置Code-Server环境并运行Python和C++
    C语言——程序环境和预处理
    IP地址、子网掩码与IP寻址【计算机网络】
    JavaScript设计模式中的享元模式
  • 原文地址:https://blog.csdn.net/jifashihan/article/details/127546121