Android 代码混淆

一、基础概念

1. 混淆工具

  • R8:Android Gradle Plugin 3.4+ 默认,替代旧版 ProGuard,兼顾压缩、混淆、资源精简、Dex 优化,编译更快。
  • ProGuard:旧版混淆工具,现已废弃,仅兼容老项目。混淆三件事:
  1. 压缩 (Shrink) :删除未使用类、方法、字段;
  2. 混淆 (Obfuscate) :类 / 方法 / 字段改名成 a、b、c 缩短名称,反编译阅读困难;
  3. 优化 (Optimize) :精简代码逻辑、内联方法、删除无用分支。

2. 开启混淆开关(build.gradle Module)

gradle

arduino 复制代码
android {
    buildTypes {
        release {
            minifyEnabled true // 开启混淆+代码压缩
            shrinkResources true // 开启资源压缩(依赖minifyEnabled)
            // 混淆规则文件
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
        debug {
            minifyEnabled false // debug一般关闭,方便调试
        }
    }
}
  • proguard-android-optimize.txt:系统自带优化混淆规则;
  • proguard-rules.pro:自定义项目混淆规则。

二、核心混淆指令大全(最常用)

1. 保留类不被混淆

proguard

scala 复制代码
# 保留指定类完整不混淆
-keep class com.xxx.bean.User

# 保留包下所有类,不混淆
-keep class com.xxx.bean.** { *; }

# 保留父类是XXX的所有子类
-keep class * extends android.app.Activity

# 保留实现某接口的所有类
-keep class * implements android.view.View.OnClickListener

2. 保留类中成员(方法 / 字段)

proguard

csharp 复制代码
# 保留类所有成员
-keep class com.xxx.bean.User { *; }

# 只保留public方法和字段
-keep public class com.xxx.bean.User {
    public <fields>;
    public <methods>;
}

# 保留所有构造方法
-keep class com.xxx.bean.User {
    <init>;
}

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

3. 保留类名,允许混淆内部方法

proguard

kotlin 复制代码
-keepnames class com.xxx.bean.User

4. 保留反射相关(重中之重)

如果代码用反射调用类 / 方法,混淆后名称改变会报错,必须保留:

proguard

csharp 复制代码
# 保留反射用到的类
-keep class com.xxx.reflect.ReflectUtil { *; }
# 保留反射调用的方法
-keep class com.xxx.bean.User {
    void setName(java.lang.String);
    java.lang.String getName();
}

5. 不压缩、不删除(仅改名)

-dontshrink:关闭代码压缩; -dontoptimize:关闭代码优化; -dontobfuscate:完全关闭混淆(仅打包不改名)。

6. 忽略警告(第三方包大量告警时使用)

proguard

bash 复制代码
# 忽略所有警告(不推荐全局使用,优先精准忽略)
-dontwarn **
# 精准忽略某包警告
-dontwarn okhttp3.**

7. 输出映射文件(用于线上崩溃堆栈还原)

proguard

shell 复制代码
# 输出混淆映射文件,路径 build/outputs/mapping/release/mapping.txt
-printmapping mapping.txt

8. 泛型、注解、枚举保留

proguard

csharp 复制代码
# 保留注解
-keepattributes *Annotation*
# 保留泛型、异常行号、签名
-keepattributes Signature,Exceptions,SourceFile,LineNumberTable
# 枚举必须保留
-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.Str

三、Android 四大组件固定混淆规则(必须加)

系统通过反射启动四大组件,一旦混淆改名会直接崩溃:

proguard

scala 复制代码
# Activity
-keep public class * extends android.app.Activity
-keep public class * extends androidx.appcompat.app.AppCompatActivity
# Service
-keep public class * extends android.app.Service
# BroadcastReceiver
-keep public class * extends android.content.BroadcastReceiver
# ContentProvider
-keep public class * extends android.content.ContentProvider

# 所有组件的构造方法、生命周期方法
-keepclassmembers class * extends android.app.Activity {
   public void *(android.view.View);
}

四、View 自定义控件规则

XML 布局中通过 class="xxx.xxxView" 反射创建,不能混淆:

proguard

csharp 复制代码
# 保留所有自定义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);
}
# 布局onClick点击方法(xml android:onClick)
-keepclassmembers class * {
    void *(android.view.View);
}

五、JSON 实体类必加规则(Gson/Jackson/FastJson)

实体类字段被混淆后,序列化 / 反序列化字段名不匹配,解析失败:

通用方案:所有实体类统一保留

proguard

csharp 复制代码
# 假设所有bean放在 com.xxx.bean 包
-keep class com.xxx.bean.** { *; }

