AGP 与 Gradle 关系:插件背后的协作逻辑

说实话,很多刚接触 Android 构建的同学,会把 AGP 和 Gradle 当成同一个东西。不太准确。

我习惯这么理解:Gradle 是舞台,AGP 是上台表演的演员。舞台搭好了,演员才能演好戏。但舞台版本不对,演员可能直接摔跤。

咱们这一章,就聊清楚这两者到底怎么配合,以及版本兼容性这个“暗坑”到底藏在哪里。

AGP 本质:一个 Gradle 插件

AGP(Android Gradle Plugin)说白了就是一个 Gradle 插件包。它实现了 Plugin 接口,在 Gradle 构建生命周期的特定阶段被加载执行。

我遇到过不少同事直接往 build.gradle 里写 com.android.application,觉得这就是个字符串。实际上它指向的是一个 Jar 包里的插件类。Gradle 会反射创建这个类的实例,然后调用 apply() 方法。

这个插件负责的事情:

  • 注册 Android 专属的 Task(如 mergeDex, compileDebugKotlin)
  • 注入 Android DSL 配置(android {} 块里的所有东西)
  • 处理资源、代码、依赖合并等复杂逻辑

你可以把 AGP 看作一个“任务工厂”,告诉 Gradle 在构建时应该做哪些事、怎么做。

关键点:没有 Gradle 的构建框架,AGP 什么也干不了。同样地,没有 AGP,Gradle 也不知道怎么编译 Android 应用。

Gradle 版本兼容性:为什么非要对齐?

AGP 和 Gradle 有严格的版本对应关系。我用一张表帮你理清常见的组合:

AGP 版本 最低 Gradle 版本 推荐 Gradle 版本
8.0.x 8.0 8.2+
8.1.x 8.1 8.3+
8.2.x 8.2 8.4+
8.3.x 8.3 8.5+
8.4.x 8.4 8.6+

为什么会这样?因为 AGP 内部依赖了 Gradle API 的某些接口,如果 Gradle 版本太老,那些接口不存在或行为不同,加载就会直接报错。最典型的错误:Gradle version X is required. Current version is Y。

注意:不要只看“最低版本”。我曾经遇到过 AGP 8.2 + Gradle 8.2 编译没问题,但 CI 上跑多个 variant 时莫名卡死。后来查官方文档发现 8.2.0 有个 bug,必须升到 8.2.1 才修。所以建议永远使用推荐版本。

AGP 插件如何被 Gradle 加载和执行?

整个过程大概几步:

  1. 初始化阶段:Gradle 解析 settings.gradle,确定项目结构,建立 project 对象。
  2. 配置阶段:Gradle 执行 build.gradle 脚本,遇到 plugins {} 或 apply plugin: 'com.android.application',就会去 classpath 里找对应的 Jar。
  3. 插件应用:Gradle 调用插件的 apply(Project project) 方法。AGP 在这里做三件事:
    • 注册 android 扩展 DSL
    • 分析 variant 维度(debug/release, flavor)
    • 创建对应的 Task 图
  4. 执行阶段:Gradle 按照 Task 依赖关系依次执行,AGP 的 Task 就在这个阶段完成编译、打包、签名。

我画了一张图帮你更直观地理解:

AGP 与 Gradle 协作流程 Gradle 构建框架 初始化 & 配置 AGP 插件 注册 android DSL 创建 Task 图 执行构建任务 APK / AAB 版本兼容性约束 AGP版本 ↔ Gradle版本 必须一一对应 ① Gradle 初始化项目,解析构建脚本 ② AGP 插件被加载,注册 DSL 和 Task ③ 根据 Task 依赖图执行构建 ④ 输出最终产物 APK / AAB

版本不兼容会怎样?

直接点,项目跑不起来。最常见的是下面这种错误:

An exception occurred applying plugin request [id: 'com.android.application']
> Failed to apply plugin 'com.android.internal.version-check'.
   > Minimum supported Gradle version is 8.3. Current version is 8.1.
     If using the gradle wrapper, try editing the distributionUrl in gradle-wrapper.properties

这个错误信息算是比较友好的了,直接告诉你要升到 8.3。但有时候报错没那么直接。我曾经遇到过一个项目,AGP 8.1 + Gradle 8.2,配置阶段正常,一运行 Task 就崩,报的是 NoSuchMethodError。一看堆栈,AGP 调用了 Gradle 8.3 才有的 API。所以别指望“碰运气”,版本对不上迟早出事。

我的做法:每次升级 AGP 大版本前,先去 官方兼容性表格 确认 Gradle 版本。然后在本地跑一次 ./gradlew clean build,确定没问题再提交 CI 配置。

Gradle Wrapper 才是关键

很多人直接本地装了 Gradle 8.5,但项目的 gradle-wrapper.properties 里写的还是 8.1。我建议你养成习惯:只看 distributionUrl 里的版本,那才是真正被使用的 Gradle 版本。

distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

这块在 CI 环境里尤其容易出问题。我见过太多 CI 机器上本地装了一个高版本 Gradle,但 wrapper 指向低版本,结果 AGP 兼容性检查通过,但运行时因为 API 不一致崩了。记住:CI 用的永远是 wrapper 指定的版本,不是你机器上装的那个。

总结一下

AGP 和 Gradle 的关系可以浓缩成三句话:

  • AGP 是 Gradle 的插件,依赖 Gradle API 工作
  • 版本必须严格配对,大版本不对直接报错
  • 用小版本推荐版,避免踩 bug