最近的 AGP 9.0 更新,再次给开发者们带来了不小的挑战。对于纯 Android 项目或许还能应对,但对于使用 Kotlin Multiplatform (KMP) 等技术的用户来说,影响可能更为深远。那么,这次 AGP 9.0 到底更新了什么?开发者们需要重点关注以下三大核心变动:
- 彻底切换到“新 DSL 接口”,旧实现和旧 Variant API 被移除。
- 内置 Kotlin (Built-in Kotlin)。
- KMP plugin 不再能与
com.android.application / com.android.library 在同一个模块中并存。
newDsl
首先是 newDsl。从 AGP 9.0 开始,只暴露新的 public DSL interfaces,旧的 DSL 类型(例如历史上许多插件或脚本会强制转换为 BaseExtension 等)不再提供。同时,旧的 variant API(如 applicationVariants)也被一并切断,开发者需要迁移到 androidComponents API。
从 Google 的角度看,这终于可以在主版本中移除“历史兼容层”,甩掉一个历史包袱。但对于用户而言,则可能面临:
- 自己编写的 Gradle 插件或 buildSrc 中,强制转换旧类型会导致直接崩溃。

- 依赖
applicationVariants、libraryVariants 的逻辑需要改为使用 androidComponents。
当然,这并不是完全没有退路。官方也提供了 android.newDsl=false 进行回退,但 AGP 10 将会彻底移除这个选项。 因此,虽然可以暂时过渡,但最终适配是必然的。
包括使用了旧版本 Hilt、KSP 的项目都可能无法编译。过渡期是存在的,但如果对应的插件作者不再维护,那就只能靠自己了。
Built-in Kotlin
Built-in Kotlin 现在默认开启。AGP 9.0 会默认启用 built-in Kotlin:目标是开发者不再需要为 Android 模块单独应用 org.jetbrains.kotlin.android 插件就能编译 Kotlin 代码,也不再需要声明 KGP 版本。
但副作用是:项目或插件生态中关于“默认的 KGP/Kotlin Android 插件”的假设会被打破,可能导致引用和依赖冲突,例如你可能会看到如下错误:
Failed to apply plugin 'org.jetbrains.kotlin.android'.
> Cannot add extension with name 'kotlin', as there is an extension already registered with that name.
Failed to apply plugin 'com.jetbrains.kotlin.android'
> The 'org.jetbrains.kotlin.android' plugin is no longer required for Kotlin support since AGP 9.0.
因此,通常你需要进行以下操作:
- 移除
kotlin-android 插件:移除 org.jetbrains.kotlin.android(或 kotlin-android),删除所有相关的 apply 语句。
- 迁移
kotlin-kapt 插件:建议迁移到 KSP。如果暂时无法迁移,可以将 kotlin-kapt 插件替换为 com.android.legacy-kapt 来尝试适配。
- 迁移
android.kotlinOptions{} DSL:将 android.kotlinOptions{} DSL 迁移到 kotlin.compilerOptions{}。
- 迁移
kotlin.sourceSets{} DSL:另外,可以使用 variant API 的 addStaticSourceDirectory 或 addGeneratedSourceDirectory 方法。

除此之外,AGP 9.0 还引入了对特定 Kotlin Gradle Plugin 版本的运行时依赖:

如果使用的 KGP 版本低于 2.2.10,Gradle 会自动将其升级到 2.2.10。同样,如果使用的 KSP 版本低于 2.2.10-2.0.2,AGP 也会将其升级到 2.2.10-2.0.2 以匹配 KGP 版本。
当然,你可以选择使用 enableKotlin 关闭这个默认支持,然后使用较低版本的 KGP 或 KSP:
android {
enableKotlin = false
}
buildscript {
dependencies {
// For KGP
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin") {
version { strictly("KGP_VERSION") }
}
// For KSP
classpath("com.google.devtools.ksp:symbol-processing-gradle-plugin") {
version { strictly("KSP_VERSION") }
}
}
}
但是官方也明确指出,最低可降级至 KGP 2.0.0,并且降级带来的不兼容问题需要自行负责:

另外,也可以通过 gradle.properties 文件中设置 android.builtInKotlin=false 来禁用 built-in Kotlin。
KMP
最后是关于 KMP 的变动。KMP plugin 不再能与 com.android.application / com.android.library 在同一个模块中并存,composeApp 必须拆分为 androidApp 才能正常工作。
对于 KMP 项目,当使用 AGP 9.0+ 时,KMP Gradle plugin 不再兼容与 com.android.application / com.android.library 共处于同一模块。解决方案是:
把 Android 入口点(如 Activity/Application 等)抽取到单独的 Android app module 中,共享代码 module 改为使用新的 Android-KMP library plugin:com.android.kotlin.multiplatform.library。
具体来说,项目结构会演变为:
androidApp:纯 Android Application 模块(打包 APK 的入口在这里)。
composeApp:共享代码模块(变为 Android Library,并进一步迁移到 Google 的 Android-KMP library plugin)。
更准确的说法是:
- 将属于 Android Application 的那部分(Activity/Application/manifest/打包配置)提取出去。
- shared module 仍然可以保留
androidMain source set 来存放 Android 平台的共享实现,但它只能是“library 语义”,不能再同时承担 application plugin 的职责。

