Android Studio:ProGuard 混淆配置

赫连睿
2023-12-01

转载地址:https://blog.csdn.net/doris_d/article/details/52609703

在 Android Studio 中可通过配置 proguard-rules.pro 对生成的 apk 和 jar 进行加密,以免被轻易破解。(附:破解方法

Android Studio 创建Module后,会自动生成 proguard-rules.pro 文件,在其中添加需要的规则即可,另外需要配置 build.gradle,开启混淆功能。

    buildTypes {
        debug {
            buildConfigField "boolean", "LOG_DEBUG", "true"
            // VersionName后缀
            versionNameSuffix "-debug"
            minifyEnabled false
            zipAlignEnabled false
            shrinkResources false
        }
        release {
            // 不显示log
            buildConfigField "boolean", "LOG_DEBUG", "false"
            // 混淆
            minifyEnabled true
            // Zipalign优化
            zipAlignEnabled true
            // 移除无用的resource
            shrinkResources true
            // 混淆配置
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

其中,release 部分配置了开启混淆,保证打包 release 时会进行混淆。debug 不进行混淆,否则无法调试。

若需要混淆的 jar,那么在库类型的 moudle 中也需要配置 proguard-rules.pro 及 build.gradle,生成后即可在 build\intermediates\bundles\release 中获得混淆后的 jar。


ProGuard 简介

ProGuard 能够对 Java 类中的代码进行压缩(Shrink),优化(Optimize),混淆(Obfuscate),预检(Preveirfy)。 

  • 压缩(Shrink):检测和删除没有使用的类,字段,方法和属性。 

  • 优化(Optimize):对字节码进行优化,并且移除无用指令。 

  • 混淆(Obfuscate):使用 a,b,c 等无意义的名称,对类,字段和方法进行重命名。 

  • 预检(Preveirfy):主要是在 Java 平台上对处理后的代码进行预检。

常用规则如下:

斜体字 表示需要设置的参数,[ ] 中的内容表示可选的配置。

  • 【-assumenosideeffects class_specification

Assume that the specified methods don’t have any side effects, while 
optimizing.

假设调用不产生任何影响,在 proguard 代码优化时会将该调用 remove 掉。如 system.out.println 和 Log.v 等。
  • 1
  • 2
  • 【-dontwarn [class_filter]】

Don’t warn about unresolved references at all.

  • 【-dump [filename]】

Write out the internal structure of the processed class files, to the 
standard output or to the given file.

  • 【-keep [,modifier,…class_specification】 

Preserve the specified classes and class members.

  • 【-keepattributes [attribute_filter]】

Preserve the given optional attributes; typically Exceptions
InnerClassesSignatureDeprecatedSourceFileSourceDir
LineNumberTableLocalVariableTableLocalVariableTypeTable
SyntheticEnclosingMethod, and *Annotation*.

  • 【-keepclasseswithmembernames class_specification

Preserve the names of the specified classes and class members, if all 
of the specified class members are present (after the shrinking step).

  • 【-keepclassmembers [,modifier,…class_specification】 

Preserve the specified class members, if their classes are preserved 
as well.

  • 【-keepnames class_specification

Preserve the names of the specified classes and class members (if they 
aren’t removed in the shrinking step).

  • 【-libraryjars class_path】 

Specifies the library jars (or wars, ears, zips, or directories).

应用的依赖包,如 android-support-v4。
  • 1
  • 2
  • 【-optimizationpasses n】 

The number of optimization passes to be performed.

  • 【-optimizations  optimization_filter】 

The optimizations to be enabled and disabled.

  • 【-printmapping [filename]】

Print the mapping from old names to new names for classes and class 
members that have been renamed, to the standard output or to the given 
file.

  • 【-printseeds [filename]】

List classes and class members matched by the various -keep options, 
to the standard output or to the given file.

  • 【-printusage [filename]】

List dead code of the input class files, to the standard output or to 
the given file.


ProGuard 常用配置

android sdk 的 /sdk/tools/proguard/proguard-android.txt 中已经提供了基本的混淆配置,不需要在 proguard-rules.pro 中重复配置。

sdk 提供的 proguard-android.txt 中提供的默认配置说明参见 Android : proguard-android.txt 解析

除此之外,需要在 proguard-rules.pro 中添加的常用配置如下:

######################## 公共 ########################

#指定代码的压缩级别
-optimizationpasses 5

# 混淆时所采用的算法
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*

#记录生成的日志数据,gradle build时在本项目根目录输出
#apk 包内所有 class 的内部结构
-dump class_files.txt
#未混淆的类和成员
-printseeds seeds.txt
#列出从 apk 中删除的代码
-printusage unused.txt
#混淆前后的映射
-printmapping mapping.txt

#移除log代码
-assumenosideeffects class android.util.Log {
    public static *** v(...);
    public static *** i(...);
    public static *** d(...);
    public static *** w(...);
    public static *** e(...);
}

#不混淆反射用到的类
-keepattributes Signature
-keepattributes EnclosingMethod

#保持继承自系统类的class不被混淆
-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 interface android.support.v4.app.** { *; }
-keep class android.support.v4.** { *; }
-keep public class * extends android.support.v4.**
-keep interface android.support.v7.app.** { *; }
-keep class android.support.v7.** { *; }
-keep public class * extends android.support.v7.**
-keep public class * extends android.app.Fragment
-keep class * extends android.**{*;}

#不混淆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();
}

######################## Module自定义 ########################

############ 不混淆引用的jar ############

#不混淆butterknife
-keepclasseswithmembernames class * {
    @butterknife.* <fields>;
}
-keepclasseswithmembernames class * {
    @butterknife.* <methods>;
}
-dontwarn butterknife.internal.**

#不混淆AndroidBootstrap
-keep class com.beardedhen.androidbootstrap.**{*;}
-dontwarn com.beardedhen.androidbootstrap.**

#不混淆应用宝自更新jar
-keep class com.qq.**
-dontwarn com.qq.**
-keep class com.tencent.**
-dontwarn com.tencent.**

############ 保持自定义控件不被混淆 ############

-keepclasseswithmembernames class * {
    public <init>(android.content.Context);
}
-keepclasseswithmembernames class * {
    public <init>(android.content.Context, android.util.AttributeSet);
}
-keepclasseswithmembernames class * {
    public <init>(android.content.Context, android.util.AttributeSet, int);
}
-keepclasseswithmembernames class * {
    public <init>(android.content.Context, android.util.AttributeSet, int, int);
}

############ 项目内部类的混淆配置 ############

#不混淆整个包
#-keep class com.test.test.**{*;}

#不混淆对外接口的public类名和成员名,否则外部无法调用
#-keep public interface com.test.test.**{*;}
#-keep public enum com.test.test.**{*;}
#-keep public class com.test.test.**{
#    public *;
#}

#忽略项目中其他Module的警告 ############
#-dontwarn com.test.test.**
  • 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

注意事项

  • 反射用到的类不能混淆,JNI 方法不混淆

  • AndroidMainfest 中的类不混淆

  • 四大组件和 Application 的子类和 Framework 层下所有的类默认不会进行混淆

  • Parcelable 的子类和 Creator 静态成员变量不混淆,否则会产生 android.os.BadParcelableException 异常

  • 使用 GSON、fastjson 等框架时,所写的 JSON 对象类不混淆,否则无法将 JSON 解析成对应的对象

  • 使用第三方开源库或者引用其他第三方的SDK包时,需要在混淆文件中加入对应的混淆规则

  • 有用到 WEBView 的 JS 调用也需要保证写的接口方法不混淆


参考资料

 类似资料: