Flutter 安卓打包踩坑实录:Gradle 卡死、NDK 偷跑与增量缓存崩溃


📝 本文由 DeepSeek(AI) 根据博主本人的构建排查记录整理总结,部分表述可能与实际略有出入,仅供学习参考。

国内网络下用 Flutter 打安卓包,是件很考验耐心的事。表面上只是一行 Running Gradle task 'assembleRelease'...,背后却可能卡上几十分钟、偷偷下 1GB 的 NDK、或者因为一个锁文件直接构建失败。

这篇不讲具体项目,只把这一轮排查里踩到的坑一条条记下来,给同样被 Flutter 安卓构建折磨的人省点时间。前提是环境变量里的国内镜像(pub、Flutter 引擎)都已经配好——这些是基础,不再展开。

坑 1:卡在 assembleRelease 几十分钟,CPU 却是 0

现象:Flutter 只打印一行 Running Gradle task 'assembleRelease'... 就再也不动了。Gradle 守护进程 CPU 占用几乎为 0,build/ 目录迟迟不出现。

根因:这不是”编译慢”,而是 Flutter 自带的 Gradle 构建在绕过项目镜像、直连国外 Maven Central 下载依赖。

Flutter SDK 里的 packages/flutter_tools/gradle/ 是一个独立的 included build,它有自己的 settings.gradle.kts 和 resolve_dependencies.gradle.kts,里面只写了 google() / mavenCentral(),不读项目里的镜像配置——项目镜像只作用于 app 模块自己的依赖。

验证:用 Get-NetTCPConnection 看 java 进程连了哪个 IP,再用 Resolve-DnsName 反查,发现连的是 repo.maven.apache.org(Maven Central)。

修复:给上面两个文件在 google() / mavenCentral() 之前 插入阿里云镜像(改前先备份成 .bak):

maven { url = uri("https://maven.aliyun.com/repository/public") }
maven { url = uri("https://maven.aliyun.com/repository/google") }
maven { url = uri("https://maven.aliyun.com/repository/gradle-plugin") }  // settings 里加

实测同一个 kotlin-stdlib 的 pom:阿里云 0.1s,Maven Central 3.2s,差约 30 倍。

⚠️ 这是改 Flutter SDK 源码,flutter upgrade 或重装 SDK 会被覆盖,需要重做。改完记得删掉 packages/flutter_tools/gradle/build 强制插件重编。

排查手段(复用):看守护进程日志 daemon-<pid>.out.log(注意 GRADLE_USER_HOME 不一定是 C:\Users\<你>\.gradle);用 Get-NetTCPConnection 看连接、Resolve-DnsName 反查 IP 归属。

坑 2:构建时偷偷下载 1GB 的 NDK

现象:构建很慢或卡住,任务管理器里能看到 sdkmanager --install ndk;28.2.xxxxx 在下 NDK。

根因:项目间接依赖了某个用了 jni 的插件,它的 android/build.gradle 写死了 ndkVersion = flutter.ndkVersion;而 flutter.ndkVersion 的默认值在 Flutter SDK 里是 28.2.xxxxx,不受 App 自己 android.ndkVersion 的影响,AGP 就去下这个版本了。

修复:把 Flutter SDK 里两处默认 NDK 改成本机已装的版本(各留 .bak):

  • packages/flutter_tools/gradle/src/main/kotlin/FlutterExtension.kt 的 ndkVersion
  • packages/flutter_tools/lib/src/android/gradle_utils.dart 的 const ndkVersion

NDK 向后兼容,新版本能编旧代码。顺手把半截的 ndk/28.2.xxxxx 删掉。

坑 3:Gradle 锁冲突 Timeout waiting to lock build logic queue

现象:报 Lock file: android\.gradle\noVersion\buildLogic.lock,Owner PID 和 Our PID 不同。

根因:同时有两个 Gradle 守护进程抢同一个项目锁。常见于:改了 gradle.properties 的 jvmargs 后新旧守护进程并存、Android Studio 和命令行同时构建、或 Ctrl+C 后立刻重跑。

修复:确保 AS 已关闭,Get-Process java | Stop-Process -Force 清掉所有守护进程,再只跑一次 构建,不要重复触发。

铁律:构建期间要么只用 Android Studio,要么关掉 AS 只用命令行,二选一。 两边同时构建必抢锁。

坑 4:Kotlin 增量编译缓存损坏

