Android Gradle Plugin 9.0 来了!Kotlin 内置、DSL 重构,这次迁移有多痛?

cover

你打开 Android Studio,看到一条升级提示:AGP 9.0 可用

你手一抖点了升级。

然后你的项目爆了 47 个编译错误。BaseExtension 找不到了,applicationVariants 不能用了,Kotlin 插件冲突了,Hilt 不兼容了……

你花了整整一天才把项目跑起来。

恭喜你,你刚刚体验了 Android 开发史上最大的一次构建系统重构。

Reddit 上有人发帖说:**”AGP 9.0 发布了,简直是灾难。这是我的完整迁移指南,希望你不用受这个罪。”** 帖子下面一片惨叫。

但冷静下来看,AGP 9.0 确实是 Google 这几年来做的最重要的一次底层升级。痛,但有意义。

AGP 9.0 到底改了什么?

一句话总结:Google 把积攒了好几个大版本的”技术债”一次性清掉了。

变更一:Kotlin 内置了

这是影响面最大的变化。

以前你要在 Android 项目里写 Kotlin,必须手动添加 org.jetbrains.kotlin.android 插件。从 AGP 7.x 到 8.x,这套配置一直没变。

AGP 9.0 把 Kotlin 支持直接内置到了插件里。 你不再需要单独声明 Kotlin 插件——AGP 自带了。

这意味着什么?

1
2
3
4
5
6
7
8
9
10
11
// 以前(AGP 8.x)
plugins {
id("com.android.application")
id("org.jetbrains.kotlin.android") // 必须手动加
}

// 现在(AGP 9.0)
plugins {
id("com.android.application")
// Kotlin 支持已内置,不需要了
}

看起来只是少了一行?实际影响比你想的大:

  • AGP 9.0 自带 KGP 2.2.10,会自动升级你项目里更低版本的 Kotlin 插件
  • 如果你还保留了 kotlin-android 插件声明,直接报错The 'org.jetbrains.kotlin.android' plugin is no longer required
  • KSP 版本也会被自动升级到 2.2.10-2.0.2

JetBrains 专门发了一篇博客提醒 Kotlin 开发者:所有 Android Kotlin 项目都需要立即调整构建配置。

变更二:DSL 全面重构

这是让很多老项目崩溃的根本原因。

从 AGP 7.x 开始,Google 就在引入新的 DSL 接口,同时保留旧的 BaseExtension 等类型做兼容。到了 AGP 9.0,旧的 DSL 类型被彻底移除了。

如果你的 build.gradle 或者自定义 Gradle 插件里引用了这些东西,直接炸:

1
2
3
java.lang.ClassCastException:
class com.android.build.gradle.internal.dsl.ApplicationExtensionImpl
cannot be cast to class com.android.build.gradle.BaseExtension

被移除的 API 清单很长,重点包括:

被移除的 API 替代方案
applicationVariants / libraryVariants androidComponents.onVariants()
variantFilter androidComponents.beforeVariants()
dexOptions 无需替代(dx 已被 d8 取代)
sdkDirectory / ndkDirectory androidComponents.sdkComponents
deviceProvider / testServer Gradle Managed Devices

一句话:如果你的项目还在用 AGP 7.x 时代的写法,这次升级会非常痛。

变更三:一堆默认值变了

AGP 9.0 不只是移除了旧 API,还改了很多默认行为。这些是”不看 Release Notes 就会踩坑”的隐藏地雷:

属性 AGP 8.x 默认值 AGP 9.0 默认值 影响
android.newDsl false true 强制使用新 DSL
android.builtInKotlin false true Kotlin 内置
android.uniquePackageNames false true 每个库必须有唯一包名
android.useAndroidx false true 默认使用 AndroidX
android.enableAppCompileTimeRClass false true R 类变为 non-final

最后一个变化要特别注意:R 类变成 non-final 了。 如果你在代码里用 switch-case 判断资源 ID,会直接编译报错。你需要把 switch 改成 if-else

变更四:Fused Library Plugin(预览)

这是一个新功能:允许你把多个库打包成一个 AAR 发布。

如果你维护的 SDK 有好几个模块(比如 sdk-coresdk-networksdk-ui),以前用户需要分别依赖每一个。现在你可以把它们”融合”成一个统一的 AAR,用户只需要一行依赖就搞定。

这个功能目前还是预览状态,但对 SDK 开发者来说绝对是好消息。

迁移有多痛?

痛点一:第三方插件不兼容

这是最大的痛点,没有之一。

Hilt、KSP、Firebase、Google Services、Crashlytics——这些常用插件在 AGP 9.0 发布时都不完全兼容。

Reddit 上那个”灾难”帖子的作者说得很直白:

“如果你在项目里用了 Hilt 或 KSP,你现在还不能迁移,除非你愿意做一些’严重的 workaround’。”

这个问题正在逐步解决。Google 已经在联系常用插件的作者推动适配。但如果你的项目依赖了很多第三方 Gradle 插件,建议先等它们出兼容版本再升级。

痛点二:自定义构建逻辑要改

如果你的团队写了自定义的 Gradle 插件或者 Task,而且用了 applicationVariantsBaseExtension 这些旧 API——全部都要改。

