Android 代码混淆

01.什么是混淆

  • 混淆代码
    • 混淆分为两种代码混淆和资源文件混淆。实际的产品研发中为了防止自己的劳动成果被别人窃取,混淆代码能有效防止apk文件被反编译,进而查看源代码。
  • Android如何混淆
    • android提供了Progurd方式来混淆apk中的代码,其核心的逻辑是在代码层将一些易懂的源代码类名,方法名称替换成毫无意义的a、b、c、d…,这样当第三方反编译出你的Apk文件时,看到的源代码也无法还原其本身的逻辑,或者代码中方法,类,对象等变成无法阅读的字母。

02.混淆具体实践

2.1 gradle配置文件

  • 在android项目中找到module的gradle配置文件,添加proguard配置

    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
    buildTypes {
    debug {
    // 显示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 {
    // 不显示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
    }
    }

2.2 proguard-rules.pro文件

  • proguard-rules.pro文件

    • 该文件就是Android中的混淆配置文件
  • proguard-rules.pro文件

  • proguard混淆语法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    -libraryjars class_path 应用的依赖包,如android-support-v4  
    -keep [,modifier,...] class_specification 这里的keep就是保持的意思,意味着不混淆某些类
    -keepclassmembers [,modifier,...] class_specification 同样的保持,不混淆类的成员
    -keepclasseswithmembers [,modifier,...] class_specification 不混淆类及其成员
    -keepnames class_specification 不混淆类及其成员名
    -keepclassmembernames class_specification 不混淆类的成员名
    -keepclasseswithmembernames class_specification 不混淆类及其成员名
    -assumenosideeffects class_specification 假设调用不产生任何影响,在proguard代码优化时会将该调用remove掉。如system.out.println和Log.v等等
    -dontwarn [class_filter] 不提示warnning
  • 混淆原则

    • jni方法不可混淆
    • 反射用到的类不混淆(否则反射可能出现问题)
    • AndroidMainfest中的类不混淆,四大组件和Application的子类和Framework层下所有的类默认不会进行混淆
    • Parcelable的子类和Creator静态成员变量不混淆,否则会产生android.os.BadParcelableException异常
    • 使用GSON、fastjson等框架时,所写的JSON对象类不混淆,否则无法将JSON解析成对应的对象
    • 使用第三方开源库或者引用其他第三方的SDK包时,需要在混淆文件中加入对应的混淆规则
    • 有用到WEBView的JS调用也需要保证写的接口方法不混淆
  • 第三方库的混淆原则

    • 一般的第三方库都有自身的混淆方案,可直接引用其自身的混淆配置即可
    • 若无混淆配置,一般的可配置不混淆第三方库
  • 项目中实际的混淆方案

    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
    # Glide图片库的混淆处理
    -keep public class * implements com.bumptech.glide.module.GlideModule
    -keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** {
    **[] $VALUES;
    public *;
    }

    -optimizationpasses 5
    -dontusemixedcaseclassnames
    -dontskipnonpubliclibraryclasses
    -dontpreverify
    -verbose
    -optimizations !code/simplification/arithmetic,!field/*,!class/merging/*


    # Gson混淆脚本
    -keep class com.google.gson.stream.** {*;}
    -keep class com.youyou.uuelectric.renter.Network.user.** {*;}

    # butterknife混淆脚本
    -dontwarn butterknife.internal.**
    -keep class **$$ViewInjector { *; }
    -keepnames class * { @butterknife.InjectView *;}


    # -------------系统类不需要混淆 --------------------------
    -keep public class * extends android.app.Fragment
    -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.support.**
    -keep public class com.android.vending.licensing.ILicensingService


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

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

    # 保留我们自定义控件(继承自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);
    }

    -keepclassmembers enum * { # 保持枚举enum类不被混淆
    public static **[] values();
    public static ** valueOf(java.lang.String);
    }
    -keep class * implements android.os.Parcelable { # 保持Parcelable不被混淆
    public static final android.os.Parcelable$Creator *;
    }

    # --------- 忽略异常提示 --------------------
    -dontwarn butterknife.internal.**
    -dontwarn com.alipay.**
    -dontwarn com.mikepenz.**
    -dontwarn org.apache.**
    -dontwarn com.amap.**
    -dontwarn com.android.volley.**
    -dontwarn com.rey.**


    # ---------- 保持代码 --------------
    -keep class it.neokree.** {*;}
    -keep class org.apache.** {*;}
    -keep class com.iflytek.** {*;}
    -keep class com.google.protobuf.** { *; }


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

    # 热修复混淆
    -keep class * extends java.lang.annotation.Annotation
    -keep class com.alipay.euler.andfix.** { *; }
    -keepclasseswithmembernames class * {
    native <methods>;
    }

    # tencent
    -keep class com.tencent.mm.opensdk.** {*;}
    -keep class com.tencent.wxop.** {*;}
    -keep class com.tencent.mm.sdk.** {*;}


    # 腾讯bugly混淆
    -dontwarn com.tencent.bugly.**
    -keep public class com.tencent.bugly.**{*;}



    # 支付宝支付sdk混淆
    -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.sdk.app.H5PayCallback {
    <fields>;
    <methods>;
    }
    -keep class com.alipay.android.phone.mrpc.core.** { *; }
    -keep class com.alipay.apmobilesecuritysdk.** { *; }
    -keep class com.alipay.mobile.framework.service.annotation.** { *; }
    -keep class com.alipay.mobilesecuritysdk.face.** { *; }
    -keep class com.alipay.tscenter.biz.rpc.** { *; }
    -keep class org.json.alipay.** { *; }
    -keep class com.alipay.tscenter.** { *; }
    -keep class com.ta.utdid2.** { *;}
    -keep class com.ut.device.** { *;}


    # 阿里推送
    -keep class com.taobao.** {*;}
    -keep class com.alibaba.** {*;}
    -keep class com.alipay.** {*;}
    -dontwarn com.taobao.**
    -dontwarn com.alibaba.**
    -dontwarn com.alipay.**
    -keep class com.ut.** {*;}
    -dontwarn com.ut.**
    -keep class com.ta.** {*;}
    -dontwarn com.ta.**
    -keep class anet.**{*;}
    -keep class org.android.spdy.**{*;}
    -keep class org.android.agoo.**{*;}
    -dontwarn anet.**
    -dontwarn org.android.spdy.**
    -dontwarn org.android.agoo.**