Proguard
Proguard是一个压缩、优化、和混淆Java字节码文件的工具,它可以删除无用的代码,还可以使用简短的无意义的名称来重命名类、字段、方法。这样生成的.apk文件的体积更小,并且不太容易被反编译。
Proguard被集成到了Android编译系统中,所以你不用手动地在程序中调用它。Proguard只在release模式下运行,所以在debug模式下,不用处理混淆过的代码。虽然Proguard是可选的,但是Android强烈建议我们使用它。
这篇文章描述了如何启用和配置Proguard,以及使用retrace工具解码被混淆的堆栈跟踪。
启用Proguard
创建android应用程序时,会自动地在项目根目录中生成一个proguard.cfg文件,该文件是定义如何优化和混淆代码,因此要理解如何去配置它。默认地,该文件只处理一般的情况,大多数你需要在该文件中编写自己所需的配置。
通常使用Eclipse和Ant作为编译工具时,需要在<project_root>/project.properties文件中设置proguard.config属性,该属性值为proguard.cfg文件的路径。(注:当使用AndroidStudio,必须为gradle编译文件添加Proguard 编译类型)
当在release模式下编译时,如运行ant release ,或者是使用Eclipse中的Export选项,编译系统都会自动检查是否设置了proguard.config属性,如果设置了改选项则会在打包成.apk文件之前处理字节码。dubug模式下不会调用Proguard。
Proguard在运行之后会输出以下文件:
- dump.txt
描述.apk文件中所有class文件的内部结构。
- mapping.txt
混淆前后的代码对照表。可以用来解码被混淆的堆栈跟踪。
- seeds.txt
没有被混淆的类和成员列表。
- usage.txt
被删除的代码。
以上这些文件在如下目录:
如果使用ant release,则<project_root>/bin/proguard
如果使用Eclipse中的Export选项,则是在<project_root>/proguard
配置proguard
某些情况下,proguard.cfg文件中的默认配置就能满足需求了。然而,很多情况是Proguard不容易正确分析的,它会认为那是没有使用的代码,并将其移除,但是这些代码确实是你需要的代码。下面是一些例子:
- 一个仅在AndroidManifest.xml中被引用的类。
- 一个被JNI调用的方法。
- 动态引用的字段和方法。
默认的配置可能会抛出异常,如Proguard移除了一个类,而你的程序又调用了它,这个时候就会抛出ClassNotFoundException。可以使用-keep来避免该问题,如:
-keep public class <MyClass>
-keep有很多选项和条件,最好是在使用之前阅读Proguard手册以便获得更多关于配置的信息。解码混淆的堆栈跟踪(stack traces)
被混淆的代码输出的堆栈跟踪,方法名是被混淆了的,这让调试变得很难,但也不是不可能。之前有说过,groguard会生成mapping.txt,它描述了混淆前后代码的类、字段、方法的映射关系。retrace脚本(windows为retrace.bat,Linux和Mac OS X为retrace.sh)可以将混淆后的堆栈跟踪转换成可读性的。该脚本在<sdk_root>/tools/proguard目录下,运行retrace工具的语法为:
retrace.bat|retrace.sh [-verbose] mapping.txt [<stacktrace_file>]
例如:
retrace.bat -verbose mapping.txtobfuscated_trace.txt
如果不定义<stacktrace_file>,retrace工具会从标准输入中读取。
debug发布的应用
为每一个发布的应用保存对应的mapping.txt,当发生bug时,可以通过混淆后的堆栈跟踪来调试问题。每一次编译,都会覆盖mapping.txt文件,所以你应该为你的应用保留你所需要的版本的对应的mapping.txt文件。