1. AGP简介

Android Gradle Plugin,圈里都叫它 AGP。说白了,它就是 Android 官方为 Gradle 准备的一套插件。

你写的 Java/Kotlin 代码、资源文件、Manifest,AGP 帮你把它们拧在一起,变成 .apk 或 .aab。没有它,你连个 Hello World 都跑不起来。

我记得刚入行那会儿,很多人觉得 AGP 就是个“黑盒子”——只管点一下 Run 按钮,背后发生了什么一概不知。直到有一天…build 突然挂了,报一堆看不懂的错,你才明白:这玩意儿比想象的复杂得多。

一句话总结:AGP = Android 工程的构建管家 + 打包工人 + 签名师傅。

1.1 它到底管哪些事?

  • 编译:把你的 .java/.kt 编译成 .class,再转成 dex。
  • 资源处理:合并、压缩、混淆资源。
  • 签名:生成签名后的 apk/aab。
  • 变体管理:debug/release、flavor、build type…全靠它调度。
  • 依赖管理:协调各个 Module 和第三方库的版本。

你想想看,项目越大,这些环节越容易出幺蛾子。尤其是最后那条——依赖管理——版本冲突的根源就在这儿。

1.2 AGP 的发展简史

AGP 是跟着 Android Studio 一起长大的。我手上有份不完整的回忆,大概是这样:

AGP 版本发布时间主要变化对应 Gradle 最低版本
1.x2013-2015第一代,支持基本构建2.2+
2.x2016-2017Instant Run,Jack & Jill3.3+
3.x2017-2020D8 编译器,R8 混淆,AndroidX4.1+
4.x2020-2022Java 8+ 支持,Maven Publish6.1+
7.x2021-2023Variant API 重构,Compose 原生支持7.0+
8.x2023-至今非传递性 R 类,KSP 稳定8.0+

你看这表,AGP 和 Gradle 版本是“绑死”的。不能用 8.x 的 AGP 配 Gradle 7.x,否则直接给你脸色看。

踩坑提示:每次升级 AGP,必须同步升级 Gradle wrapper。我曾经因为偷懒只改了 AGP 版本号,结果 build 了两小时,最后告诉我“Unsupported class file major version”…

1.3 AGP 与 Gradle 的“婚姻关系”

这种对应关系不是随便写的,背后是 Android 团队对 Gradle API 的依赖。官方有一套兼容矩阵,我把它简化成你脑子里要记住的几组:

  • AGP 4.x → Gradle 6.1.1+ (但不要超过 6.7)
  • AGP 7.0 → Gradle 7.0.2+
  • AGP 7.3 → Gradle 7.4+
  • AGP 8.0 → Gradle 8.0+
  • AGP 8.1 → Gradle 8.0+ (实际上我推荐 8.1+)

为什么会这样?因为 AGP 会调用 Gradle 内部的 Task API、Configuration API,老版本 Gradle 根本没有那些方法。你想想,相当于让一个现代 App 跑在 Android 4.4 上——不是不能跑,但很多功能直接 crash。

我的检测方法:升级前先查官方文档的 api-versions.html,或者直接跑一次 ./gradlew --version,确保 Gradle 版本没问题。

1.4 版本冲突的常见场景

好了,前面都是铺垫,下面才是真正的“暗雷”。我在排过不下五十次发布崩溃后,总结出这几类最常见的冲突:

1.4.1 AGP 版本与 Gradle 版本不匹配

这是“起步就摔”的经典。比如你引入了一个只支持 AGP 8.x 的三方库,但你项目还在用 AGP 4.2。结果 build 时直接报:

ERROR: Minimum supported Gradle version is X.X.X.
Current version is Y.Y.Y.

解决方案:升级 AGP 同时升级 Gradle wrapper。我建议把这两个放在同一个 commit 里,免得同事拉代码后一脸懵。

1.4.2 三方库强制约束了 AGP 版本

有些库(比如 Firebase、Google Play Services)会在自己的 POM / 模块元数据里声明对 AGP 版本的要求。一旦你用的 AGP 低于它的下限,就会触发依赖冲突。典型的错误信息:

Unable to resolve dependency for ':app@debug/compileClasspath':
Could not resolve com.example:library:1.0.
Required by: project :app
> Failed to list versions for com.example:library.

嗯,这种我遇到过最坑的是一次发布前夜,Firebase 推送了新版本,但要求 AGP 7.4+。我们还在 7.0 上,结果被迫通宵升级…

1.4.3 AGP 内部组件版本冲突

AGP 本身包含一堆子组件:构建工具(build-tools)、SDK 构建工具(Android SDK Build-tools)、Lint、D8、R8…这些组件也有版本号。如果你手工指定了不同路径下的版本,就会炸。

举个例子:

android {
    buildToolsVersion "33.0.2"
}

但是你本地 SDK 里安装的 build-tools 是 34.0.0。这时候 AGP 会尝试用你指定的旧版本,如果缺少对应文件或内部接口变了…嗯,又是一场灾难。

1.4.4 多个 Module 中 AGP 版本不一致

多模块项目里,每个 Module 的 build.gradle 都可能有自己的 AGP 依赖。如果主 app 用了 8.0,某个 library 用了 7.4,Gradle 在 resolution 阶段就会抛出:

Plugin [id: 'com.android.application' version: '8.0.0'] was not found in any of the following sources:
- dependencies {
    classpath 'com.android.tools.build:gradle:7.4.0'
  }

解决起来很简单:根项目的 buildscript 里统一声明 AGP 版本,子模块全部省略 version。但很多历史项目没这么做,我重构过一个项目,光改这个就改了 30 个文件…

最佳实践:在根项目的 build.gradle 中用 extra 属性定义 AGP 版本,所有子模块用 com.android.application 但 apply false。这样一处改,全局生效。

// 根 build.gradle
buildscript {
    ext {
        agp_version = '8.1.4'
    }
    dependencies {
        classpath "com.android.tools.build:gradle:$agp_version"
    }
}
// 子模块只 apply,不写 version
apply plugin: 'com.android.application'

1.5 本章知识体系

AGP 版本冲突知识体系 Android Gradle Plugin 作用:编译·打包·签名 发展历史(1.x → 8.x) 与 Gradle 版本绑定 版本冲突 Gradle 版本不匹配 三方库强制依赖 内部组件版本矛盾 多 Module 不一致 💡 避坑要点 • 升级 AGP 前确认 Gradle 版本是否满足下限 • 根项目统一声明 AGP 版本号,子模块不写 version 常见错误信息 Minimum supported Gradle version is 8.0. Current is 7.0. Plugin [id: 'com.android.application'] was not found. Unable to resolve dependency... Failed to list versions.

1.6 总结:你该记住的

聊了这么多,其实核心就三点:

  1. AGP 和 Gradle 是夫妻,版本必须门当户对,否则直接离婚 (build 失败)。
  2. 版本冲突的根因:要么是手动写死了不兼容的版本,要么是被三方库间接拖拽。
  3. 解决方案思路:统一管理、按官方表格升级、不要乱改 build-tools。

我的一点经验:每次新项目初始化,我习惯第一时间在根 build.gradle 用 ext.agp_version = '8.x.x' 锁死版本。然后所有子模块直接 apply plugin: 'com.android.application' 不写版本——这样未来升级改一个地方就够了。

好了,第一章就到这里。AGP 这块儿概念比较多,但别慌,后面的章节我们一个一个场景拆,把那些让你头疼的“发布崩溃”彻底掰开揉碎。