如果你最近有关注Android开发动态,一定听说了——Android Gradle Plugin(AGP)9.0正式发布了。这不是一次小修小补,而是一次伤筋动骨的大版本升级。用一句话来形容:Google终于下决心把过去十年攒下的技术债给清了。
本文将从背景、核心变更、迁移步骤到新特性,为你呈现一份完整的AGP 9.0升级指南,并附上详细的代码示例。
一、升级背景:为什么这次不一样?
从AGP最初版本开始,为了保持向后兼容性,Google一直在内部保留着大量过时API(如applicationVariants.all、BaseExtension等)。这些“老家具”虽然能用,但让构建系统负重前行。
AGP 9.0相当于直接把你搬到了一栋全新的大楼里——布局更合理、结构更先进,但你之前那些老家具可能塞不进新房间了。Google一刀切删除了所有已废弃API,彻底清理技术债。
二、核心变更之一:Kotlin正式成为“内建居民”
1. 不再需要手动应用Kotlin插件
// 以前(需要手动引入)
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android' // 这行现在可以删除了
}
// AGP 9.0
plugins {
id 'com.android.application'
// Kotlin支持已内置,无需显式声明
}
新建Android模块后,什么都不用配置,直接就能写Kotlin代码。
2. Kotlin版本管理
AGP 9.0默认自带的Kotlin版本是2.2.10。如果你的项目Kotlin版本低于此,Gradle会自动升级。
想用更高版本Kotlin?
// 顶层 build.gradle.kts
buildscript {
dependencies {
// 指定更高版本的KGP
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:2.3.0")
// KSP也要同步升级
classpath("com.google.devtools.ksp:symbol-processing-gradle-plugin:2.3.0-1.0.0")
}
}
想强制降级到低版本? (不推荐,但可能有必要)
# 先在 gradle.properties 中关闭内置Kotlin
android.builtInKotlin=false
// 然后在顶层build.gradle中用strictly锁定版本
buildscript {
dependencies {
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin") {
version { strictly("2.1.0") }
}
}
}
实用技巧:如果某个模块是纯Java代码,可以单独关闭内置Kotlin避免编译开销
# 在纯Java模块的 gradle.properties 中
android.builtInKotlin=false
三、核心变更之二:DSL接口彻底更换
在AGP 9.0中,老的DSL实现类被完全替换,只暴露新的公开接口。
❌ 错误写法(会报错)
// 这种写法在AGP 9.0中直接报 ClassCastException
val extension = project.extensions.getByType(BaseExtension::class.java)
错误信息:
java.lang.ClassCastException:
class com.android.build.gradle.internal.dsl.ApplicationExtensionImpl
cannot be cast to class com.android.build.gradle.BaseExtension
✅ 正确写法
// 改用 CommonExtension
val android = project.extensions.findByType(CommonExtension::class.java)
四、Variant API 彻底重做
以前我们用applicationVariants.all做各种自定义操作,现在必须迁移到新的androidComponents API。
1. 修改APK输出名称
// 以前(已废弃)
android.applicationVariants.all { variant ->
variant.outputs.all {
outputFileName = "app-${variant.name}-${variant.versionName}.apk"
}
}
// AGP 9.0 新写法
androidComponents {
onVariants { variant ->
// 新API采用懒加载设计
variant.signingConfig.enableV1Signing.set(false)
// 注意:修改输出名称的方式也变了,需要通过artifact API
}
}
2. 禁用特定构建变体
// 以前
android {
variantFilter { variant ->
if (variant.buildType.name == "debug" && variant.flavors[0].name == "blue") {
setIgnore(true)
}
}
}
// AGP 9.0 替代方案
androidComponents {
beforeVariants(
selector()
.withBuildType("debug")
.withFlavor("color", "blue")
) { variantBuilder ->
variantBuilder.enable = false
}
}
3. 主要API变更对照表
| 废弃的旧API | 用途 | AGP 9.0 新方案 |
|---|---|---|
applicationVariants/libraryVariants | 自定义构建行为 | androidComponents.onVariants |
variantFilter | 禁用特定变体 | androidComponents.beforeVariants |
sdkDirectory/ndkDirectory | 获取SDK组件路径 | androidComponents.sdkComponents |
dexOptions | dx工具配置 | 已无替代(d8不需要) |
deviceProvider/testServer | 自定义测试环境 | Gradle-managed devices |
五、Kotlin Multiplatform (KMP) 项目的特殊迁移
如果你正在做KMP开发,AGP 9.0的影响最大。
1. Android库模块必须换插件
// 以前(混搭)
plugins {
id 'com.android.library'
id 'org.jetbrains.kotlin.multiplatform'
}
// AGP 9.0
plugins {
id 'com.android.kotlin.multiplatform.library' // 专用插件
}
2. Android应用模块必须独立
严禁在同一个子项目中同时使用KMP插件和com.android.application插件。必须:
- 创建独立的Android应用模块(如
androidApp) - 将
MainActivity、Application类、AndroidManifest.xml等移过去 - 让新模块依赖共享的KMP模块
六、默认行为变更(容易踩坑)
1. R类不再是final(重要!)
# 默认值从false变为true
android.enableAppCompileTimeRClass=true
这意味着R类字段不再是编译时常量。如果你在switch-case中用了R.id.xxx,必须改为if-else:
// 以前(现在会编译报错)
when (view.id) {
R.id.button_ok -> handleOk()
R.id.button_cancel -> handleCancel()
}
// 现在必须改成
if (view.id == R.id.button_ok) {
handleOk()
} else if (view.id == R.id.button_cancel) {
handleCancel()
}
2. targetSdk默认对齐compileSdk
android.targetSdkDefaultToCompileSdk=true
如果未显式设置targetSdk,现在默认使用compileSdk的值,而不是以前的minSdk。
3. 唯一包名校验
android.uniquePackageNames=true
所有Android库模块必须有唯一的包名,否则构建失败。
七、好消息:Fused Library插件来了
对于SDK或组件库开发者,这是个期盼已久的功能:把多个模块融合成一个AAR文件发布。
// 在需要合并的模块中应用插件
plugins {
id 'com.android.fused.library'
}
// 配置要合并的模块
fusedLibrary {
// 自动合并依赖的所有本地模块
}
以前需要各种hack手段才能实现的多模块合并,现在原生支持了。
八、R8更新
1. 处理Kotlin空检查代码
新增配置-processkotlinnullchecks,有三个选项:
keep:保留原样remove_message:保留空检查但去掉错误消息(默认值)remove:完全移除空检查(极致包体积优化,需确保空安全)
2. ProGuard规则文件变更
不再支持proguard-android.txt,只能使用proguard-android-optimize.txt。
九、环境要求升级
| 依赖 | 最低版本要求 |
|---|---|
| JDK | 17(重要!CI/CD流水线必须检查) |
| Gradle | 9.1.0 |
| SDK Build Tools | 36.0.0 |
| Android Studio | Otter 3 Feature Drop (2025.2.3)+ |
十、分步升级实战指南
第一步:环境预检
- 确认JDK版本 ≥ 17(包括CI/CD环境)
- 检查Android Studio版本
- 确认第三方插件(Hilt、KSP、Firebase等)是否已适配AGP 9.0
第二步:使用AGP升级助手
千万不要手动改版本号! 通过菜单栏 Tools → AGP Upgrade Assistant 自动处理基础迁移。
第三步:设置临时回退(可选)
如果遇到大量编译错误,可在gradle.properties中添加:
# 临时恢复旧DSL行为(仅用于缓冲,AGP 10.0将移除)
android.newDsl=false
# 临时关闭内置Kotlin(如果需要)
android.builtInKotlin=false
第四步:迁移自定义构建逻辑
对照前面的API变更表,逐步将自定义插件和构建脚本迁移到新API。
第五步:渐进式验证
- 先升级AGP版本,配合临时回退保持项目可运行
- 逐个模块迁移到新DSL和API
- 每迁移完一个模块就编译测试
- 全部完成后移除临时回退标志
写在最后
AGP 9.0是一次典型的“阵痛型”升级。短期看迁移成本不低,但清理掉积累十年的技术债,对Android构建系统的长远健康至关重要。
建议:不要急着第一时间升级,先仔细评估项目受影响范围,等核心三方插件都适配后再动手。但也不要拖太久——临时回退标志在AGP 10.0(预计明年年中)就会被移除,留给我们的时间窗口约一年。
参考资源:Google官方Gradle Recipes示例
developer.android.com/build/exten…