保留规则简介

当您使用默认设置启用应用优化时,R8 会执行广泛的优化,以最大限度地提高性能优势。R8 会对代码进行大幅修改,包括重命名、移动和移除类、字段和方法。如果您发现这些修改会导致错误,则需要通过在保留规则中声明 R8 不应修改的代码部分,来指定这些部分。

需要保留规则的常见场景

R8 会识别并保留代码中的所有直接调用。不过,R8 无法看到间接的代码使用情况,这可能会导致它移除应用需要的代码,从而导致崩溃。您可以使用保留规则来告知 R8 保留此类间接使用的代码。以下是一些常见情况,您可能需要保留规则:

  • 通过反射访问的代码:R8 无法识别何时通过反射访问类、字段或方法。例如,R8 无法识别使用 Class.getDeclaredMethod() 按名称查找的方法,也无法识别使用 Class.getAnnotation() 检索到的注释。在这些情况下,R8 可能会重命名这些方法和注释或完全移除它们,从而导致运行时出现 ClassNotFoundExceptionNoSuchMethodException
  • 通过 Java 原生接口 (JNI) 调用的代码:当原生(C 或 C++)代码调用 Java 或 Kotlin 方法,或者 Java 或 Kotlin 代码通过 JNI 调用 C++ 代码时,调用基于对方法名称的动态字符串查找。R8 无法看到基于动态字符串的方法调用,因此其优化可能会破坏您的代码。

以下并非需要保留规则的所有情形,但这些情形涵盖了您可能需要保留规则的大多数情况。

如何向应用添加保留规则

您的保留规则配置取决于您使用的 AGP 版本。

较大的应用通常在多个库模块中包含代码。在这种情况下,最好将 keep 规则与它们所适用的代码放在同一特定库模块中。在为库维护保留规则时,关键区别在于如何在库模块的 build.gradle.kts(或 build.gradle)文件中声明这些规则。如需了解详情,请参阅面向库作者的优化

对于 AGP 版本 9.3 及更高版本

将规则添加到 src/<variant>/keepRules 目录中带有 .keep 后缀的文件中。例如 src/main/keepRules/custom-rules.keep。请注意,使用 AGP 9.3 及更高版本的更新版 DSL 可同时实现代码和资源优化,并且不需要您明确定义默认的 Android keep 规则文件 (proguard-android-optimize.txt),因为该文件默认包含在内,除非明确省略。

Kotlin

android {
    buildTypes {
        release {
            optimization {
                enable = true // Enables code and resource optimizations.
            }
        }
    }
}

Groovy

android {
    buildTypes {
        release {
            optimization {
                enable = true // Enables code and resource optimizations.
            }
        }
    }
}

省略默认 Android 平台保留规则(高级)

AGP 提供了一组默认 Android 平台规则。如需从项目配置中省略这些规则并自行管理所有保留规则,请将 optimization.keepRules.includeDefault 设置为 false

Kotlin

android {
    buildTypes {
        release {
            optimization {
                enable = true // Enables code and resource optimizations.
                keepRules {
                    includeDefault = false // The file with optimization
                    // rules for the Android platform is included by
                    // default. To omit this file, set this option to false.
                }
            }
        }
    }
}

Groovy

android {
    buildTypes {
        release {
            optimization {
                enable = true // Enables code and resource optimizations.
                keepRules {
                    includeDefault = false // The file with optimization
                    // rules for the Android platform is included by
                    // default. To omit this file, set this option to false.
                }
            }
        }
    }
}

适用于低于 9.3 的 AGP 版本的旧版 DSL

将规则添加到应用模块根目录中的 proguard-rules.pro 文件中;该文件可能已存在,但如果不存在,请创建该文件。如需应用文件中的规则,您必须在模块级 build.gradle.kts(或 build.gradle)文件中声明该文件。

默认情况下,您的 build 文件还包含 proguard-android-optimize.txt 文件。此文件包含大多数 Android 项目所需的规则,因此您应让其保留在 build 文件中。此文件基于 proguard-common.txt 文件,并与其共享内容。

旧版 DSL (Kotlin)

android {
    buildTypes {
        release {
            isMinifyEnabled = true
            isShrinkResources = true

            proguardFiles(
                // Default file with default optimization rules.
                getDefaultProguardFile("proguard-android-optimize.txt"),
                ...
            )
        }
    }
}

旧版 DSL (Groovy)

android {
    buildTypes {
        release {
            minifyEnabled = true
            shrinkResources = true

            // Default file with default optimization rules.
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt')
            ...
        }
    }
}

添加保留规则

添加保留规则时,您可以添加全局选项,也可以定义自己的保留规则。

  • 全局选项:全局选项是影响 R8 如何处理整个代码库的常规指令。如需了解详情,请参阅全局选项

  • 保留规则:保留规则需要精心设计,以确保在最大限度地优化代码的同时,不会意外中断应用。如需了解如何编写保留规则,请参阅添加保留规则

为库作者保留规则

在了解了保留规则的全局选项和语法后,请参阅面向库作者的优化,了解更多详情。