Flutter-->Namespace not specified.

更新Android gradle 7.5.0之后, 运行项目会出现Namespace not specified.问题, 这里出一个我的解决方案.

由于很多库都不可能及时更新适配gradle 7.5.0, 所以可以等pub get将子库拉取到本地之后, 在本地手动添加namespace属性,即可解决本文问题.

作为程序猿,那肯定不可能手动修改, 这种体力活是干不会的.

祭出本文干货dart脚本:

dart 复制代码
import 'dart:convert';
import 'dart:io';

import 'package:yaml/yaml.dart';

///
/// Email:angcyo@126.com
/// @author angcyo
/// @date 2024/10/08
///
/// 更新Gradle到7.5.0之后, 需要指定namespace属性, 不指定会报错.
/// ```
/// Namespace not specified.
/// ```
///
/// ```
/// android {
///     if (project.android.hasProperty("namespace")) {
///         namespace 'com.angcyo.xxx'
///     }
/// }
/// ```
///
/// 此脚本用于在`build.gradle`文件的`android{ ... }`中加入`namespace`属性.
///
void main() async {
  final currentPath = Directory.current.path;
  print('脚本工作路径->$currentPath');

  //读取yaml配置信息
  final localYamlFile = File("$currentPath/script.local.yaml");
  final yamlFile = File("$currentPath/script.yaml");
  final localYaml = loadYaml(
      localYamlFile.existsSync() ? localYamlFile.readAsStringSync() : "");
  final yaml = loadYaml(yamlFile.readAsStringSync());

  //---

  // 需要修改库的名字集合, 不指定全部
  // [YamlList]
  final names =
      yaml["androidCompileSdkNames"] ?? localYaml["androidCompileSdkNames"];

  //获取所有依赖的子库
  final dependenciesFile = File("$currentPath/.flutter-plugins-dependencies");
  final androidDependencies =
      jsonDecode(dependenciesFile.readAsStringSync())?["plugins"]?["android"];
  if (androidDependencies is List) {
    //{
    //    "name": "device_info_plus",
    //    "path": "/Users/angcyo/.pub-cache/hosted/pub.dev/device_info_plus-10.1.1/",
    //    "native_build": true,
    //    "dependencies": []
    // },
    int index = 0;
    for (final dependency in androidDependencies) {
      final name = dependency["name"];
      final path = dependency["path"];
      if (path != null) {
        if (names == null || names.contains(name)) {
          final namespace = getPackageFromAndroidManifest(path);
          if (namespace != null) {
            colorLog(
                "正在添加[${index + 1}/${androidDependencies.length}]->$path -> namespace:$namespace");
            appendNamespace(path, namespace);
          } else {
            colorLog("未找到[package]信息, 请检查[${getAndroidManifestPath(path)}]文件.");
          }
        }
      }
      index++;
    }
  } else {
    colorLog("未找到子模块的依赖信息, 请检查[${dependenciesFile.path}]文件.");
  }
}

/// 核心修改方法
/// 添加flutter子库android工程中`build.gradle`文件加入`namespace`
/// [flutterPath] flutter工程子库根路径
void appendNamespace(String flutterPath, String namespace) {
  final androidPath = "$flutterPath/android";
  final androidPathFile = File("$androidPath/build.gradle");
  if (androidPathFile.existsSync()) {
    final androidPathFileContent = androidPathFile.readAsStringSync();
    if (!androidPathFileContent.contains("namespace")) {
      //修改 android {
      final newContent = androidPathFileContent
          .replaceAllMapped(RegExp(r"android *{ *"), (match) {
        return 'android { \n    if (project.android.hasProperty("namespace")) namespace "$namespace" //by angcyo ${DateTime.now()}\n';
      });
      //写入文件
      androidPathFile.writeAsStringSync(newContent);
      colorLog("修改成功->$androidPathFile", 250);
    } else {
      colorLog("跳过已存在[namespace]信息 -> ${androidPathFile.path}");
    }
  }
}

/// 获取AndroidManifest.xml文件路径
String getAndroidManifestPath(String flutterPath) {
  return "$flutterPath/android/src/main/AndroidManifest.xml";
}

/// 从`AndroidManifest.xml`文件中获取`package`
String? getPackageFromAndroidManifest(String flutterPath) {
  final androidManifestFile = File(getAndroidManifestPath(flutterPath));
  if (androidManifestFile.existsSync()) {
    final content = androidManifestFile.readAsStringSync();
    final package = RegExp(r'package=\"(.*?)\"').firstMatch(content)?.group(1);
    return package;
  }
  return null;
}

void colorLog(dynamic msg, [int col = 93]) {
  print('\x1B[38;5;${col}m$msg');
}

Flutter工程的任意位置, 新建一个dart文件, 粘贴上述代码, 使用dart运行main方法即可.


群内有各(pian)种(ni)各(jin)样(qun)的大佬,等你来撩.

联系作者

点此QQ对话 该死的空格 点此快速加群

相关推荐
ALLIN17 小时前
Flutter 三种方式实现页面切换后保持原页面状态
flutter
Dabei17 小时前
Flutter 国际化
flutter
Dabei17 小时前
Flutter MQTT 通信文档
flutter
Dabei20 小时前
Flutter 中实现 TCP 通信
flutter
孤鸿玉20 小时前
ios flutter_echarts 不在当前屏幕 白屏修复
flutter
前端 贾公子1 天前
《Vuejs设计与实现》第 16 章(解析器) 上
vue.js·flutter·ios
tangweiguo030519871 天前
Flutter 数据存储的四种核心方式 · 从 SharedPreferences 到 SQLite:Flutter 数据持久化终极整理
flutter
0wioiw01 天前
Flutter基础(②④事件回调与交互处理)
flutter
肥肥呀呀呀1 天前
flutter配置Android gradle kts 8.0 的打包名称
android·flutter
吴Wu涛涛涛涛涛Tao2 天前
Flutter 实现「可拖拽评论面板 + 回复输入框 + @高亮」的完整方案
android·flutter·ios