新的 androidComponents API 设计得更稳定、更规范,但迁移过程需要理解新的数据模型:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 旧写法(不再可用)
android.applicationVariants.all { variant ->
variant.outputs.all {
outputFileName = "my-app-${variant.name}.apk"
}
}

// 新写法
androidComponents {
onVariants { variant ->
variant.outputs.forEach { output ->
// 使用新的 API 处理输出
}
}
}

痛点三:KMP 项目要拆模块

如果你在做 Kotlin Multiplatform 项目,AGP 9.0 有一个重要限制:不能在同一个 Gradle 子项目里同时使用 KMP 插件和 Android Application 插件。

你需要把 Android 应用代码抽取到一个单独的模块里。Kotlin 官方文档有详细的迁移指南,但这个拆分工作量不小,特别是对大型 KMP 项目。

痛点四:Flutter 也受影响

Flutter 开发者同样逃不掉。Flutter 团队正在迁移旧的 DSL 类型,但目前还没完成。如果你想在 Flutter 项目里用 AGP 9.0,需要在 gradle.properties 里加一行:

1
android.newDsl=false

等 Flutter 团队完成适配后再移除这个标志。

迁移指南:5 步搞定

说了这么多痛点,也给你一条最靠谱的迁移路径。

第一步:检查第三方插件兼容性

在改任何东西之前,先确认你用的所有 Gradle 插件都支持 AGP 9.0。 Firebase、Hilt、Google Services、Crashlytics——这几个是最容易出问题的。

如果某个插件还不兼容,等它更新。不要硬上。

第二步:用 AGP Upgrade Assistant

不要手动改版本号。 Android Studio 自带的 AGP Upgrade Assistant(Tools > AGP Upgrade Assistant)是 Google 专门为这次升级更新的工具。它会自动处理大部分配置变更。

第三步:移除 Kotlin 插件声明

1
2
// 删除这一行
id("org.jetbrains.kotlin.android")

如果你还没准备好,可以暂时加上 android.builtInKotlin=false 来延迟迁移。

第四步:迁移 Variant API

把所有 applicationVariantslibraryVariants 的用法改成 androidComponents.onVariants()androidComponents.beforeVariants()

Google 提供了一套 Gradle Recipes 示例代码,覆盖了大部分常见场景。

第五步:处理 R 类变更

全局搜索你代码里的 switch(R.id.xxx)switch(R.layout.xxx),改成 if-else。很多项目这一步很快就能搞定。

为什么 Google 要做这么大的改动?

你可能会想:好端端的为什么要改这么多?

答案很简单:为了速度。

AGP 9.0 的这些变更,本质上都在为两件事铺路:

第一,Configuration Cache。 Gradle 的 Configuration Cache 可以大幅减少构建的配置阶段时间。但旧的 DSL 和 Variant API 跟 Configuration Cache 不兼容。移除旧 API,才能让 Configuration Cache 真正发挥作用。

第二,Isolated Projects。 这是 Gradle 未来最重要的性能优化。Isolated Projects 可以让多模块项目的配置阶段并行化,大幅缩短大型项目的构建时间。但它对 API 的稳定性和隔离性要求极高——旧的 API 根本做不到。

用一位开发者的话说:

“AGP 9.0 看起来是 Google 的’大扫除’。他们移除了多年前就已经弃用的 API,把 Kotlin 集成到核心里,逼你迁移到更高效的构建模式。”

短期是痛苦的迁移。长期是更快的构建速度。

时间窗口:你有多久?

Google 给了一个临时的”逃生口”:在 gradle.properties 里设置 android.newDsl=falseandroid.builtInKotlin=false 可以暂时回退到旧行为。

但这些 flag 会在 AGP 10.0(预计 2026 年中)彻底移除。

也就是说,你最多只有半年的迁移窗口。

建议是:现在就开一个分支开始迁移。 不要等到 AGP 10.0 发布了再着急。一个模块一个模块地改,用 Upgrade Assistant 做基础工作,在 CI 里验证整个流程。

版本兼容速查表

依赖 最低版本要求
Gradle 9.1.0
JDK 17
SDK Build Tools 36.0.0
Kotlin Gradle Plugin 2.2.10(自动内置)
KSP 2.2.10-2.0.2(自动升级)
NDK r28c(默认)
Android Studio Otter 3 Feature Drop (2025.2.3)+
Max API Level 36.1

写在最后

AGP 9.0 是 Google 对 Android 构建系统做的一次”重大手术”。

它移除了从 AGP 7.x 就开始弃用的旧 API,把 Kotlin 从”外挂”变成了”内核”,统一了 DSL 接口,为未来的性能优化扫清了障碍。

迁移会痛吗?会。 特别是那些积累了大量自定义构建逻辑的老项目。但越早迁移,痛苦越小。等到 AGP 10.0 强制移除所有兼容选项的时候,你就没有退路了。

好消息是,Google 这次提供了不错的迁移工具(Upgrade Assistant)、详细的文档、和临时的 opt-out 机制。不至于让你一夜之间全部改完。

打开你的项目,跑一下 AGP Upgrade Assistant,看看有多少报错。如果数字不大——恭喜你,你可以很快完成迁移。如果数字很大——更要早点开始。

你的项目升级到 AGP 9.0 了吗?迁移过程中踩到了什么坑?哪个第三方插件最让你头疼?欢迎评论区分享你的迁移经验。