[ProGuard](http://proguard.sourceforge.net/) 是一个在Android项目中广泛使用的压缩和混淆打包的源码的工具。
你是否使用ProGuard取决你项目的配置,当你构建一个release版本的apk时,通常你应该配置gradle文件。
~~~
buildTypes {
debug {
minifyEnabled false
}
release {
signingConfig signingConfigs.release
minifyEnabled true
proguardFiles 'proguard-rules.pro'
}
}
~~~
为了决定哪些代码应该被保留,哪些代码应该被混淆,你不得不指定一个或多个实体类在你的代码中。 这些实体应该是指定的类包含main方法,applets,midlets,activities,等等。 Android framework 使用一个默认的配置文件,可以在`SDK_HOME/tools/proguard/proguard-android.txt` 目录下找到。自定义的工程指定的 project-specific 混淆规则,如在`my-project/app/proguard-rules.pro`中定义, 会被添加到默认的配置中。
关于 ProGuard 一个普遍的问题,是看应用程序是否崩溃并报`ClassNotFoundException` 或者 `NoSuchFieldException` 或类似的异常, 即使编译是没有警告并运行成功。 这意味着以下两种可能:
1. ProGuard 已经移除了类,枚举,方法,成员变量或注解,考虑是否是必要的。
2. ProGuard 混淆了类,枚举,成员变量的名称,但是这些名字又被拿原始名称使用了,比如通过Java的反射。
检查`app/build/outputs/proguard/release/usage.txt`文件看有问题的对象是否被移除了。 检查`app/build/outputs/proguard/release/mapping.txt` 文件看有问题的对象是否被混淆了。
In order to prevent ProGuard from _stripping away_ needed classes or class members, add a `keep` options to your proguard config: 以防 ProGuard _剥离_ 需要的类和类成员,添加一个 `keep`选项在你的 proguard 配置文件中:
~~~
-keep class com.futurice.project.MyClass { *; }
~~~
防止 ProGuard _混淆_ 一些类和成员,添加 `keepnames`:
~~~
-keepnames class com.futurice.project.MyClass { *; }
~~~
查看[this template's ProGuard config](https://github.com/futurice/android-best-practices/blob/master/templates/rx-architecture/app/proguard-rules.pro) 中的一些例子。 更多例子请参考[Proguard](http://proguard.sourceforge.net/#manual/examples.html)。
**在构建项目之初,发布一个版本** 来检查ProGuard规则是否正确的保持了重要的部分。 同时无论何时你添加了新的类库,做一个发布版本,同时apk在设备上跑起来测试一下。 不要等到你的app要发布 "1.0"版本了才做版本发布,那时候你可能会碰到好多意想不到的异常,需要一些时间去修复他们。
**Tips**每次发布新版本都要写 `mapping.txt`。每发布一个版本,如果用户遇到一个bug,同时提交了一个混淆过的堆栈跟踪。 通过保留`mapping.txt`文件,来确定你可以调试的问题。
**DexGuard** 若果你需要核心工具来优化,和专门混淆的发布代码,考虑使用[DexGuard](http://www.saikoa.com/dexguard), 一个商业软件,ProGuard 也是有他们团队开发的。 它会很容易将Dex文件分割,来解决65K个方法限制问题。