Gradle 与 AGP:不只是调用关系

说实话,很多刚接触 Android 的朋友会把 Gradle 和 AGP 混为一谈。我之前带新人时就发现,配置文件里一行 id 'com.android.application',他们以为 "这就是 Gradle 本身"。其实不是的。

Gradle 是个通用的构建工具,它不知道什么叫 Android、什么叫 APK。真正让 Gradle 懂 Android 的,是 AGP —— Android Gradle 插件。AGP 就是一个 Gradle 插件,它把 Android 的编译、打包、签名等逻辑「注入」到 Gradle 的构建流程里。

通过 Gradle 插件集成 AGP

集成 AGP 的方式,说白了就两种。我习惯用新版的 plugins 块,简洁且支持版本锁定:

// settings.gradle.kts
pluginManagement {
    repositories {
        google()
        mavenCentral()
        gradlePluginPortal()
    }
}

// app/build.gradle.kts
plugins {
    id("com.android.application") version "8.2.2" apply false
}

// app/build.gradle.kts
plugins {
    id("com.android.application")
}

如果你还在用老项目,可能看到的是这种写法:

// app/build.gradle
buildscript {
    repositories {
        google()
    }
    dependencies {
        classpath "com.android.tools.build:gradle:8.2.2"
    }
}

apply plugin: "com.android.application"

哪种更好?我个人推荐 plugins 块。原因是它可以避免许多依赖冲突问题。我记得有次帮同事排查构建问题,他用的是旧式的 apply plugin,结果项目里两个子模块引了不同版本的 AGP,直接炸了——编译都过不去。换成 plugins 块统一声明后,问题就解决了。

一点小建议: 不管用哪种方式,记得在 settings.gradle.kts 里把 google() 仓库放在第一位。AGP 和 AndroidX 的依赖都从 Google 的 Maven 仓库拉,顺序不对很容易卡网络或报 404。

版本兼容性——最容易踩坑的地方

AGP 和 Gradle 的版本是有严格对应关系的。不是说你用最新的 AGP 就行,还得看你的 Gradle 版本是否支持。我曾经在项目里直接把 AGP 从 7.0 跳到 8.2,没改 Gradle wrapper 版本,结果编译报错提示 API 不兼容。折腾了半天才发现 Gradle 版本太低。

下面这张表格是我从历年升级中整理出来的「AGP - Gradle 版本对应表」,有些公司内部的基线会用这些组合:

AGP 版本 最低 Gradle 版本 推荐 Gradle 版本 备注
8.3.x 8.4 8.5+ 支持 Java 17 编译
8.2.x 8.2 8.4 稳定版,推荐升级
8.1.x 8.0 8.2 旧项目过渡用
8.0.x 8.0 8.1 最低要求 Gradle 8.0
7.4.x 7.5 7.6 部分老库仍用此版本
7.3.x 7.4 7.5 注意 NDK 兼容
注意: 千万不要只看最低版本,还要检查你用的 Gradle wrapper 是否与 AGP 的 API 完全兼容。比如 AGP 8.2 要求 Gradle 8.2,但如果你用了 Gradle 8.4,大部分情况没问题;反过来说,用 Gradle 8.0 跑 AGP 8.2 就一定会报错。

怎么知道当前项目该用哪个 AGP?

我的做法是两步走:

  1. 查 Gradle 版本: 运行 ./gradlew --version,或者看 gradle/wrapper/gradle-wrapper.properties 里的 distributionUrl。
  2. 查 AGP 版本: 看项目根目录 build.gradle 或 settings.gradle 里声明的 com.android.tools.build:gradle 版本号。

然后对照上面的表格,就能知道当前组合是否合法。举个例子,如果你发现自己的 Gradle 是 7.6,AGP 是 8.1,那就要小心了——7.6 其实不满足 8.1 的 Gradle 最低要求(8.0)。虽然有时低版本 Gradle 也能勉强运行 AGP 8.1,但你会遇到各种诡异的缓存错误,比如 R 资源找不到、BuildConfig 不生成之类。我在升级 AGP 8.2 时就被这种问题坑过,后来严格按表格走,再没出现类似情况。

核心原则: AGP 的每次大版本更新,都可能会废弃或修改 Gradle 的某些 API。你最好把 Gradle 升级到 AGP 推荐版本的上一个或同版本,这样能避免 90% 的兼容性问题。

知识结构速览

下面这张图是我自己总结的「Gradle ↔ AGP ↔ SDK 调用链路」,能帮你快速理清它们之间的关系:

Gradle 与 AGP 集成关系及版本兼容链路 Gradle 构建系统 apply / plugins 块 AGP (Android Gradle Plugin) Android SDK / Build Tools Gradle API / 版本 版本兼容性检查表(AGP ↔ Gradle) 建议:每次 AGP 大版本升级前,先查看官方兼容表,同步升级 Gradle wrapper

从这张图能看出来,AGP 处于中间枢纽位置:上面通过 plugins 或 apply plugin 被 Gradle 加载,下面同时依赖 Android SDK 和 Gradle API 的版本。任何一个不匹配,都会导致构建失败。我之前在升级到 AGP 8.2 时就忘了升级 Gradle 到 8.2,结果 SDK 工具链报了一大堆 "API level 34 not supported" —— 其实根本不是 SDK 的问题,是 Gradle 版本太老,AGP 8.2 用了一个它不认识的 API。

避坑指南:升级三步曲

如果你现在正准备给项目升级 AGP,我的建议是:

  • 第一步: 确认当前 Gradle 版本,在官方兼容性矩阵中找到对应的最高 AGP 版本(不要直接跳大版本,比如从 7.0 直接到 8.3,最好 7.4 → 8.0 → 8.2 逐步升级)。
  • 第二步: 修改 gradle-wrapper.properties 里的 Gradle 版本到推荐值,执行 ./gradlew wrapper --gradle-version 8.4 更新 wrapper。
  • 第三步: 修改 plugins 或 buildscript 中的 AGP 版本号,然后 ./gradlew clean 后全量构建。
再次强调: 千万别跳过 Gradle 版本升级直接改 AGP。我曾经图省事,直接用低版本 Gradle 跑高版本 AGP,结果 lint 插件和 kapt 全都报 ClassNotFoundException,浪费了一整天排查。老老实实按表格升,反而最快。

总结一下重点

  • AGP 是一个 Gradle 插件,通过 plugins 块集成到 Gradle 里。
  • 每个 AGP 版本有对应的最低 Gradle 版本要求,不满足则无法编译。
  • 升级时优先看官方兼容表,同步升级 Gradle wrapper,而不是只改 AGP 版本号。
  • 推荐使用新版 plugins 声明方式,避免旧式 apply plugin 的依赖混乱问题。

嗯,核心就这些。下个阶段我们就要真正动手画瀑布图了——不过前提是你已经能把 Gradle 和 AGP 的关系理顺。搞不定兼容性的话,后边的所有性能分析都没法跑。所以别嫌这章啰嗦,基础打牢了才能走远。