Gson 专用规则

proguard

diff 复制代码
-keepattributes Signature
-keepattributes *Annotation*
# 保留序列化实体
-keep class com.google.gson.** {*;}
-keep class com.xxx.bean.** {
    <fields>;
}

六、混淆常见踩坑点 & 注意事项

1. 反射相关类 / 方法不保留 → 运行崩溃

场景:Gson 解析、EventBus、JS 交互、动态跳转、反射工具类。解决方案:精准 -keep 对应类和方法。

2. XML 自定义 View、onClick 方法被混淆

布局反射创建 View、点击方法找不到,闪退。解决方案:添加自定义 View 专属 keep 规则。

3. 第三方 SDK 忘记加混淆规则

现象:打包成功,运行报 NoSuchMethod / ClassNotFound。解决方案:去 SDK 官方文档复制配套混淆规则。

4. 枚举、Parcelable Creator 丢失

序列化传参直接报错,必须单独保留枚举与 CREATOR 字段。

5. 线上崩溃堆栈看不懂

原因:没开启 printmapping 输出 mapping.txt,无法还原混淆后的类名。解决方案:打包 release 后保存 mapping 文件,用于崩溃日志还原。

6. 开启资源压缩后图片 / 布局丢失

gradle

arduino 复制代码
shrinkResources true

未引用资源会被删除,若代码动态加载资源,添加资源保留:

proguard

bash 复制代码
# 保留指定资源
-keepresource xml layout/main

7. 混淆后调试困难

  • debug 环境关闭混淆;
  • release 如需调试,可临时添加 -dontobfuscate 关闭混淆。

8. 组件、Service、BroadcastReceiver 类名混淆

AndroidManifest 中写死类全名,混淆改名后系统找不到组件,直接闪退,四大组件必须全部 keep。

