ProGuard 是一个能对 java 字节码文件进行压缩、优化、混淆和预验证的免费工具。 ProGuard 可以删除 java 代码中无用的类、字段、方法和属性,可以重命名已经存在的类、字段、方法和属性。 ProGuard 常用于 Android 开发对项目进行混淆,增加项目代码被反编译的难度。 对于Android 项目,混淆是 ProGuard 中最重要的一个功能。
ProGuard 之所以可以保护 apk 并减小 apk 大小, 是因为其具有压缩、优化、混淆和预验证功能。 ProGuard 四大功能的工作顺序是压缩–>优化—>混淆—>预验证。 压缩:检测和删除项目中没有使用的类、字段、方法和属性。如果存在两个类互相调用,但项目实际上并没有使用到这两个类,这两个类也会被删除。 优化:优化代码的复杂调用,使代码运行顺序更为合理。 混淆:依据用户的配置,将代码的包名、类名、方法名和变量名等改成 a,b,c 等无意义的名称。 预验证:在 java 平台对处理后的代码进行预检,保证代码能够正常运行。这一步在 android 项目中不需要。
Java 源代码编译后产生二进制 class 文件,这个 class 文件可以反编译成 java 代码。反编译后生成的 java 代码除了原来的注释外,其他代码比如变量名、类名和方法名等基本都能看到,和 java 源代码几乎没有区别。为了防止项目代码被泄露,我们需要把项目代码中的包、类、方法和变量名等 java 元素的名称改成无意义的名称。这个过程就是混淆。 混淆之后的代码只是在一些名称上有修改,对代码的结构没有影响,所以混淆后的代码依然可以运行。 项目经混淆后并不是说代码就不能被反编译了,只是反编译混淆后的项目后看到的代码将不是源码,变量名变得不再能一眼看懂其意思,此时想弄懂原有的项目代码架构很难。 在混淆的过程中,不影响正常工作的信息将永久删除,使得反编译之后的代码变得更加难以理解。
Android Studio 已经集成了 ProGuard 工具。对 Android 项目进行混淆时,我们只需修改一些配置即可。随便打开一个 android 项目,在 app 目录下的 build.grade 文件中可以看到如下代码 以上图为例,minifyEnabled 置为 true 表示在 release 环境下启用 ProGuard 工具。在打包程序时,这一项必须置为 true, 否则 release 打出的包将没有压缩、优化、混淆。 proguardFiles 命令后面加了两个文件名。这两个文件是 ProGuard 的配置文件,启用 ProGuard 后, ProGuard 对项目的处理将遵循这两个文件的配置。'proguard-android.txt’ 是 Android Studio 集成 ProGuard 工具时自带的 ProGuard 配置文件,’proguard-rules.pro’ 是开发项目时由程序员添加的配置文件。 Android Studio 集成 ProGuard 工具的同时,给出了两个默认配置文件:’proguard-android.txt’和’proguard-android-optimize.txt’,两个文件的差别是使用’proguard-android.txt’将不会对项目代码进行优化。这两个文件可以在电脑 android SDK 安装目录下的 /tools/proguard 的目录下找到。 ‘proguard-rules.pro’ 文件可以在当前 android 项目 app 目录下找到。初始时此文件是空白的,开发者可以在这个文件中添加自己项目的ProGuard配置,不能在’proguard-android.txt’和’proguard-android-optimize.txt’中添加。 proguardFiles 后面可以加入多个文件名,意味着 ProGuard 工作会遵循多个文件的配置。比如
当在项目中配置了 minifyEnabled 为 true 时,如果不配置 ProGuard 文件,ProGuard 会混淆所有代码。而有些情况下,有些代码是不能混淆的,否则就会导致程序出错。常用的不能混淆的代码如下: 1.系统接口(Framework 层下所有的类) 2.Manifest 中声明的所有类 3.xml 中声明的所有资源名 4.使用反射的地方 5.使用第三方开源库或者引用其他第三方的SDK包时,需要在混淆文件中加入对应的混淆规则 6.JNI 方法 7.Parcelable的子类和Creator静态成员变量不混淆,否则会产生android.os.BadParcelableException 异常 8. 使用GSON、fastjson等框架时,所写的JSON对象类不混淆,否则无法将JSON解析成对应的对象 9.有用到WEBView的JS调用也需要保证写的接口方法不混淆 Android Studio 启用 ProGuard 工具后,会默认不混淆系统接口、Manifest 中声明的所有类和 xml 中声明的所有资源名, 因此这些情况下不需要手动配置 ProGuard 文件。而其他情况下不应该混淆的代码就需要对 ProGuard 文件进行配置。
ProGuard 配置通配符
? 匹配除包分隔符外的任意单个字符 * 匹配除包分隔符外的所有符号 ** 匹配多个字符(任意) % 匹配所有基本类型(不包含 void) *** 匹配任何类型 ! 不匹配 <init> 匹配所有构造函数 <fields> 匹配所有字段 <methods>匹配所有方法ProGuard 配置举例
-keep class com.ihs.** 不混淆所有com.ihs包下的类,换成具体的类名则表示不混淆某个具体的类 -keep class com.ihs.**{*;} 不混淆所有com.ihs包下的类和类中的所有成员变量 -keep class com.ihs.view.CustomImageView {public void setBackground(Bitmap);} 不混淆com.ihs.view.CustomImageView 类下的 public void setBackground(Bitmap) 方法 -keepclasseswithmembernames class * { 不混淆native 方法 native <methods>; } -keepclassmembers enum * { 不混淆 enum 类 public static **[] values(); public static ** valueOf(java.lang.String); } -keep public class * extends android.content.BroadcastReceiver 不混淆继承 android.content.BroadcastReceiver 的所有类 -keepattributes Exceptions,InnerClasses,Signature,LineNumberTable 不混淆异常,内部类,泛型,保留行号的属性ProGuard 是一个能对 java 字节码文件进行混淆、压缩、优化和预验证的免费工具。 ProGuard 可以删除 java 代码中无用的类、字段、方法和属性,并混淆代码 ,从而减小 APK 的大小。 打包 apk 上线时,代码是一定要混淆的,不然辛辛苦苦写的代码别人可以通过反编译看到源码。 有些情况下,代码是不能混淆的,否则就会导致程序出错。
