当您使用 Android Gradle 插件 3.4.0 或更高版本构建项目时,不再使用 ProGuard 来执行编译时代码优化。相反,它与 R8 编译器协同工作以处理以下编译时任务:
```java
android {
buildTypes {
release {
// 仅在项目的发布构建类型中启用代码缩小、混淆和优化
minifyEnabled true
// 启用资源缩小,该操作由 Android Gradle 插件执行
shrinkResources true
// 包括与 Android Gradle 插件一起打包的默认 ProGuard 规则文件。要了解更多信息,请参阅有关 R8 配置文件的部分。
proguardFiles getDefaultProguardFile(
'proguard-android-optimize.txt'),
'proguard-rules.pro'
}
}
...
}
```
自定义要保留的资源:使用 `tools:keep` 和 `tools:discard` 标签来指定要保留或丢弃的资源。例如:
```groovy
tools:keep = "@layout/l_used*_c,@layout/l_used_a,@layout/l_used_b*"
tools:discard = "@layout/unused2" />
```
关键字 `keep` 和 `keepclassmembers`,它们可以用来保护指定的类文件和类的成员。例如:
```groovy
keep {Modifier} {class_specification} 保护指定的类文件和类的成员
keepclassmembers {modifier} {class_specification} 保护指定类的成员,如果此类受到保护他们会保护的更好
keepclasseswithmembers {class_specification} 保护指定的类和类的成员,但条件是所有指定的类和类成员是要存在。
```
## keepnames
`keepnames` 命令用于保护指定的类和类的成员的名称,如果他们在压缩步骤中被删除。以下是 `keepnames` 命令的具体用法:
```bash
./apktool b obfuscate -s name -o output.apk input.apk --keepnames "com.example.MyClass"
```
此命令将对 `input.apk` 应用混淆,并保留指定类 `com.example.MyClass` 以及其所有成员的名称。最终生成的混淆后的 APK 文件将保存为 `output.apk`。
## keepclassmembernames
`keepclassmembernames` 命令与 `keepnames` 类似,但它仅保护指定类的成员名称,而不涉及类本身。以下是 `keepclassmembernames` 命令的具体用法:
```bash
./apktool b obfuscate -s name -o output.apk input.apk --keepclassmembernames "com.example.MyClass"
```
此命令将对 `input.apk` 应用混淆,并保留指定类 `com.example.MyClass` 的所有成员名称,而不影响类本身。最终生成的混淆后的 APK 文件将保存为 `output.apk`。
## printseeds
`printseeds` 命令用于列出在应用混淆时,哪些类和类的成员使用了 `-keepnames`、`-keepclassmembersnames` 或者 `-keepclasseswithmembernames` 选项。以下是 `printseeds` 命令的具体用法:
```bash
./apktool b obfuscate -s names --printseeds output.apk input.apk
```
此命令将对 `input.apk` 应用混淆,并输出在混淆过程中保留的类名和成员名清单到标准输出(即 `output.txt`)。最终生成的混淆后的 APK 文件将保存为 `output.apk`,清单信息将保存到 `output.txt`。
8 是 Google 开发的一个 Android 代码混淆工具,它可以移除 APK 中的无用代码,提高应用的安全性和运行性能。在使用 R8 进行混淆时,可以通过配置文件来自定义混淆规则和输出报告。下面是一个使用 R8 的简单示例:
首先,在模块的 `proguard-rules.pro` 文件中添加以下内容,以获取 R8 在构建项目时应用的所有规则的完整报告:
```
// You can specify any path and filename.
-printconfiguration tmp/full-r8-config.txt
```
接下来,创建一个名为 `mapping.txt` 的文件,列出原始的类、方法和字段名与混淆后代码之间的映射关系。这些映射关系将被用于生成混淆后的代码。例如:
```
original_class_name=obfuscated_class_name
method_name=method_name
field_name=field_name
```
然后,创建一个名为 `seeds.txt` 的文件,列出未被混淆的类和成员。这些类和成员将在混淆过程中保持不变。例如:
```
com.example.MyClass
public static final java.lang.String MY_FIELD = "my field";
```
最后,创建一个名为 `usage.txt` 的文件,列出从 APK 中删除的代码。这些代码将在混淆过程中被移除。例如:
```
com.example.MyClass.myMethod();
```
对于多模块项目,可以在子模块的 `build.gradle` 文件中添加以下配置:
```groovy
release {
consumerProguardFiles 'proguard-rules.pro'
}
```
这样,只要 app 模块开启了混淆,子模块无论是否打开混淆都会默认开启。请注意,子模块的混淆规则是无法影响 app 模块的,因此建议在子模块里尽量只放和子模块相关的混淆规则,一些公有的混淆方式请放在 app 或者公有的模块中。