简单来说,迁移主要包括:
- 将
composeApp/src/androidMain 整个移动到 androidApp/src/。AGP 9 要求 Android 应用入口(如 MainActivity.kt)不能再待在同时应用了 KMP 和 Android Application 插件的模块中,入口必须属于 androidApp 这类 application module 才能正常打包与运行。
- 但
expect/actual 声明必须继续留在共享模块(composeApp)的 source sets 里,以确保其它平台也能使用。
如果你的 actual 实现严重依赖 Activity 级别的 Context 或生命周期,可能需要重构为依赖注入或回调接口,否则在 Library 级别的 Shared Module 中很难处理。
- 将
androidApp/src/androidMain 重命名为 main。androidApp 是一个普通的 Android application module,它不遵循 KMP 的 source set 命名体系。
- 清理
composeApp 里原本的 androidMain.dependencies。在 composeApp/build.gradle.kts 中删除 kotlin.sourceSets.androidMain.dependencies {} 相关配置。这意味着基于 build variants 的依赖(如 debugImplementation/releaseImplementation)需要搬迁或重构,同时需要按照 Android-KMP library plugin 的规则重新组织 androidMain 相关依赖。
- 在 IDE 的 Run Configuration 里,将以前的
composeApp 配置改为 androidApp。

当然,目前还能暂时通过设置 android.enableLegacyVariantApi=true 来临时兼容,但这个“legacy” API 也会在 AGP 10 中被彻底移除,同时可能还需要设置 android.newDsl=false。

另外,Android-KMP library plugin 对 shared module 的 Android 部分不提供传统的 variant-aware 依赖配置(debugImplementation/releaseImplementation 等会失效),因此需要改用其提供的 classpath/配置方式来注入依赖:
- 以前在 shared module 中使用
debugImplementation / releaseImplementation 或者依赖 buildType/flavor 来注入不同实现/依赖的方式,现在需要迁移。
- 许多仅在 debug 模式下才需要的工具、调试依赖或开关,在 shared module 中无法再按 variant 优雅地区分,只能更换策略。
实际上,KMP 早期就推荐 Shared Module + Android App Module 的模式。后来为了简化上手难度,特别是 JetBrains 的 Wizard 向导,推广了 Single Module (Umbrella) 模式,允许一个模块既是共享库又是安卓应用。如今,这似乎又回到了起点。
此外,Android Studio 需要更新至 Otter 3 Feature Drop 2025.2.3 或更高版本才支持 AGP 9.0.0,IntelliJ IDEA 的支持预计在 2026 年第一季度上线。

为什么
为什么会有如此“大变动”?这大概是谷歌想一次性清算多年积累的技术债务。说通俗点就是:维护成本太高,需要精简。结合以上三点,你会发现 AGP 9 的目标非常一致:
- 控制公共 API 面:旧 DSL/旧 Variant API 过于开放,导致外部插件、buildSrc、脚本广泛依赖其内部实现,增加了 AGP 团队的维护成本。
- 为更稳定的构建模型铺路:Gradle 9 的大方向之一是将 Configuration Cache 推广为“首选执行模式”,并逐步淘汰不兼容的老 API/模式。AGP 9 的“新 DSL + 新 Variant API(androidComponents)”正是顺势而为。
- 深度集成 Kotlin:将 Kotlin 编译集成进 AGP(built-in Kotlin),旨在减少过去 KGP 与 AGP 之间脆弱的耦合点。
因此,AGP 9 就像是 Google 在进行一次技术上的“断舍离”,而对于广大开发者而言,这也将是一个被动的“断舍离”过程。不过话又说回来,不更新就不会有问题,能暂缓升级或许是当下最稳妥的策略。谁知道未来几个版本是否还会有新的变化呢?对于这类重大的构建工具升级,在云栈社区这样的技术论坛与同行交流经验,往往能事半功倍。
参考链接
https://developer.android.com/build/releases/agp-9-0-0-release-notes
https://developer.android.com/build/migrate-to-built-in-kotlin
https://kotlinlang.org/docs/multiplatform/multiplatform-project-agp-9-migration.html