转载

当你尝试构建 Flutter 应用或  Android 项目时,编译瞬间被 Namespace not specified. Specify a namespace in the module's build.gradle file. 报错卡住。截至 2026 年,随着 Android Gradle Plugin(AGP)8.0 及以上版本成为主流,这个错误在重新打开旧项目、或依赖树中仍保留旧插件时变得极其常见。本文将结合可直接复制的 build.gradle 代码片段,彻底讲解这个错误的本质、成因以及可靠的解决方法。

结论·三行摘要

  • 根本原因是 AGP 8.0 将 namespace 的指定变为强制要求,并废弃了以往用 AndroidManifest.xml 中 package 属性充当命名空间的做法。
  • 最快的解决方法是在 android/app/build.gradle 的 android { } 块中加入 namespace "com.example.your_app",删除 Manifest 中的 package 属性,然后执行 flutter clean
  • 如果罪魁祸首是旧插件而非你自己的代码,请更新该插件,或在根目录 build.gradle 中注入 namespace 作为临时规避方案。

这个错误是什么?会出现哪些症状

Namespace not specified. 是 Android 构建工具 AGP 在告诉你:它无法判断某个模块属于哪个命名空间(包名)。从 AGP 8.0 开始,每一个 Android 模块(应用本体、库、插件)都必须在其 build.gradle 中声明 namespace。缺少该声明时,构建会在配置(configuration)阶段停止。

实际的错误信息有几种变体。当问题出在你自己的应用模块时,通常会看到:

FAILURE: Build failed with an exception.

* What went wrong:
A problem occurred configuring project ':app'.
> Namespace not specified. Specify a namespace in the module's build.gradle file
  like so:

  android {
      namespace 'com.example.namespace'
  }

当问题出在插件时,项目名会指向某个依赖而非你的应用:

* What went wrong:
A problem occurred configuring project ':flutter_some_plugin'.
> Could not create task ':flutter_some_plugin:generateDebugRFile'.
   > Namespace not specified. Specify a namespace in the module's build.gradle file.

它们的共同点是:失败发生在编译之前的「项目配置」阶段。即便你的 Dart、 Java 或 Kotlin 逻辑完全没有问题,也会触发。无论是 flutter runflutter build apkflutter build appbundle,还是从 Android Studio 启动,都会以相同方式失败。在 IDE 中它常表现为 Gradle Sync 失败。一个典型场景是「昨天还能跑,更新了 Flutter 或 Android Studio 之后就构建不了了」。

发生的原因

这个错误的根源是 AGP 8.0 引入的破坏性变更。将成因拆分开来,主要有以下四种情形。

原因1:AGP 8.0 将 namespace 声明变为强制要求(破坏性变更)。 在 AGP 7.x 之前,AndroidManifest.xml 中的 属性可以充当命名空间。但 AGP 8.0 彻底移除了对该 package 属性的支持,用于生成 R 类和 BuildConfig 的命名空间现在只能从 build.gradle 的 namespace 中读取。因此,任何依赖 Manifest package 的旧项目,在 AGP 升级到 8.0 及以上的那一刻就会撞上这个错误。

原因2:你自己项目的 build.gradle 中没有 namespace。 用较旧的 Flutter 模板(大致是 Flutter 2.x 之前)生成的项目,android/app/build.gradle 中没有 namespace,因为当时 Manifest 的 package 已经够用。用当前的 Flutter/AGP 构建这类项目时,就会对你的应用模块(:app)报错。

原因3:旧的第三方插件或依赖不支持 namespace。 即使修好了你自己的代码,通过 pub.dev 引入的、尚未适配 namespace 的旧插件仍会在其模块中重现该错误。这在停止维护的库、或长期未更新的依赖上很常见。判别方法是:configuring project ':xxx' 中的名称是插件名,而非你的应用。

原因4:Flutter / AGP / Gradle / Kotlin 版本不匹配。 AGP 8.0 要求 Gradle 8.0+、JDK 17+ 以及兼容的 Kotlin Gradle Plugin。如果你只在 settings.gradle 中升级 AGP 版本,却没有同步 Gradle Wrapper 和 JDK,就可能引发一连串配置错误——其中就包括与 namespace 相关的错误。版本组合本身的错位就是触发点。

