AGP升级与迁移:版本演进、DSL变更与API废弃处理

AGP(Android Gradle Plugin)的升级,说白了就是一场「基建改造」。我见过太多团队,因为AGP版本落后,导致新特性用不上、构建速度慢、甚至无法适配最新的Android API。今天咱们就来聊聊,怎么平稳地完成这场升级。

AGP版本演进:这些年我们都经历了什么

AGP从3.0到8.x,每个大版本都有标志性的变化。我整理了一张核心演进图,你先感受下整体脉络:

AGP 3.0 Java 8+ 支持 变体感知API AGP 4.0 R8 默认开启 Java 8 脱糖 AGP 7.0 AGP DSL 大重构 Java 11 最低要求 AGP 8.0 非传递R类 BuildConfig默认关闭 AGP 8.x+ KSP 优先 配置缓存稳定 AGP 版本演进关键里程碑

你看,每个版本都不是简单的数字增加。AGP 7.0那次DSL大重构,我印象特别深——我们团队当时有30多个模块,迁移花了整整两周。

DSL变更:从Groovy到Kotlin的阵痛

DSL的变更,是AGP升级中最「疼」的部分。我个人习惯是:先理解变更背后的设计意图,再动手改代码

1. 命名空间与配置方式的变化

AGP 7.0之前,我们这样写:

android {
    compileSdkVersion 31
    buildToolsVersion "30.0.3"
    defaultConfig {
        applicationId "com.example.app"
        minSdkVersion 21
        targetSdkVersion 31
    }
}

AGP 7.0之后,变成了这样:

android {
    namespace "com.example.app"
    compileSdk 34
    defaultConfig {
        applicationId "com.example.app"
        minSdk 21
        targetSdk 34
    }
}

关键变化点:

  • compileSdkVersioncompileSdk(去掉了Version后缀)
  • buildToolsVersion 不再需要显式声明
  • namespace 从AndroidManifest.xml移到了build.gradle中

嗯,这里要注意:namespace的迁移,如果你有多个模块,每个模块都要单独设置。我曾经遇到一个坑——某个library模块忘了加namespace,结果R资源引用全部报错。

2. 变体过滤API的变更

AGP 7.0之前,过滤变体用variantFilter

android {
    variantFilter { variant ->
        if (variant.buildType.name == "debug" && variant.flavorName == "china") {
            setIgnore(true)
        }
    }
}

AGP 8.0之后,推荐使用onVariants

android {
    onVariants { variant ->
        if (variant.buildType == "debug" && variant.flavorName == "china") {
            variant.ignore = true
        }
    }
}

注意:variantFilter在AGP 8.0中已被标记为废弃,建议尽早迁移到onVariants。我建议你在升级AGP版本时,同步检查所有变体相关的API。

API废弃处理:别等到编译报错才动手

AGP的API废弃,通常有一个「软废弃→硬废弃→移除」的过程。我的经验是:在软废弃阶段就处理掉,别拖到硬废弃

常见的废弃API清单

废弃API 废弃版本 替代方案 移除版本
variant.getOutputs() AGP 7.0 variant.outputs 属性 AGP 9.0(预计)
BaseVariant.getApplicationId() AGP 7.2 variant.applicationId AGP 8.0
BuildType.isDebuggable() AGP 8.0 buildType.debuggable AGP 9.0(预计)
Dependency.getArtifact() AGP 7.4 Dependency.artifact AGP 8.1

你可能会问:「怎么知道哪些API被废弃了?」其实很简单——编译时会有@Deprecated警告。我习惯在gradle.properties中开启:

android.deprecationPrinter.level=WARN

这样所有废弃API的警告都会显示出来,方便你逐个排查。

小技巧:如果你有自定义插件,建议在插件代码中加上@Suppress("DEPRECATION")注解,明确标记哪些地方使用了废弃API,方便后续统一清理。

迁移工具:AGP官方给的「救命稻草」

Google其实提供了不少迁移工具,但很多人不知道。我整理了几个最实用的:

1. Android Studio的AGP升级助手

在Android Studio中,打开 Tools → AGP Upgrade Assistant。它会自动分析你的项目,列出所有需要修改的地方。我个人觉得这个工具对中小型项目特别友好,但大型项目(比如超过50个模块)可能会卡顿。

2. 命令行迁移工具

AGP 8.0之后,官方提供了android-gradle-plugin-migration工具:

./gradlew :app:checkDeprecation --warning-mode all

这个命令会输出所有废弃API的使用位置,精确到文件和行号。我曾经用它一次性定位了47个废弃调用,效率非常高。

3. 自动迁移脚本

对于DSL变更,我写过一个简单的Gradle任务:

tasks.register("migrateNamespace") {
    doLast {
        fileTree(".").include("**/build.gradle*").each { file ->
            def content = file.text
            // 替换 compileSdkVersion → compileSdk
            content = content.replaceAll("compileSdkVersion", "compileSdk")
            // 替换 minSdkVersion → minSdk
            content = content.replaceAll("minSdkVersion", "minSdk")
            // 替换 targetSdkVersion → targetSdk
            content = content.replaceAll("targetSdkVersion", "targetSdk")
            file.text = content
        }
    }
}

注意:自动脚本只能处理简单的文本替换。像namespace这种需要从AndroidManifest.xml中提取的逻辑,还是得手动处理。我建议你跑完脚本后,再用git diff仔细检查一遍。

兼容性矩阵:版本匹配的「黄金法则」

AGP和Gradle、JDK、Kotlin之间有严格的版本对应关系。我见过太多人因为版本不匹配,编译时各种诡异报错。

AGP版本 最低Gradle版本 最低JDK版本 推荐Kotlin版本
7.0.x 7.0 11 1.5.x
7.1.x 7.1 11 1.6.x
7.2.x 7.3 11 1.6.x
7.3.x 7.4 11 1.7.x
7.4.x 7.5 11 1.8.x
8.0.x 8.0 17 1.9.x
8.1.x 8.1 17 1.9.x
8.2.x 8.2 17 1.9.x

这里有个容易忽略的点:JDK版本。AGP 8.0强制要求JDK 17,如果你还在用JDK 11,升级后编译会直接报错。我建议你在升级前,先检查CI环境和开发机的JDK版本。

我的升级流程:

  1. 先升级Gradle到目标版本
  2. 再升级AGP到目标版本
  3. 运行./gradlew :app:checkDeprecation --warning-mode all检查废弃API
  4. 逐个修复废弃调用
  5. 运行完整测试用例
  6. 提交代码,观察CI构建是否正常

这个流程我用了好几年,基本没出过大的问题。当然,如果你项目特别大,建议先在一个分支上试水,别直接在主干上搞。

避坑指南:那些年我踩过的坑

最后分享几个我亲身经历的坑,希望能帮你少走弯路:

  • 坑一:升级AGP后,BuildConfig默认关闭了。如果你依赖BuildConfig.DEBUG之类的字段,记得在build.gradle中显式开启:buildFeatures { buildConfig = true }
  • 坑二:AGP 8.0之后,R.class不再是传递性的。如果你有多个模块,每个模块的R资源必须显式引用。我有个同事因为这个,排查了整整一天。
  • 坑三:配置缓存(Configuration Cache)在AGP 8.0中默认开启。如果你的自定义插件没有做好序列化,构建会报错。建议在gradle.properties中先关闭:org.gradle.configuration-cache=false,等插件适配后再开启。

升级AGP,说白了就是一场「有计划的风险管理」。别怕,按照流程一步步来,大部分问题都能解决。如果遇到实在搞不定的,欢迎来公众号找我聊聊。


公众号:蓝海资料掘金营,微信deep3321