1 - Flutter Android 构建的版本地狱:为什么改一个版本要改一堆?

前言

如果你在构建 Flutter Android 应用时遇到过这样的错误:

Could not resolve all files for configuration ':surface:androidJdkImage'.
Error while executing process jlink with arguments...

然后按照提示升级了 AGP(Android Gradle Plugin),结果又报错说找不到仓库,再加上仓库后又说 Gradle 版本不对,再升级 Gradle 后又说 Kotlin 版本太旧…

恭喜你,欢迎来到 Flutter Android 构建的版本地狱 🔥

本文将深入解析这背后的原因,以及如何优雅地解决这类问题。

一、问题的本质:多层依赖链

Flutter Android 项目的构建涉及一条复杂的依赖链:

Flutter (Google Flutter 团队)
  ↓
Android Gradle Plugin / AGP (Google Android 团队)
  ↓
Gradle (Gradle Inc.)
  ↓
Kotlin (JetBrains)
  ↓
Java/JDK (Oracle/OpenJDK)

关键问题:这些工具由不同的组织开发,各自独立发版,但又必须相互兼容。

典型的版本兼容矩阵

AGP 版本最低 Gradle 版本推荐 Kotlin 版本最低 Java 版本
7.4.07.51.8.0+11
8.0.08.01.8.10+17
8.1.08.01.8.22+17
8.2.18.21.9.0+17
8.3.08.41.9.20+17

一旦某一层不兼容,整个构建就会失败。

二、真实案例分析

案例:Java 21 + AGP 8.1.0 的灾难

场景

  • 你的电脑升级到了 Java 21(可能是 Android Studio 自动更新的)
  • 项目使用 AGP 8.1.0
  • 尝试构建 Release 版本

错误信息

Error while executing process jlink with arguments
{--module-path ... --add-modules java.base ...}

根本原因

AGP 8.1.0 及以下版本在处理 Java 模块系统时有一个已知 bug(Issue 294137077),当遇到 Java 21 的新特性时会失败。

解决方案

1
2
// 必须升级到 AGP 8.2.1+
id "com.android.application" version "8.2.1" apply false

但这只是开始…

连锁反应

升级 AGP 后,你会遇到:

问题 1:找不到依赖

Cannot resolve external dependency com.android.tools.build:gradle:8.2.1
because no repositories are defined.

原因:忘记配置仓库

解决

1
2
3
4
5
6
pluginManagement {
    repositories {
        google()
        mavenCentral()
    }
}

问题 2:Gradle 版本太旧

AGP 8.2.1 requires Gradle 8.2 or higher.
Current version is 7.6.

解决:升级 gradle-wrapper.properties

1
distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-all.zip

问题 3:Kotlin 版本不兼容

This version of Gradle requires Kotlin Gradle plugin version 1.9.0 or higher.

解决

1
id "org.jetbrains.kotlin.android" version "1.9.20" apply false

一个简单的构建错误,最终需要修改 4-5 个配置文件!

三、为什么会这么复杂?

1. 历史包袱

2008 年 - Android 发布
2012 年 - Gradle 成为 Android 官方构建工具
2017 年 - Kotlin 成为 Android 官方语言
2018 年 - Flutter 1.0 发布
2023 年 - Java 21 发布(LTS 版本)

每个工具都有 10+ 年的历史,必须保持向后兼容。

2. 独立团队的协调成本

  • Google Flutter 团队:关注跨平台体验
  • Google Android 团队:关注 Android 生态
  • Gradle Inc.:构建工具公司,服务多个平台
  • JetBrains:Kotlin 语言开发商
  • Oracle/OpenJDK:Java 语言维护者

这些团队发版节奏不同,优先级也不同。

3. 构建工具的特殊性

Gradle 是个自举系统(bootstrap system):

问:用什么下载 Gradle?
答:用 Gradle Wrapper

问:Gradle Wrapper 从哪来?
答:从 Gradle 仓库下载

问:怎么配置仓库?
答:写在 Gradle 配置文件里

问:Gradle 还没下载,怎么读配置文件?
答:...这就是鸡生蛋蛋生鸡的问题

这导致版本协调必须在多个层次手动配置。

四、新版 vs 旧版项目结构

Flutter 在 3.16 版本引入了新的项目结构来简化配置。

旧版结构(Flutter 3.15 及以下)

android/build.gradle

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
buildscript {
    repositories {
        google()
        mavenCentral()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:7.4.0'
        classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.0'
    }
}

allprojects {
    repositories {
        google()
        mavenCentral()
    }
}

android/settings.gradle

1
include ':app'

新版结构(Flutter 3.16+)

android/settings.gradle

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
pluginManagement {
    repositories {
        google()
        mavenCentral()
    }
}

plugins {
    id "dev.flutter.flutter-plugin-loader" version "1.0.0"
    id "com.android.application" version "8.2.1" apply false
    id "org.jetbrains.kotlin.android" version "1.9.20" apply false
}