走向正确修复的第一步,永远是读懂错误信息中的 project ':___' 部分,判断是你的应用(:app)还是某个插件在作怪。

解决方法1(推荐):在应用的 build.gradle 中添加 namespace

这是最可靠、也应最先尝试的方法。如果原因出在你的应用模块(:app),此法即可解决。

步骤1:确认当前的 applicationId / package

打开 android/app/build.gradle,查看 defaultConfig 中的 applicationId。大多数情况下这就是你想要的命名空间。

android {
    compileSdkVersion 34

    defaultConfig {
        applicationId "com.example.your_app"
        minSdkVersion 21
        targetSdkVersion 34
    }
}

步骤2:在  android 块中添加 namespace

在 android { } 内部(compileSdkVersion 附近)直接添加 namespace。其值应与 applicationId 及原 Manifest 的 package 保持一致。

android {
    namespace "com.example.your_app"   // <- 添加这一行
    compileSdkVersion 34

    defaultConfig {
        applicationId "com.example.your_app"
        minSdkVersion 21
        targetSdkVersion 34
    }
}

若使用 Kotlin DSL(build.gradle.kts),请以赋值形式书写:

android {
    namespace = "com.example.your_app"
    compileSdk = 34
}

步骤3:从  AndroidManifest.xml 中删除 package 属性

删除 android/app/src/main/AndroidManifest.xml 顶部的 package="..." 属性。由于 AGP 8.0 将 namespace 视为唯一信息来源,Manifest 的 package 已无必要,建议删除。

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.your_app">

<manifest xmlns:android="http://schemas.android.com/apk/res/android">

步骤4:用干净构建来确定生效

陈旧缓存可能导致改动不生效,因此重新构建前务必先清理。

flutter clean
flutter pub get
flutter run

请确保 namespace 是有效的  Java 包名(小写字母、以点分隔的段,且任何段不以数字开头)。applicationId 与 namespace 可以相同也可以不同,但为避免混乱,在迁移旧项目时最好保持一致。至此,由 :app 引起的错误几乎必然得到解决。

解决方法2(替代方案):更新 Flutter 并重新生成模板

对于用旧 Flutter 模板生成的项目,build.gradle 的书写格式本身可能与当前 AGP 的预期不符。此时,用最新模板整体重新生成 android 文件夹是最快捷的解决方式。

首先更新 Flutter 本体:

flutter upgrade
flutter --version

接着,在现有项目根目录执行 flutter create .。它会在保留 lib/ 中你自己代码的同时,用最新模板重新生成平台文件夹(android/ios/)。执行前务必先用 Git 提交,以便查看差异。

git add -A && git commit -m "backup before regen"
flutter create --platforms=android .

重新生成后,全新的 android/app/build.gradle 已经内置了 namespace。同时也要一并更新 AGP、Gradle 和 Kotlin 的版本。在近期的 Flutter 项目中,AGP 与 Kotlin 版本在 settings.gradle 的 plugins { } 块中集中管理:

plugins {
    id "com.android.application" version "8.5.0" apply false
    id "org.jetbrains.kotlin.android" version "1.9.24" apply false
}

Gradle Wrapper 版本在 android/gradle/wrapper/gradle-wrapper.properties 中指定。AGP 8.x 需要 Gradle 8.x:

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

如果你曾自定义过 AndroidManifest.xml 等文件,重新生成可能会覆盖它们,因此请对照已提交的差异,手动恢复所需的更改(权限、应用名、图标设置等)。另外注意必须使用 JDK 17 或更高版本。此方法的优势在于能一次性清理多处配置不匹配。

解决方法3(面向高级用户):向旧插件注入 namespace

当错误中的 project ':___' 是插件名时,原因就是该库不支持 namespace。最佳做法是升级到已支持的版本,但对于停止维护的库,你可以在根目录 android/build.gradle 中编写向子项目注入 namespace 的脚本来规避。

subprojects {
    afterEvaluate { project ->
        if (project.hasProperty("android")) {
            project.android {
                if (namespace == null) {
                    namespace project.group
                }
            }
        }
    }
}

该脚本会在每个子项目(插件)被评估后,检查 android 扩展是否存在;若 namespace 未设置,则自动赋值为 project.group(多数情况下即该插件的原包名)。这样无需直接改写插件源码即可补上命名空间。

