第2课:AGP、Kotlin、Gradle的版本匹配
——那些年我们踩过的兼容坑
Gradle 升级翻车,十次里有八次是因为版本不匹配。我说的不是玄学,是实实在在的 NoSuchMethodError 和 UnsupportedOperationException。
AGP(Android Gradle Plugin)、Kotlin 插件、Gradle 本身,这三者就像齿轮。你看上去每个版本都升了,但咬合不对,照样崩。我自己就碰到过一个项目,只升了 Gradle 7.5 没动 AGP,结果构建直接报 Could not get unknown property 'android'。查了半天,原来是 AGP 7.4 不支持 Gradle 8.0+ 的新 API。嗯,从那以后我养成了一个习惯——
升任何组件前,先看官方兼容矩阵。
版本兼容的核心原则
说白了就一句话:大版本号对齐,小版本号宽容。
- Gradle 主版本号(首位)决定 AGP 的最低要求
- AGP 主版本号决定 Kotlin 插件的兼容范围
- Kotlin 插件版本又反过来约束 AGP 的某些特性(比如 Compose 编译器)
我曾经见过一个团队,Kotlin 1.9.0 配了 AGP 8.0,看起来没问题。但他们的 Compose 版本是 1.5.0,而 Kotlin 1.9.0 对应的 Compose 编译器是 1.5.1。结果 Compose 预览全部挂掉,报错说什么内部编译器异常。你想想看,这种错靠看 log 根本猜不到是版本没对齐。
我的铁律:每个季度第一个周一,打开 developer.android.com/build/releases/gradle-plugin,扫一遍兼容表格。
AGP 与 Gradle 的版本对应关系
这是最基础、也最容易出事的。我直接贴一张我自己整理的速查表,你最好保存下来:
| AGP 版本 | 最低 Gradle 版本 | 推荐 Gradle 版本 | 备注 |
|---|---|---|---|
| 7.0.x | 7.0 | 7.0 – 7.3 | 旧版 R8 兼容问题 |
| 7.1.x | 7.1 | 7.1 – 7.4 | 需升级 JDK 11+ |
| 7.2.x | 7.2 | 7.2 – 7.4 | AGP 配置缓存问题较多 |
| 7.3.x | 7.3 | 7.3 – 7.5 | 支持 Gradle 配置缓存稳定版 |
| 7.4.x | 7.5 | 7.5 – 8.0 | ⚠️ 不要用 Gradle 8.0+ |
| 8.0.x | 8.0 | 8.0 – 8.2 | 强制 JDK 17,namespace 必须声明 |
| 8.1.x | 8.0 | 8.1 – 8.3 | 新增短文件名打包 |
| 8.2.x | 8.2 | 8.2 – 8.4 | NonTransitiveRClasses 默认开启 |
| 8.3.x | 8.4 | 8.4 – 8.5 | 支持 lint 并行分析 |
避坑技巧:别图新,用 AGP 发布后 3 个月以上的版本。我踩过 8.0.0-alpha 的坑,resource 合并直接炸裂。
Kotlin 插件与 AGP 的版本互动
很多人以为 Kotlin 版本独立于 AGP,其实两者深度耦合。尤其是 IDE 侧,AS 的 Kotlin 插件版本必须匹配 Gradle 里的 Kotlin 版本。否则就会出现「项目编译通过,但 IDE 标红」的灵异现象。
我个人习惯是:Kotlin 版本永远不要领先 AGP 超过一个大版本。举个例子:
- AGP 7.x 可以用 Kotlin 1.6 ~ 1.8
- AGP 8.0+ 推荐 Kotlin 1.9+
- AGP 8.2+ 最好用 Kotlin 1.9.10+(修复了编译器崩溃)
这里有个容易忽略的点:Compose 编译器版本。如果你项目里用了 Compose,Kotlin 版本不能随意升。Compose 编译器是跟着 Kotlin 版本走的。比如:
// build.gradle (app)
android {
composeOptions {
kotlinCompilerExtensionVersion = "1.5.1"
}
}
// 这个版本必须与使用的 Kotlin 版本对应:
// Kotlin 1.9.0 -> Compose Compiler 1.5.1
// Kotlin 1.9.10 -> Compose Compiler 1.5.3
// Kotlin 1.9.20 -> Compose Compiler 1.5.4
我曾经在升级 Kotlin 1.9.20 时,没改 Compose 编译器版本,结果 build 成功但 @Preview 全崩。那个错你根本看不懂——java.lang.InternalError,没有堆栈。最后我硬是被折腾了俩小时才找到根因。
警告:不要在 AGP 版本未稳定时升级 Kotlin 主版本。比如 AGP 8.4 刚出来,匹配的 Kotlin 2.0 还是 RC,直接上必定出IncompatibleClassChangeError。
其他关键依赖的版本约束
除了 AGP 和 Kotlin,还有几个插件也会在升级时反水:
- Google Services 插件(
com.google.gms:google-services)- 4.3.15 只支持 AGP 7.0 ~ 8.1
- 4.4.0+ 才支持 AGP 8.2+
- 如果你升了 AGP 8.3 没升 Google Services,build 时直接报
Missing google-services.json—— 其实文件在,只是插件不认。
- Firebase Crashlytics 插件
- 2.9.8 之前与 AGP 8.0 的
namespace强制声明冲突 - 我曾经有个客户,升级 AGP 8.2 后
crashlytics上传签名死活失败,最后发现是插件版本不够。
- 2.9.8 之前与 AGP 8.0 的
- Hilt / Dagger
- Hilt 2.44 以下不支持 Gradle 8.0 的配置缓存
- 如果你的 Gradle 升到 8.2,Hilt 至少得 2.46+,不然
Kapt会卡死
- ButterKnife(别笑,还有人在用)
- 10.2.3 只支持 AGP 3.x ~ 4.x,到了 AGP 7.0 直接不能用
补个我个人总结的「升级安全清单」:
| 你要升级 | 必须一起升级 | 可能受影响 |
|---|---|---|
| Gradle 8.0 → 8.4 | AGP 8.2+,JDK 17 | Hilt、Kapt、AndroidX 构建流程 |
| AGP 7.4 → 8.0 | Kotlin 1.8+, Gradle 8.0+, JDK 17 | namespace、Crashlytics、Google Services |
| Kotlin 1.8 → 1.9 | Compose Compiler 1.5+, AGP 8.0+ | KSP、Jetpack Navigation |
版本兼容的全貌图
下面这张图,我画了好久。它把 AGP、Gradle、Kotlin、Compose 编译器、常见插件之间依赖关系串起来了。升级前你看一眼,就知道该动谁、不该动谁。
实战升级策略(三步走)
看完图,你可能心里有底了。但具体操作我建议你按这个顺序来,少走弯路:
-
先确定目标 AGP 版本
查官方兼容表,确认最低 Gradle 和 JDK 要求。
然后把gradle-wrapper.properties里的 Gradle 版本改过来,别动别的。 -
再升级 Kotlin 与 Compose 编译器
看上面表格,把 Kotlin 版本和 Compose 编译器版本对齐。
这一步容易遗漏的是kotlinx.serialization、kotlinx.coroutines等库,它们也有最低 Kotlin 要求。 -
最后处理第三方插件
按我整理的清单,挨个检查 Google Services、Crashlytics、Hilt 等。
如果某个插件不支持新 AGP,先升插件,再试 build。不要同时升所有东西。
我的小秘诀:每个步骤做完,跑一次 ./gradlew assembleDebug --dry-run,能快速发现Version mismatch类型错误,不用等完整编译。
常见崩溃与根因速查
我整理了几个我在技术社区里高频看到的问题,你遇到可以直接对照:
| 错误信息(关键词) | 根因 | 解决方案 |
|---|---|---|
Could not find method android() |
Gradle 版本太高,AGP 太旧 | 升级 AGP 或降 Gradle |
Unsupported class file major version 61 |
JDK 版本与 AGP 不匹配 | 升 JDK 到 17 或降 AGP |
KotlinJvmAndroidCompilation 报错 |
Kotlin 插件版本与 AGP 不符 | 按上面表格调版本 |
Android resource linking failed |
AGP 8.0+ 中 namespace 未声明 |
在 android 块里加 namespace 'com.xxx' |
Cannot get property 'android' on null object |
Google Services 插件版本过旧 | 升级到 4.4.0+ |
最后铁律:升级前务必在分支上操作。不要像我那个同事一样,直接改 master 的 build.gradle,然后全组无法编译。他那天下午请全组喝了奶茶才平息众怒。
好了,这一章的核心就是:版本匹配不是玄学,是工程。你只要把上面表格存好,升级前看一眼,大概率不会翻车。下一章我会讲具体崩溃场景 —— 那种 Gradle Sync Failed 弹窗出现时,你该怎么办。
这就是第 2 章的全部内容。我把我知道的、踩过的坑都摊牌了。你如果严格按照这张图和三步走策略来升级,应该不会遇到我当年那种半夜三点还在查 version mismatch 的局面。