include ":app"

android/build.gradle

1
2
3
4
5
6
allprojects {
    repositories {
        google()
        mavenCentral()
    }
}

新版结构的优势

  1. 集中管理插件版本:所有插件版本在 settings.gradle
  2. 更清晰的职责分离
    • settings.gradle:插件和仓库配置
    • build.gradle:项目级配置
    • app/build.gradle:应用级配置
  3. 符合 Gradle 最佳实践:使用 pluginManagement

五、如何判断项目结构版本

快速判断法

检查 android/settings.gradle

新版结构

1
2
3
4
5
plugins {
    id "dev.flutter.flutter-plugin-loader" version "1.0.0"
    id "com.android.application" version "X.X.X" apply false
    // ↑ 有 plugins 块和 flutter-plugin-loader = 新版
}

旧版结构

1
2
include ':app'
// ↑ 只有简单的 include 语句 = 旧版

判断矩阵

特征新版旧版
settings.gradleplugins
build.gradlebuildscript
包含 flutter-plugin-loader
Flutter 版本3.16+3.15-

六、终极解决方案

方案 A:推荐的稳定版本组合(2024-2025)

1
2
3
4
5
6
# 推荐配置
Flutter: 3.24.x
Java: 17 (不要用 21,除非必须)
Gradle: 8.2
AGP: 8.2.1
Kotlin: 1.9.20

配置文件

android/settings.gradle(新版结构):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
pluginManagement {
    repositories {
        google()
        mavenCentral()
    }
}

plugins {
    id "dev.flutter.flutter-plugin-loader" version "1.0.0"
    id "com.android.application" version "8.2.1" apply false
    id "org.jetbrains.kotlin.android" version "1.9.20" apply false
}

include ":app"

android/gradle/wrapper/gradle-wrapper.properties

1
distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-all.zip

android/app/build.gradle

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
android {
    namespace "com.example.app"
    compileSdk 34

    defaultConfig {
        minSdk 21
        targetSdk 34
    }

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_17
        targetCompatibility JavaVersion.VERSION_17
    }

    kotlinOptions {
        jvmTarget = '17'
    }
}

方案 B:旧版结构迁移到新版

步骤

  1. 备份项目
  2. 升级 Flutter:flutter upgrade
  3. 重新生成 Android 配置:
    1
    2
    3
    4
    
    cd android
    rm -rf build.gradle settings.gradle
    cd ..
    flutter create --platforms=android .
    
  4. 恢复自定义配置(如私有仓库)

七、预防措施和最佳实践

1. 版本锁定

在项目根目录创建 VERSIONS.md

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# 项目依赖版本

- Flutter: 3.24.5
- Dart: 3.5.4
- Java: 17.0.9
- Gradle: 8.2
- AGP: 8.2.1
- Kotlin: 1.9.20

## 构建环境

- macOS: 14.0+
- Android Studio: 2023.3.1+

## 最后更新: 2024-12-23

2. 使用 FVM 管理 Flutter 版本

1
2
3
4
5
6
7
8
# 安装 FVM
dart pub global activate fvm

# 锁定项目 Flutter 版本
fvm use 3.24.5

# 使用指定版本运行命令
fvm flutter build apk

3. Docker 化构建环境

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
FROM cirrusci/flutter:3.24.5

# 固定 Java 版本
RUN apt-get update && apt-get install -y openjdk-17-jdk

# 设置环境变量
ENV JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64
ENV PATH=$JAVA_HOME/bin:$PATH

WORKDIR /app
COPY . .

RUN flutter pub get
RUN flutter build apk --release

4. CI/CD 配置示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# .github/workflows/build.yml
name: Android Build

on: [push, pull_request]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      - uses: actions/setup-java@v3
        with:
          distribution: 'temurin'
          java-version: '17'

      - uses: subosito/flutter-action@v2
        with:
          flutter-version: '3.24.5'
          channel: 'stable'

      - run: flutter pub get
      - run: flutter build apk --release

5. 团队协作规范

强制使用相同环境

1
2
3
4
# 项目根目录创建 .tool-versions (适用于 asdf)
flutter 3.24.5
java openjdk-17
gradle 8.2

pre-commit hook

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
#!/bin/bash
# .git/hooks/pre-commit

# 检查 Flutter 版本
FLUTTER_VERSION=$(flutter --version | grep -oP "Flutter \K[0-9]+\.[0-9]+\.[0-9]+")
EXPECTED_VERSION="3.24.5"

if [ "$FLUTTER_VERSION" != "$EXPECTED_VERSION" ]; then
    echo "错误:Flutter 版本不匹配"
    echo "期望: $EXPECTED_VERSION"
    echo "实际: $FLUTTER_VERSION"
    exit 1
fi

八、常见错误速查表

