Flutter-->Namespace not specified.

news2024/12/23 9:15:11

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

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

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

祭出本文干货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对话 该死的空格 点此快速加群

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2198075.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Elasticsearch、Kibana学习

系列文章目录 JavaSE基础知识、数据类型学习万年历项目代码逻辑训练习题代码逻辑训练习题方法、数组学习图书管理系统项目面向对象编程:封装、继承、多态学习封装继承多态习题常用类、包装类、异常处理机制学习集合学习IO流、多线程学习仓库管理系统JavaSE项目员工…

鸿蒙--知乎评论

这里我们将采用组件化的思想进行开发 拆解组件 pages下,新建ZhiHu的文件pages下,新建components, 里面新建 HmNavBar和HmCommentItem components/HmNavBar.ets Entry Component struct HmNavBar {title: string 标题build() {Row() {// 返回键Row() {I…

数据湖数据仓库数据集市数据清理以及DataOps

一提到大数据我们就知道是海量数据,但是我们并不了解需要从哪些维度去考虑这些数据的存储。比如 数据湖、数据仓库、数据集市,以及数据自动化应用DataOps有哪些实现方式和实际应用,这篇文章将浅显的做一次介绍。 数据湖 数据湖是一种以自然…

Spring Boot 学习之路 -- Thymeleaf 模板引擎

前言 最近因为业务需要,被拉去研究后端的项目,代码框架基于 Spring Boot,后端对我来说完全小白,需要重新学习研究…出于个人习惯,会以 Blog 文章的方式做一些记录,文章内容基本来源于「 Spring Boot 从入门…

Python爬虫之正则表达式于xpath的使用教学及案例

正则表达式 常用的匹配模式 \d # 匹配任意一个数字 \D # 匹配任意一个非数字 \w # 匹配任意一个单词字符(数字、字母、下划线) \W # 匹配任意一个非单词字符 . # 匹配任意一个字符(除了换行符) [a-z] # 匹配任意一个小写字母 […

获取淘宝直播间弹幕数据的技术探索实践方法

在数字时代,直播已成为电商营销的重要渠道之一,而弹幕作为直播互动的核心元素,蕴含着丰富的用户行为和情感数据。本文将详细介绍如何获取淘宝直播间弹幕数据的技术方法和步骤,同时分析不同工具和方法的优缺点,并提供实…

夜莺监控的机器支持挂载到多个业务组了

夜莺开源项目于国庆前夕发布了 v7.4.1 版本,修复了一些 bug,同时也带来了一些新功能。其中最重要的一个功能是:机器支持挂载到多个业务组了。本文将介绍几个重要的变更。 所有变更点 feat: 左侧栏业务组新设计feat: 机器支持了绑定到多个业…

GAN(Generative Adversarial Nets)

GAN(Generative Adversarial Nets) 引言 GAN由Ian J. Goodfellow等人提出,是Ian J. Goodfellow的代表作之一,他还出版了大家耳熟能详的花书(Deep Learning深度学习),GAN主要的思想是同时训练两个模型,生成…

CentOS 7 安装并部署 Mysql

安装 Mysql 下载并添加库 sudo yum localinstall https://dev.mysql.com/get/mysql57-community-release-el7-11.noarch.rpm安装 Mysql 包(一路键入y即可) yum -y install mysql mysql-server --nogpgcheck- -nogpgcheck 作用为 禁掉GPG验证检查 配…

Serilog文档翻译系列(七) - 应用设置、调试和诊断、开发接收器

01应用设置 Serilog 支持在 App.config 和 Web.config 文件中使用简单的 配置语法,以设置最低日志级别、为事件添加额外属性以及控制日志输出。 Serilog 主要通过代码进行配置,设置支持旨在作为补充功能。虽然不是全面的,但大多数日志记录配…

SpringBoot3实战:实现接口签名验证

有时候我们要把自己的服务暴露给第三方去调用,为了防止接口不被授权访问,我们一般采用接口签名的方式去保护接口。 接下来松哥和大家聊一聊这个话题。 一 场景分析 什么时候需要接口签名? 接口签名是一种重要的安全机制,用于确…

Jmeter链接数据库、分布式

目录 一、Jmeter链接数据库 连接准备 有两种添加驱动的方法 第一种: 第二种: 连接方法: 1.先添加一个配置元件中的jdbc connection configuration 2、配置内容 使用: 二、Jmeter做分布式操作 1、准备多台电脑 2、多台电…

顶象生僻字点选模型识别

注意,本文只提供学习的思路,严禁违反法律以及破坏信息系统等行为,本文只提供思路 如有侵犯,请联系作者下架 该文章模型已经上线ocr识别网站,欢迎测试!!,地址:http://yxlocr.nat300.top/ocr/textclick/5 某网站使用顶象的生僻字点选模型,部分数据集如下: 这种数据集…

【Vue3 + TS + Vite】从0到1搭建后台管理系统

前言 没搭建过Vue3的项目,从0开始搭建一下,记录一下自己的步骤。 技术栈: vue3 ts scss pinia vite 我尽量写的详细一些,后续也会记录我在项目过程中,遇到的一些问题。 文章目录 前言环境搭建一、创建项目1. 使用…

使用IOT-Tree Server制作一个边缘计算设备(Arm Linux)

最近实现了一个小项目,现场有多个不同厂家的设备,用户需要对此进行简单的整合,并实现一些联动控制。 我使用了IOT-Tree Server这个软件轻松实现了,不外乎有如下过程: 1)使用Modbus协议对接现有设备&#…

探索循环神经网络RNN:解锁序列数据的奥秘

在这个数据驱动的时代,机器学习模型已经深入到我们生活的方方面面,从智能推荐系统到自然语言处理,无一不彰显其强大的能力。在众多模型中,循环神经网络(Recurrent Neural Network, RNN)以其独特的结构和对序…

Java日志(总结)

一、logback日志 Logback是由log4j创始人设计的又一个开源日记组件。logback当前分成三个模块:logback-core,logback- classic和logback-access。logback-core是其它两个模块的基础模块。logback-classic是log4j的一个 改良版本。此外logback-classic完整实现SLF4J …

elasticsearch创建索引

1对比关系型数据库,创建索引就等同于创建数据库 在postman中,向ES服务器发PUT请求 显示已经创建成功了 http://192.168.1.108:9200/shopping 请求方式get http://192.168.1.108:9200/shopping 请求全部的index的url地址 get 请求 http://192.168.1.10…

OpenHarmony(鸿蒙南向开发)——轻量系统内核(LiteOS-M)【扩展组件】

往期知识点记录: 鸿蒙(HarmonyOS)应用层开发(北向)知识点汇总 鸿蒙(OpenHarmony)南向开发保姆级知识点汇总~ 持续更新中…… C支持 基本概念 C作为目前使用最广泛的编程语言之一,…

同样的颜色在iOS和Flutter中显示不一样?色域差异解析

同样的颜色在iOS和Flutter中显示不一样?色域差异解析 在移动应用开发中,颜色的一致性对于提供良好的用户体验至关重要。然而,开发者有时会遇到一个令人困惑的问题:为什么同样的颜色代码在iOS的xib和Flutter的Container中显示的效…