Android Gradle Plugin 9.0 升级指南:告别十年技术债,你准备好了吗?

如果你最近有关注Android开发动态,一定听说了------Android Gradle Plugin(AGP)9.0正式发布了。这不是一次小修小补,而是一次伤筋动骨的大版本升级。用一句话来形容:Google终于下决心把过去十年攒下的技术债给清了。

本文将从背景、核心变更、迁移步骤到新特性,为你呈现一份完整的AGP 9.0升级指南,并附上详细的代码示例。

一、升级背景:为什么这次不一样?

从AGP最初版本开始,为了保持向后兼容性,Google一直在内部保留着大量过时API(如applicationVariants.allBaseExtension等)。这些"老家具"虽然能用,但让构建系统负重前行。

AGP 9.0相当于直接把你搬到了一栋全新的大楼里------布局更合理、结构更先进,但你之前那些老家具可能塞不进新房间了。Google一刀切删除了所有已废弃API,彻底清理技术债。

二、核心变更之一:Kotlin正式成为"内建居民"

1. 不再需要手动应用Kotlin插件

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?

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")
    }
}

想强制降级到低版本? (不推荐,但可能有必要)

properties 复制代码
# 先在 gradle.properties 中关闭内置Kotlin
android.builtInKotlin=false
kotlin 复制代码
// 然后在顶层build.gradle中用strictly锁定版本
buildscript {
    dependencies {
        classpath("org.jetbrains.kotlin:kotlin-gradle-plugin") {
            version { strictly("2.1.0") }
        }
    }
}

实用技巧:如果某个模块是纯Java代码,可以单独关闭内置Kotlin避免编译开销

properties 复制代码
# 在纯Java模块的 gradle.properties 中
android.builtInKotlin=false

三、核心变更之二:DSL接口彻底更换

在AGP 9.0中,老的DSL实现类被完全替换,只暴露新的公开接口。

❌ 错误写法(会报错)

kotlin 复制代码
// 这种写法在AGP 9.0中直接报 ClassCastException
val extension = project.extensions.getByType(BaseExtension::class.java)

错误信息:

text 复制代码
java.lang.ClassCastException: 
class com.android.build.gradle.internal.dsl.ApplicationExtensionImpl
cannot be cast to class com.android.build.gradle.BaseExtension

✅ 正确写法

kotlin 复制代码
// 改用 CommonExtension
val android = project.extensions.findByType(CommonExtension::class.java)

四、Variant API 彻底重做

以前我们用applicationVariants.all做各种自定义操作,现在必须迁移到新的androidComponents API。

1. 修改APK输出名称

kotlin 复制代码
// 以前(已废弃)
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. 禁用特定构建变体

kotlin 复制代码
// 以前
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库模块必须换插件

kotlin 复制代码
// 以前(混搭)
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插件。必须:

  1. 创建独立的Android应用模块(如androidApp
  2. MainActivityApplication类、AndroidManifest.xml等移过去
  3. 让新模块依赖共享的KMP模块

六、默认行为变更(容易踩坑)

1. R类不再是final(重要!)

properties 复制代码
# 默认值从false变为true
android.enableAppCompileTimeRClass=true

这意味着R类字段不再是编译时常量。如果你在switch-case中用了R.id.xxx,必须改为if-else

kotlin 复制代码
// 以前(现在会编译报错)
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

properties 复制代码
android.targetSdkDefaultToCompileSdk=true

如果未显式设置targetSdk,现在默认使用compileSdk的值,而不是以前的minSdk

3. 唯一包名校验

properties 复制代码
android.uniquePackageNames=true

所有Android库模块必须有唯一的包名,否则构建失败。

七、好消息:Fused Library插件来了

对于SDK或组件库开发者,这是个期盼已久的功能:把多个模块融合成一个AAR文件发布

kotlin 复制代码
// 在需要合并的模块中应用插件
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升级助手

千万不要手动改版本号! 通过菜单栏 ToolsAGP Upgrade Assistant 自动处理基础迁移。

第三步:设置临时回退(可选)

如果遇到大量编译错误,可在gradle.properties中添加:

properties 复制代码
# 临时恢复旧DSL行为(仅用于缓冲,AGP 10.0将移除)
android.newDsl=false
# 临时关闭内置Kotlin(如果需要)
android.builtInKotlin=false

第四步:迁移自定义构建逻辑

对照前面的API变更表,逐步将自定义插件和构建脚本迁移到新API。

第五步:渐进式验证

  1. 先升级AGP版本,配合临时回退保持项目可运行
  2. 逐个模块迁移到新DSL和API
  3. 每迁移完一个模块就编译测试
  4. 全部完成后移除临时回退标志

写在最后

AGP 9.0是一次典型的"阵痛型"升级。短期看迁移成本不低,但清理掉积累十年的技术债,对Android构建系统的长远健康至关重要。

建议:不要急着第一时间升级,先仔细评估项目受影响范围,等核心三方插件都适配后再动手。但也不要拖太久------临时回退标志在AGP 10.0(预计明年年中)就会被移除,留给我们的时间窗口约一年。

参考资源:Google官方Gradle Recipes示例
developer.android.com/build/exten...

相关推荐
千里马学框架1 天前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台1 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
AFinalStone1 天前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
致远ccc1 天前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试
ttyyttemo1 天前
Kotlin 协程中的 Job 结构化并发与取消
android
sun0077001 天前
tbox 4g/5g切换,导致wan ip 改变,导致车机旧网络不可用。需要重启车机才行
android
ai2work2 天前
ch23 综合复刻:从零做一个最小可用版本(capstone)
kotlin
其实防守也摸鱼2 天前
内网穿透与反向代理:原理、工具与实战指南
android·大数据·运维·安全·网络安全·自动化·渗透
ai2work2 天前
ch21 签名、校验与发版
kotlin
AFinalStone2 天前
Android7 SystemUI 源码解析(四)NavigationBar 导航栏与 SystemBars
android·systemui