错误信息原因解决方案
jlink error with Java 21AGP < 8.2.1 不支持 Java 21升级 AGP 到 8.2.1+
Cannot resolve dependency缺少仓库配置pluginManagement 添加仓库
Gradle version too oldAGP 需要更新的 Gradle升级 gradle-wrapper.properties
Kotlin plugin versionKotlin 版本与 Gradle 不兼容升级 Kotlin 到 1.9.0+
namespace not specifiedAGP 8.0+ 需要 namespaceapp/build.gradle 添加 namespace
Unsupported class file major versionJava 版本太新降级到 Java 17 或升级 AGP

九、未来展望

Flutter 和 Android 团队正在努力改进:

已实现的改进

  • ✅ 新版项目结构(Flutter 3.16+)
  • ✅ 更友好的错误提示(Flutter Fix)
  • ✅ 自动版本检测警告

计划中的改进

  • 🚧 自动依赖版本协调
  • 🚧 统一的版本管理工具
  • 🚧 更详细的兼容性文档

社区期望

  • 🔮 一键升级命令:flutter upgrade android-deps
  • 🔮 版本冲突自动修复
  • 🔮 可视化依赖管理界面

十、总结

Flutter Android 构建的版本地狱源于:

  1. 多个独立组织的工具链整合
  2. 历史包袱和向后兼容性要求
  3. 构建系统的自举特性
  4. 缺乏统一的版本协调机制

应对策略

  • ✅ 使用稳定的版本组合
  • ✅ 锁定开发环境版本
  • ✅ 理解依赖关系链
  • ✅ 保持配置文件简洁
  • ✅ 记录和分享工作配置

虽然现状不完美,但理解了这些依赖关系后,你就能快速定位和解决问题,而不是在错误信息中迷失方向。

版本推荐

  • Flutter 版本:3.24.x
  • 推荐 AGP:8.2.1
  • 推荐 Java:17 最后的建议:如果配置正常工作,就不要随意升级 — 这不是保守,而是务实 😉

参考资源

2 - 解决 Flutter 插件在 Android Studio 中的 Gradle 版本冲突

问题现象

在 Android Studio 中打开 Flutter 插件的 Android 目录时,遇到以下错误:

Build file '~/libpag/flutter-ext/android/build.gradle' line: 23
A problem occurred evaluating root project 'libpag_flutter'.
> 'org.gradle.api.artifacts.Dependency org.gradle.api.artifacts.dsl.DependencyHandler.module(java.lang.Object)'
* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.
> Get more help at https://help.gradle.org.
Deprecated Gradle features were used in this build, making it incompatible with Gradle 10.0.
You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.
For more on this, please refer to https://docs.gradle.org/9.0-milestone-1/userguide/command_line_interface.html#sec:command_line_warnings in the Gradle documentation.

问题原因

这是典型的 Gradle 版本与 Android Gradle Plugin (AGP) 版本不兼容问题。

在 Android 项目中,有两个关键版本需要匹配:

  1. Gradle 版本:构建工具本身(如 7.5, 8.0, 9.0)

    • 定义在 gradle/wrapper/gradle-wrapper.properties
  2. AGP 版本:Android 专用插件

    • 定义在 build.gradleclasspath 'com.android.tools.build:gradle:x.x.x'

版本兼容关系:

Gradle 版本AGP 版本
7.4 - 7.67.3.0 - 7.4.2
8.0 - 8.38.0.0 - 8.1.4
8.4+8.2.0+

Flutter 插件的特殊性

Flutter 插件项目通常没有 gradle-wrapper.properties 文件,因为它依赖宿主应用的 Gradle 配置。

但在 Android Studio 中直接打开插件的 android 目录时,IDE 会将其视为独立项目,使用默认 Gradle 版本(可能是 9.0),导致与旧版 AGP 冲突。

解决方案

方案一:创建 gradle-wrapper.properties(推荐)

android/gradle/wrapper/ 目录下创建 gradle-wrapper.properties

1
2
3
4
5
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

方案二:升级 AGP 版本

修改 android/build.gradle

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
buildscript {
    ext.kotlin_version = '1.9.0'
    repositories {
        google()
        mavenCentral()
    }
    dependencies {
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
        classpath 'com.android.tools.build:gradle:8.1.4'  // 升级到 8.1.4
    }
}

allprojects {  // 注意:去掉 rootProject
    repositories {
        google()
        mavenCentral()
    }
}

方案三:在 Android Studio 中配置

  1. 打开 File → Settings → Build Tools → Gradle
  2. 选择 Use Gradle from: ‘specified location’
  3. 指定或下载 Gradle 7.5

建议

对于 Flutter 插件开发,推荐方案一,改动最小且不影响插件在实际 Flutter 项目中的使用。

执行任一方案后,点击 Android Studio 的 Sync Now 重新同步项目即可。