现象:Execution failed for task ':xxx:compileReleaseKotlin',Caused by: java.lang.AssertionError: Could not close incremental caches ... caches-jvm ...。

根因:反复 Ctrl+C / 强杀 Java 进程,把 Kotlin 增量缓存写坏了。

修复:删掉项目 build/ 整个目录;并在 android/gradle.properties 加:

kotlin.incremental=false

以后即使中断也不会再损坏缓存。代价是 Kotlin 每次全量编译,稍慢但更稳。

坑 5:开了并行构建反而触发 AGP 竞态

现象:

  • :jni:stripReleaseDebugSymbols → NoSuchFileException: ...\libdartjni.so
  • :local_auth_android:syncReleaseLibJars → IllegalArgumentException: !directory.isDirectory

根因:org.gradle.parallel=true 让任务乱序执行——stripReleaseDebugSymbols 在 mergeReleaseNativeLibs 生成文件之前就跑了。那些”缺失”的文件其实构建结束后都存在,是可复现的竞态。

修复:关掉并行与缓存:

org.gradle.parallel=false
org.gradle.caching=false

稳定优先,等确认能出包后再考虑打开。

坑 6:全局 init.gradle 让 Flutter 构建直接报错

现象:Build was configured to prefer settings repositories over project repositories...

根因:Flutter 的 packages/flutter_tools/gradle/settings.gradle.kts 用了 RepositoriesMode.FAIL_ON_PROJECT_REPOS,而全局 ~/.gradle/init.gradle(或 ~/.gradle/init.d/init.gradle)里的 allprojects { repositories { ... } } 会往所有构建注入 project 级仓库,直接触发这个限制。

修复:把全局 init 里的 project 级 repositories{...} 删掉(原文件备份 .bak),镜像改到项目内:

  • android/settings.gradle.kts 的 pluginManagement.repositories
  • android/build.gradle.kts 的 allprojects.repositories

另外要记住:init.gradle 管不了 Gradle 发行包下载。init 脚本只影响依赖仓库,下载 gradle-x.zip 由 wrapper 的 distributionUrl 决定。

坑 7:Gradle 堆给太大,反而卡死

本机内存不大(12GB)时,-Xmx8G 加上 Android Studio 会触发内存换页,越跑越卡。改成:

org.gradle.jvmargs=-Xmx4G -XX:MaxMetaspaceSize=1G
org.gradle.daemon=true
org.gradle.vfs.watch=true

够用就行,堆不是越大越好。

坑 8:杂项零碎

  • Flutter 工程没有 android/gradlew:它被 .gitignore 忽略,flutter build 时才自动生成,别指望直接跑 gradlew.bat。
  • Gradle 发行包要单独配镜像:依赖仓库有镜像不代表发行包有,wrapper 的 distributionUrl 要指向腾讯/阿里云镜像,并保留官方 distributionSha256Sum 校验。
  • compileSdk 拉高要补装平台:比如 compileSdk = 36 就需要 platforms;android-36,否则会报缺平台。
  • Android Studio 报 “not a Gradle-based project”、Generate APKs 是灰的属正常:Flutter 工程根目录没有 settings.gradle,Gradle 工程在 android\ 子目录,需要 Flutter 插件 把它挂成子项目——而插件必须先配好 Flutter SDK 路径才会做这一步。修法:Settings → Languages & Frameworks → Flutter 填好 SDK 路径 → 完全关闭 AS → 删掉项目 .idea → 重新 Open。
  • Flutter 工程别用 AS 的 Generate Signed Bundle / APK:在 Flutter 工程里它一直是灰的,属正常。用 Build → Flutter → Build APK,或干脆命令行 flutter build apk --release 绕开 IDE 集成,最稳。
  • AS 自带的 Flutter/Dart 插件可能缺失:需要手动装与 AS build 号匹配的版本,升级 AS 后要重装。
  • keystore 丢了就麻烦:同一 applicationId 无法覆盖升级,务必离线备份(这条和具体项目无关,通用)。

小结

Flutter 安卓构建的坑,多数不是”写错代码”,而是网络、镜像、缓存、并发 这些环境层面的问题:

  • 卡住先看网络连的是哪个仓库,而不是无脑等
  • 改 Gradle/Flutter SDK 配置前先备份
  • 稳定优先:parallel / caching / kotlin.incremental 出问题就关
  • 构建并发只留一个入口(AS 或命令行的某一个)

把这几条记住,下次再遇到 assembleRelease 转圈,至少知道从哪下手。


  目录