Android代码混淆

混淆配置

android{
buildTypes {
        release {
            .......
            
            // 开启混淆会使编译时间变长,所以debug模式下建议不开启
            minifyEnabled true
            shrinkResources true
            
            // 这行代码定义了混淆规则由两部分构成:
            // 位于SDK的tools/proguard/文件夹中的proguard-android.txt的内容
            // 以及默认放置于模块根目录的proguard-rules.pro的内容
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            .......
            }
        }
}

混淆优点:减小Apk大小,提高代码安全

混淆proguard-rules.pro文件配置


# For native methods, see http://proguard.sourceforge.net/manual/examples.html#native
-keepclasseswithmembernames class * {
    native <methods>;
}

# 保留在Activity中的方法参数是view的方法,保证在layout中写的onClick不会被影响
# 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);
}

# 实现了序列化的类
-keepclassmembers class * implements android.os.Parcelable {
  public static final android.os.Parcelable$Creator CREATOR;
}

# ---------------------------------------------------------------------
# 上面都是默认配置,写在proguard-android.txt文件中,无需我们再次编写
# 下面代码是自己编写部分(根据自己项目编写)
# ---------------------------------------------------------------------

# 指定压缩级别
-optimizationpasses 5

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

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

# 把混淆类中的方法名也混淆了
-useuniqueclassmembernames

# 保持泛型
-keepattributes Signature

# 保持所有实现 Serializable 接口的类成员(默认Parcel)
-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();
}

# assume no side effects:删除android.util.Log输出的日志
-assumenosideeffects class android.util.Log {
    public static *** v(...);
    public static *** d(...);
    public static *** i(...);
    public static *** w(...);
    public static *** e(...);
}

# 抛出异常时保留代码行号
-keepattributes SourceFile,LineNumberTable
 
 # 保留自定义控件(继承自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*(***);
    *** get* ();
}

# 对于带有回调函数onXXEvent的,不能混淆
-keepclassmembers class * {
    void *(**On*Event);
}

# arouter 这种路由框架
-keep public class com.alibaba.android.arouter.routes.**{*;}
-keep public class com.alibaba.android.arouter.facade.**{*;}
-keep class * implements com.alibaba.android.arouter.facade.template.ISyringe{*;}

# glide 图片框架
-keep public class * implements com.bumptech.glide.module.GlideModule
-keep public class * extends com.bumptech.glide.module.AppGlideModule
-keep public enum com.bumptech.glide.load.ImageHeaderParser$** {
  **[] $VALUES;
  public *;
}

#  如果集成了bugly
-dontwarn com.tencent.bugly.**
-keep public class com.tencent.bugly.**{*;}

# 微信SDK
-keep class com.tencent.mm.opensdk.** { *; }

...

除了混淆配置文件以外,我们还可以在一些不想被混淆的代码之上加上Keep注解,哪怕我们打包之前在混淆配置文件中漏写了,也不会报错。如下图所示:
Android代码混淆

检查混淆结果

代码混淆后,需要检查混淆结果,避免BUG
Android代码混淆
这几个文件可以在最终打包之前,好好查查不需要混淆的代码是不是正常的

参考链接

  1. ProGuard代码混淆技术详解
  2. Android混淆方案
  3. Android如何优雅地防止Bean类混淆