Android ProGuard 代码混淆详解
ProGuard 是 Android 开发中常用的代码混淆工具,它通过检测和移除未使用的类、字段、方法,优化字节码,以及用短名称混淆类名和方法名,使 APK 难以被逆向工程。本文从启用配置到混淆规则编写,全面介绍 ProGuard 的使用方法。
1、ProGuard 的作用
ProGuard 提供三大核心功能:
• 压缩(Shrink):检测并移除未使用的类、字段、方法和属性,包括依赖库中未使用的项,也是解决 64k 引用限制的变通方式
• 优化(Optimize):优化字节码,移除未使用的代码指令,减小 APK 体积
• 混淆(Obfuscate):用短名称重命名类、字段和方法,增加逆向工程难度
2、启用 ProGuard
在模块级 build.gradle 的 release 构建类型中启用混淆:
android {
buildTypes {
release {
minifyEnabled true // 启用代码压缩和混淆
zipAlignEnabled true // Zipalign 优化
shrinkResources true // 移除无用的资源文件,必须和 minifyEnabled 一起使用
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'),
'proguard-rules.pro'
}
}
}注意事项:
• 代码混淆会拖慢构建速度,应仅在 release 构建中启用
• Android Studio 使用 Instant Run 时会自动停用 ProGuard
• shrinkResources 必须和 minifyEnabled 一起使用
3、配置文件说明
ProGuard 涉及两个配置文件:
3.1、proguard-android.txt 与 proguard-android-optimize.txt
两个文件的核心区别在于是否开启优化:
• proguard-android.txt:配置了 -dontoptimize 和 -dontpreverify,关闭优化和预校验
• proguard-android-optimize.txt:开启了优化,并配置了经过验证的安全优化算法
# proguard-android.txt
-dontoptimize
-dontpreverify
# proguard-android-optimize.txt
-optimizations !code/simplification/arithmetic,!code/simplification/cast,!field/*,!class/merging/*
-optimizationpasses 5
-allowaccessmodification
-dontpreverify建议使用 proguard-android-optimize.txt,但需注意优化可能带来的风险,务必充分测试。
3.2、proguard-rules.pro
项目自定义的混淆规则文件,用于指定需要保留不混淆的类、方法和字段。
4、常用混淆规则
4.1、保留指令说明
ProGuard 提供多种保留指令:
• -keep:防止类和成员被移除或被重命名
• -keepnames:防止类和成员被重命名,但允许被移除
• -keepclassmembers:仅防止成员被移除或重命名
• -keepclasseswithmembers:保留类中包含指定成员的类及其成员
• -keepclassmembernames:仅防止成员被重命名
4.2、保留 Android 基础组件
# 保留 Activity 中参数是 View 的方法(避免 layout 中 onClick 指定方法无法调用)
-keepclassmembers class * extends android.app.Activity {
public void *(android.view.View);
}
# 保留 Native 方法
-keepclasseswithmembernames class * {
native <methods>;
}
# 保留自定义 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 * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
# 保留 Parcelable
-keepclassmembers class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator CREATOR;
}
# 保留 Serializable
-keepclassmembers class * implements java.io.Serializable {
static final long serialVersionUID;
private static final java.io.ObjectStreamField[] serialPersistentFields;
!static !transient <fields>;
private void writeObject(java.io.ObjectOutputStream);
private void readObject(java.io.ObjectInputStream);
java.lang.Object writeReplace();
java.lang.Object readResolve();
}4.3、保留第三方库
# 保留 Retrofit
-keepclasseswithmembers class * {
@retrofit2.http.* <methods>;
}
# 保留 Gson 序列化的实体类
-keep class com.example.bean.** { *; }
# 保留 OkHttp
-dontwarn okhttp3.**
-dontwarn okio.**
-keep class okhttp3.** { *; }
-keep interface okhttp3.** { *; }
# 保留 Glide
-keep public class * implements com.bumptech.glide.module.GlideModule
-keep class * extends com.bumptech.glide.module.AppGlideModule { <init>(android.content.Context, com.bumptech.glide.GlideBuilder); }
-keep public enum com.bumptech.glide.load.ImageHeaderParser { **[] values(); public ** valueOf(java.lang.String); }
# 保留 ButterKnife
-keep class butterknife.** { *; }
-dontwarn butterknife.internal.**
-keep class * { @butterknife.* <fields>; }4.4、保留反射相关类
# 保留与反射相关的类
-keep class com.example.reflect.** { *; }
# 保留内部类(如 Activity 中的 JSInterface)
-keepclasseswithmembers class com.example.MainActivity$JSInterface {
<methods>;
}5、混淆后定位问题
启用混淆后,Crash 堆栈中的类名和方法名会被替换为无意义的短名称,增加调试难度。
5.1、保留映射文件
在 build.gradle 中配置保留 mapping 文件:
android {
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'),
'proguard-rules.pro'
// 保留 mapping 文件,方便反混淆
mappingProguardFile "build/outputs/mapping/release/mapping.txt"
}
}
}5.2、使用 retrace 工具还原堆栈
SDK 中的 retrace 工具可以根据 mapping 文件将混淆后的堆栈还原为原始名称:
# 使用 retrace.sh 还原混淆后的堆栈
retrace.sh mapping.txt stacktrace.txt > original_stacktrace.txt6、常见问题与注意事项
6.1、常见混淆导致的错误
• Gson 反序列化失败:实体类被混淆后字段名改变,需用 -keep 保留实体类
• Retrofit 方法传参失败:需添加 -keepclasseswithmembers 保留 Retrofit 接口方法
• ButterKnife 绑定失败:需保留注解相关的类和字段
• 反射调用失败:反射使用的类和成员需保留
• JNI 方法找不到:Native 方法对应的 Java 方法需保留
6.2、调试建议
• 开发阶段使用 debug 构建(不启用混淆)
• release 构建前充分测试,覆盖所有功能模块
• 保存每次发布的 mapping.txt 文件,与对应版本 APK 关联
• 使用 -dontwarn 忽略第三方库的警告,避免构建失败
7、总结
ProGuard 是 Android 应用安全的重要防线,通过代码压缩、优化和混淆三重机制保护应用。正确配置混淆规则是关键,需要根据项目使用的第三方库逐一添加保留规则。建议在项目初期就建立混淆规则模板,随着依赖库的增减持续维护,确保每次 release 构建都能正常工作。

