前言
Google 发布了 Android Gradle Plugin 9.2.0。
这一版不是大迁移,但它动到了几条构建主线:Gradle 版本要求抬到 9.4.1、测试和覆盖率报告开始聚合、R8 的 -keepattributes 规则更严格,以及 Lint / DSL / JDK 兼容问题修复。
如果你的项目有多模块、CI 覆盖率、自定义 Lint、复杂混淆规则,升级 AGP 9.2 不能只看能不能编过。
先把构建环境对齐
AGP 9.2.0 的兼容矩阵已经变化。
AGP: 9.2.0
Gradle: 9.4.1
JDK: 17
SDK Build Tools: 36.0.0
默认 NDK: 28.2.13676358
最高支持 API: 36.1
升级入口通常先改插件版本:
plugins {
id("com.android.application") version "9.2.0" apply false
id("com.android.library") version "9.2.0" apply false
}
然后把 Gradle Wrapper 对齐到 9.4.1:
distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.1-bin.zip
JDK 还是 17。这个要求看起来稳定,但 CI 最容易在这里掉链子。
本地 Android Studio 可能已经用 JDK 17,CI 镜像却还停在旧版本;本地 Gradle Wrapper 已经更新,流水线缓存还在用老分发包。最后表现出来的不是业务编译错误,而是插件加载、同步、任务配置阶段失败。
统一测试报告来了
AGP 9.2.0 增加了一个实验能力:统一测试报告和覆盖率报告。
开启方式是在 gradle.properties 里加:
android.experimental.reportAggregationSupport=true
它解决的是多模块项目的老问题。
以前每个模块都有自己的测试报告:
app/build/reports/tests/
feature-login/build/reports/tests/
feature-device/build/reports/tests/
core/build/reports/tests/
覆盖率报告也类似。模块少的时候还能手动点开看;模块多了以后,CI 上很难快速回答三个问题:哪个模块挂了,哪个 variant 挂了,哪类测试挂了。
AGP 9.2 的方向是把不同模块、不同 variant、不同测试类型聚合到一个 HTML dashboard。
这个功能对单模块项目感知不强。对多模块 App、组件化工程、提测前全量测试和覆盖率归档更有用。
但它现在还是 experimental。更合适的接入方式是先放到非阻塞 CI 链路里验证,不要第一天就拿它做强制门禁。
R8 不再让通配符兜底
AGP 9.2 里最容易被忽略的是 R8 行为变化。
很多老项目都有类似规则:
-keepattributes *
-keepattributes *Annotation*
-keepattributes *Invisible*
这类规则写起来省事,但范围太宽。
AGP 9.2 之后,带通配符的 -keepattributes 不再匹配下面三类 runtime invisible annotation:
RuntimeInvisibleAnnotations
RuntimeInvisibleParameterAnnotations
RuntimeInvisibleTypeAnnotations
也就是说,下面这些规则不会再保留 runtime invisible annotation:
-keepattributes *
-keepattributes *Annotation*
-keepattributes *Invisible*
如果项目确实需要保留,需要显式写出属性名:
-keepattributes RuntimeInvisibleAnnotations,
RuntimeInvisibleParameterAnnotations,
RuntimeInvisibleTypeAnnotations
这个变化是为了让 R8 更贴近 D8 的行为。runtime invisible annotation 本来不能在运行时读取,D8 通常会移除它们;R8 过去为了兼容 ProGuard 保留了更宽松的匹配方式。
普通业务 App 多数不会感知。
但如果项目里有字节码扫描、AOP、插件化、注解元信息分析,或者历史混淆规则里大量使用宽泛 -keepattributes,升级后要重点跑 release 包验证。
只跑 assembleDebug 不够。这里影响的是 shrink / optimize / obfuscate 后的产物。
member rule 支持排除名称
R8 这次还扩展了配置语言。
member rule 现在支持 negated name pattern,也就是可以匹配“不符合某个名称模式”的成员。
官方给的例子是:匹配所有不以 ForTesting 结尾的方法。
-keepclassmembers class com.example.MyClass {
*** !*ForTesting(...);
}
这个能力适合收窄 keep 规则。
以前很多规则只能正向匹配,写到最后容易变成“先全保住再说”。现在可以在成员规则里直接表达排除条件,规则可以更接近真实意图。
它也有边界:如果反向成员名模式里包含通配符,这些通配符不能在 -if 后续规则里反向引用。
简单说,可以用它减少过宽规则,不要拿它写复杂模板。
修复项更偏工程链路
AGP 9.2.0 的修复项主要集中在 alpha 阶段,方向比较工程化。
APK 重命名相关问题被修复。使用新 AGP DSL 改 APK 输出名的项目,可以关注这条。
bootClasspath 访问时报 targetCompatibility is not yet finalized 的问题也修了。这类问题常见于自定义 Gradle 插件或构建逻辑访问 Android 配置太早。
JDK 26 下的 JdkImageTransform failure 被修复。大多数项目短期内不会把 CI 切到 JDK 26,但这说明 AGP 还在继续处理新 JDK 的兼容问题。
Lint 相关修复更多:
SARIF 报告上下文截断
Lint Gradle client 可靠性问题
Lint Gradle task 忽略 --quiet
自定义 Lint 使用 Java 21 bytecode 失败
Lint 文案错误
如果项目只是普通业务 App,这些修复不一定有感知。
如果你们接了自定义 Lint、SARIF 上报、CI 静态扫描,这些修复会更实际。
升级验证别只跑 debug
AGP 升级最容易漏掉 release 链路。
最低限度要跑一次 release 构建:
./gradlew assembleRelease
多 flavor 项目不要只跑默认 variant。至少要覆盖线上会发版的 flavor 和 buildType。
如果有自定义 Lint,单独跑:
./gradlew lint
如果有多模块测试,可以先在分支里打开聚合报告:
android.experimental.reportAggregationSupport=true
最后看 R8 规则。重点搜这几类:
-keepattributes *
-keepattributes *Annotation*
-keepattributes *Invisible*
如果项目不依赖 runtime invisible annotation,不要为了保险继续写宽规则。
如果确实依赖,就改成显式属性名,并把对应场景放进 release 包回归。
最后
AGP 9.2.0 不是大版本迁移,但它碰到了构建系统里几个容易被忽略的位置。
小项目可以等 Android Studio、Gradle、CI 环境统一后再升。
多模块项目、自定义 Lint 项目、R8 规则复杂的项目,建议单独拉分支验证。重点不是“能不能编过”,而是 release 包、测试报告、混淆产物和 CI 链路是否都正常。