ProGuard工具通过删除未使用的代码,使用语义模糊的名字重命名类、字段和方法的方式,减少、优化和混淆你的代码。结果生成一个更小的,更难被反向工程的.apk文件。因为ProGuard使你的应用程序更难反向工程,当你发布的应用程序使用对安全敏感功能的时候,使用它尤为重要。
ProGuard已经被集成到Android的构建系统中,所以你不需要手动的调用它。ProGuard仅仅当你在release模式构建你的应用程序时运行,所以你不需要在Debug模式的时候处理被混淆的代码。运行ProGuard是完全可选的,但是强烈推荐。
这个文档描述了如何启动和配置ProGuard,以及使用retrace工具解码被混淆的堆栈跟踪。
启动ProGuard
————————————————————————————————————————————————————————————
当你创建一个Android项目,在项目的根目录下自动生成一个proguard.cfg文件。这个文件定义了ProGuard如何优化和混淆你的代码,所以你知道如何根据你的需要定制它是非常重要的。默认的配置文件仅仅涵盖一般情况,所以你很可能为了你自己的需求必须编辑它。阅读下面Configuring ProGuard的章节了解定制ProGuard配置文件的信息。
为了启动ProGuard使它作为Ant或者Eclipse构建的一部分,设置<project_root>/project.properties文件中的proguard.config属性。这个路径可以是绝对路径或者一个相对项目根目录的路径。
注意:当使用Android Studio,你必须向你的gradle.build文件添加构建类型。更多信息,查阅Gradle Plug User Guid。
如果你放置proguard.cfg文件在它的默认位置(项目的跟目录),你像这样指定它的位置:
proguard.config=proguard.cfg
你也能将文件移动到任意你想要的位置,并且指定它的绝对路径:
proguard.config=/path/to/proguard.cfg
当你以Release模式构建你的应用程序,通过运行ant发布或者通过使用Eclipse的导出向导,构建系统自动检查是否proguard.config属性是否设置。如果它设置了,ProGuard在把所有东西打包到.apk文件之前自动处理应用程序字节码。在Debug模式不调用ProGuard,以为它使得调试更难处理。
在ProGuard运行后输出下面的文件:
dump.txt
描述了在apk文件所有class文件的内部结构
mapping.txt
列出了原始和被混淆类,方法和成员之间名称的映射。这个文件当你从release构建收到Bug报告的时候非常重要,因为它将混淆的堆栈转义回原来的类,方法,和成员名称。更多信息查阅Decoding Obfuscated Stack Traces。
seeds.txt
列出了没有被混淆的类和成员。
usage.txt
列出了从.apk被删除的代码
这些文件被放置在下面的目录:
- <project_root>/bin/proguard如果你使用Ant。
- <project_root>/proguard如果你使用Eclipse。
注意:每次你在release模式运行一次构建,这些文件都被ProGuard最新生成的文件覆盖。每次你发布你的应用程序保存它们的复本,为了从你的release构建反混淆Bug报告。更多关于为什么保存这些文件是重要的信息,查看Debugging considerations for published applications。
配置ProGuard
—————————————————————————————————————————————————————————————
对于一些情况,在proguard.cfg文件中的默认配置将足够了。然而,很多情况下ProGuard很难分析正确,并且它可能移除它认为没有被使用的代码,但是你的应用程序实际上需要。这些情况包括:
- 仅仅在AndroidManifest.xml文件引用的类
- 在JNI被调用的方法
- 动态引用的文件和方法
默认的proguard.cfg文件试图覆盖一般情况,但是你可能遇到异常,例如ClassNotFoundException,当ProGuard删除你的应用程序调用的一个整个类时发生。
当ProGuard删除你的代码的时候,你能通过在proguard.cfg文件中添加一个-keep行来解决这个错误。例如:
-keep public class <MyClass>
当使用-keep选项的时候有许多选项和注意事项,所以它强烈要求你阅读ProGuard Manual关于自定义你的配置文件的信息。Keep选项概览和Examples章节尤其有帮助。ProGuard手册的Troubleshooting章节概述了当你的代码被删除的时候可能遇见的其它问题 。
解码混淆栈跟踪
—————————————————————————————————————————————————————————————
当你的被混淆的代码输出一个堆栈跟踪的时候,这个方法名称被混淆了,如果不是不可能的话,它也使得调试更难。幸运的是,每当ProGuard运行的时候,它输出一个<project_root>/bin/proguard/mapping.txt文件,它显示了你的原始类,方法,和成员名称映射到它们的被混淆的名称。
在Window上的retract.bat脚本或者在Linux或者Mac OS X的retrace.sh脚本,能将被混淆的堆栈转换成可读的。它被放置在<sdk_root>/tools/proguard/目录。运行retract工具的语法是:
retrace.bat|retrace.sh [-verbose] mapping.txt [<stacktrace_file>]
例如:
retrace.bat -verbose mapping.txt obfuscated_trace.txt
如果你没有指定<stacktrace_file>值,retrace工具从标准输入读取。
发布程序调试注意事项
保存每次你给你的用户发布应用的mapping.txt文件。通过保留每次release构建的mapping.txt的复本,你确保了如果用户遭遇到了一个Bug,你能调试问题,并且提交一个混淆过的堆栈跟踪。项目的mapping.txt文件在你每次执行一个release构建的时候被覆盖,所以你必须小心保存你需要的版本。
例如,你发布应用程序,继续开发应用程序新版本的新功能。然后你不久后使用ProGuard执行新的release构建。这次构建覆盖了前面的mapping.txt文件。用户提交了从来自当前发布的应用程序Bug报告,包含栈跟踪信息。你不能在你的应用程序中调试用户的栈跟踪信息,因为和这个版本相关的mapping.txt文件在用户的设备上不存在了。还有其它的情况你的mapping.txt文件能被覆盖,所以确保你为你预测需要测试的每一个版本保存一个副本。
如何保存这个mapping.txt文件你来决定。例如,你能重命名它们来包含版本或者构建号,或者你可以和你的源代码一起对它们进行版本控制。
Android Developers:ProGuard