七、AGP 8.x/ 9.x 新版 rules.keep 完整说明(纠正误区:不是替代 proguard-rules.pro

1、先澄清核心误区

  1. rules.keep 不是放全部混淆规则的文件 ,它只放R8 专属轻量 keep 保留规则
  2. 传统 proguard-rules.pro 依然完全生效,两者是互补关系,不是替换
  3. 你看到的 rules.keep 是 Android Studio 新版模板自动生成的R8 专用保留规则文件 ,语法简化、仅支持 -keep 系列指令,不支持 -dontwarn-printmapping、优化开关等完整 ProGuard 指令。

2、三种规则文件完整区分(AGP 8+ 共存)

1. proguard-rules.pro(传统全量混淆文件,项目主规则)

  • 支持全部 ProGuard/R8 语法-keep / -dontwarn / -printmapping / -keepattributes / -dontoptimize 等;
  • 放项目全局通用规则:四大组件、Gson 实体、第三方 SDK、JNI、输出 mapping、全局警告忽略;
  • build.gradle 显式注册:

gradle

java 复制代码
proguardFiles getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro"

2. rules.keep(新版轻量 R8 keep 专用文件)

特点

  • 仅支持 keep/keepclassmembers/keepnames保留类规则
  • 不支持全局配置、警告忽略、映射文件、优化开关;
  • 无需在 gradle 手动注册,R8 自动读取模块下 src/main/rules.keep
  • 语法更简洁,只写「哪些类不能被删 / 改名」,适合放业务 Bean、自定义 View、反射类;
  • 推荐放纯业务自定义类 keep 规则,把反射 / 序列化类抽离到这里,精简 proguard-rules.pro

示例 rules.keep 内容(只写 keep):

plaintext

csharp 复制代码
# 网络实体
-keep class com.xxx.bean.** { *; }
# 自定义View
-keep class com.xxx.view.** {
    public <init>(android.content.Context);
    public <init>(android.content.Context, android.util.AttributeSet);
}
# JS交互类
-keep class com.xxx.js.JsInterface { <methods>; }

3. consumer-rules.pro(仅 Library 模块生效)

给第三方库对外 API 保留规则,App 模块不读取,库打包时自动传递给依赖它的 App。

3、两者分工最佳实践(新版项目标准分层)

1. rules.keep 只放:纯 keep 保留规则(自己写的业务类)

适合:

  • 所有 JSON 实体 Bean
  • 自定义 View、自定义注解类
  • JS 交互、JNI 交互类
  • ARouter/EventBus 反射相关类、接口实现
  • 自己手写反射用到的类、方法

2. proguard-rules.pro 放:全局配置、框架、系统规则、杂项指令

必须放这里(rules.keep 不支持):

  1. 全局属性保留:-keepattributes *Annotation*,Signature,LineNumberTable
  2. 输出 mapping 日志:-printmapping mapping.txt
  3. 第三方 SDK 忽略警告:-dontwarn okhttp3.**
  4. 优化开关:-dontshrink / -dontobfuscate(调试临时用)
  5. 系统通用基础规则(四大组件、Parcelable、枚举、native 通用模板)

4、底层执行顺序

  1. SDK 默认规则 proguard-android-optimize.txt 最先加载;
  2. 自动读取 rules.keep 所有 keep 规则;
  3. 再加载手动注册的 proguard-rules.pro
  4. 规则冲突以后加载的为准(proguard-rules 优先级高于 rules.keep)。

5、常见疑问解答

1. 能不能只写 rules.keep,删掉 proguard-rules.pro

不可以 。rules.keep 不支持 -dontwarn-keepattributes、映射文件、全局优化配置,删掉会出现:

  • 注解 / 泛型被删除,Gson、反射直接报错;
  • 第三方库大量编译警告;
  • 无法生成 mapping.txt,线上崩溃堆栈无法还原。

2. 老项目没有 rules.keep 需要新建吗?

可选。

  • 不想拆分:全部规则仍写在 proguard-rules.pro 完全兼容;
  • 想分层管理:新建 src/main/rules.keep,把业务类 keep 迁移进去,精简主混淆文件。

3. 自己写的类、接口、方法放哪里 keep?

  • -keep 保留规则 → 放到 rules.keep(整洁分层);
  • 需要搭配 -dontwarn、全局属性、映射配置 → 留在 proguard-rules.pro

4. 混淆失效、类被删除排查

  1. 反射类只写在 rules.keep 没问题;
  2. 如果需要保留泛型 / 注解,必须在 proguard-rules.pro 添加 -keepattributes Signature,*Annotation*
  3. 第三方 SDK 警告报错,只能在 proguard-rules 加 -dontwarn

6、最简分层模板示例

src/main/rules.keep(只放业务 keep)

plaintext

csharp 复制代码
# 网络、本地存储实体
-keep class com.xxx.bean.** { *; }
# 自定义控件
-keep class com.xxx.widget.** {
    public <init>(android.content.Context);
    public <init>(android.content.Context, android.util.AttributeSet);
}
# EventBus 订阅方法
-keepclassmembers class ** {
    @org.greenrobot.eventbus.Subscribe <methods>;
}
# JS交互
-keep class com.xxx.bridge.JsApi { <methods>; }

proguard-rules.pro(全局配置 + 系统通用规则)

proguard

scala 复制代码
# 输出混淆映射
-printmapping mapping.txt
# 保留注解、泛型、行号
-keepattributes *Annotation*,Signature,Exceptions,SourceFile,LineNumberTable

# 四大组件通用
-keep public class * extends android.app.Activity
-keep public class * extends androidx.appcompat.app.AppCompatActivity
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider

# Parcelable
-keep class * implements android.os.Parcelable {
  public static final android.os.Parcelable$Creator *;
}

# JNI native
-keepclasseswithmembernames class * {
    native <methods>;
}

# 第三方库忽略警告
-dontwarn okhttp3.**
-dontwarn retrofit2.**

7、总结一句话

rules.keep 是 AGP8+ 新增的轻量专用 keep 规则文件 ,只用来存放你自己业务类的保留指令;传统 proguard-rules.pro 依然是主混淆配置文件,承载全局属性、警告、映射、系统组件、第三方 SDK 完整配置,两者配合使用,不是替换关系。

相关推荐
apihz4 小时前
台风实时与历史详情查询免费 API 接口完整教程
android·开发语言·tcp/ip·dubbo·台风·天气预报
浪客川5 小时前
AOSP源码隐藏状态栏
android·aosp
没有了遇见5 小时前
AI Agent 是什么?—— 一文理解 LLM、Memory、Skills、Tools、MCP、Workflow,Context
android·前端·程序员
御坂嘀喵6 小时前
Speed Tools:一套低侵入的 Android 插件化 + 动态换肤 + 字体切换框架
android·gitee
浮江雾6 小时前
Flutter第三节----Dart中的数据类型
android·开发语言·学习·flutter·入门·函数
风和先行6 小时前
Android 数据库相关学习总结
android·数据库·学习
杉氧6 小时前
Compose 渲染内核 (3):Slot Table 与 Gap Buffer —— 极速重组的数学艺术
android·架构·android jetpack
AFinalStone7 小时前
Android 7系统网络(五)Framework层(上)—ConnectivityService核心机制
android·网络
阿巴斯甜7 小时前
ContentObserver的使用:
android