但请记住,这只是权宜之计。如果 project.group 并非你期望的包名,或多个插件在命名空间上发生冲突,就需要另寻办法。作为永久解决方案,可考虑:(1)查看该插件的 Issue 或 PR,确认是否已发布支持 namespace 的版本;(2)若没有,则自行 fork 并添加 namespace;(3)改用维护活跃的替代插件。请把注入脚本仅当作让构建通过的急救手段,并作为安全运维的一部分,定期检查 CI 日志中是否有警告。

如何预防

只要对版本管理与依赖新鲜度保持关注,就能大幅减少这个错误。要点如下:

首先,定期更新依赖。用 flutter pub outdated 找出过时的依赖,用 flutter pub upgrade 有计划地更新。不长期抱着不支持 namespace 的插件,是最重要的预防措施。

其次,在进行 Flutter 或 AGP 的大版本升级时,务必查阅迁移指南。像 AGP 8.0 这样的破坏性变更,一定会写在官方发行说明和迁移指南里。绝大多数「突然坏了」的事件,其实都是提前公告过的变更。

再次,在 CI 中运行构建验证同样有效。通过 GitHub Actions 在每次 push 时执行 flutter build apk,就能在发布前捕获本地可能忽略的环境相关构建失败。此外,保持项目模板为最新也很重要。新项目始终用最新的 Flutter 通过 flutter create 生成;从旧模板复制资产时,请确认 build.gradle 的格式符合当前规范。养成这些习惯后,你几乎不会再被 AGP 的版本升级打个措手不及。

总结

Namespace not specified. Specify a namespace in the module's build.gradle file. 是由于 AGP 8.0 将 namespace 变为强制要求,并移除了对 AndroidManifest.xml 中 package 属性的回退支持而导致的错误。处理的第一步是读懂信息中的 project ':___',判断原因是你的应用(:app)还是某个依赖插件。

如果是你的应用引起的,只需在 android/app/build.gradle 的 android { } 中加入 namespace "com.example.your_app",删除 Manifest 的 package,再执行 flutter clean 即可解决。如果整个项目都很旧,用 flutter create . 重新生成模板会很有效;同时也要对齐 AGP、Gradle、Kotlin 与 JDK 的版本。如果原因在插件,优先更新它,并把 namespace 注入脚本作为急救手段。养成定期更新依赖与查阅迁移指南的习惯,这个错误就不会再阻挡你的脚步。

常见问题(FAQ)

Q1. namespace 与 applicationId 有什么区别?应该设成一样吗? A. namespace 是编译时用于生成 R 类和 BuildConfig 的代码级包名;applicationId 是在 Google Play 上唯一标识应用的 ID,发布后不可更改。二者在技术上可以不同,但迁移时保持一致最为稳妥,以免混淆。

Q2. 一定要从  AndroidManifest.xml 删除 package 属性吗? A. 在 AGP 8.0+ 下,namespace 是命名空间的唯一信息来源,Manifest 的 package 会被忽略;若与 namespace 冲突还会引发警告或错误。为避免麻烦,建议删除。

Q3. 我加了 namespace 却仍然报同样的错,为什么? A. 请重新查看信息中的 project ':___'。如果它是插件名而非 :app,那么原因就在该插件,用解决方法3的注入脚本或更新插件来处理。另外,不执行 flutter clean 就重建可能残留陈旧缓存,因此务必先清理。

Q4. 把 AGP 退回 7.x 能消除错误吗? A. 会暂时消失,但最新的 Android SDK、Flutter 和各类插件都以 AGP 8.x 为前提,因此不建议降级。适配 namespace 才是正道的永久解决方案。

Q5. Kotlin DSL(build.gradle.kts)的写法一样吗? A. 概念相同但语法不同。Groovy DSL 写作 namespace "com.example.app",Kotlin DSL 则用赋值形式 namespace = "com.example.app"

Q6. namespace 里可以用哪些字符? A. 它必须是有效的  Java/Kotlin 包名:小写字母、以点分隔的段,任何段不以数字开头,也不能含连字符或保留字。请命名为诸如 com.example.your_app 的形式。

参考资料

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