从 Dart 应用访问 pubspec.yaml 属性(版本)

Posted

技术标签:

【中文标题】从 Dart 应用访问 pubspec.yaml 属性(版本)【英文标题】:Access to pubspec.yaml attributes (version) from Dart app 【发布时间】:2014-06-30 01:35:31 【问题描述】:

有什么方法可以访问该文件 Dart 应用程序中的 pubspec.yaml 文件中列出的某些属性?

特别是,在版本信息对话框中查看版本和描述属性可能非常有用,在使用控制台应用程序时,甚至是“--version”。我一直无法找到在 API 中访问的方法。我不确定 Mirrors 是否有任何合适的东西,但是如果将 Web 应用程序编译为 JS,那么我在输出 JS 中的任何地方都看不到描述。

谢谢。

编辑 功能请求:https://code.google.com/p/dart/issues/detail?id=18769

【问题讨论】:

我没有看到任何类似的东西。我建议您在 dartbug.com 提出功能请求。我觉得这是一个非常有趣的想法。 会的。谢谢,君特。 你需要把这个建议给 Flutter,而不是 Dart。 【参考方案1】:

仅用于颤振

请使用来自 Flutter 社区的新软件包 package_info_plus。

import 'package:package_info_plus/package_info_plus.dart';

PackageInfo packageInfo = await PackageInfo.fromPlatform();

String appName = packageInfo.appName;
String packageName = packageInfo.packageName;
String version = packageInfo.version;
String buildNumber = packageInfo.buildNumber;

以下解决方案已弃用。

我知道 OP 想要阅读 YAML,但对于 Flutter 开发者,你们可以使用 package_info 阅读应用程序的版本和其他信息。

这是从 Android/iOS 应用程序中获取详细信息的示例。

import 'package:package_info/package_info.dart';

PackageInfo packageInfo = await PackageInfo.fromPlatform();

String appName = packageInfo.appName;
String packageName = packageInfo.packageName;
String version = packageInfo.version;
String buildNumber = packageInfo.buildNumber;

【讨论】:

与主题完全无关 我同意你的看法。但是,我已经给出了免责声明,这是为了颤振,开发人员阅读版本和其他信息。不要误会我的意思。我确实遵循 *** 指南 :) 谢谢@***.com/users/6566310/jawand-singh您从Flutter Developer的角度给出了完美的要求答案。这个答案需要投票:) 如果您希望您的应用在 Web、androidios 上运行,请改用“Package info_plus”。 pub.dev/packages/package_info_plus. @AlexCorreia 请发表您的评论作为答案,以便对其进行投票。需要访问该文件的其他解决方案对 Web 无效。【参考方案2】:

您可以安装“dart_config”包并使用此代码解析 pubspec.yaml 文件:

import 'package:dart_config/default_server.dart';
import 'dart:async';

void main() 
  Future<Map> conf = loadConfig("../pubspec.yaml");
  conf.then((Map config) 
    print(config['name']);
    print(config['description']);
    print(config['version']);
    print(config['author']);
    print(config['homepage']);
    print(config['dependencies']);
  );

输出类似于:

test_cli
A sample command-line application
0.0.1
Robert Hartung
URL
dart_config: any

编辑

您可以使用 Yaml 包本身来做到这一点:

*注意:这不适用于 Flutter Web

import 'package:yaml/yaml.dart';
import 'dart:io'; // *** NOTE *** This will not work on Flutter Web

void main()       
    File f = new File("../pubspec.yaml");
    f.readAsString().then((String text) 
      Map yaml = loadYaml(text);
      print(yaml['name']);
      print(yaml['description']);
      print(yaml['version']);
      print(yaml['author']);
      print(yaml['homepage']);
      print(yaml['dependencies']);
    );

问候罗伯特

【讨论】:

“dart_config”解决方案应该效果很好。非常感谢罗伯特的提醒。 @Robert 有什么好的方法可以对这些解决方案中的任何一个进行单元测试吗? 但是你能在 Flutter 应用程序中使用这个方法读取 pubspec.yaml dart_config 现已过时,Dart 2 不兼容。【参考方案3】:

以上答案都不适合我,但这是 Flutter 应用的有效解决方案:

在您的 pubspec.yaml 中将“pubspec.yaml”添加到资产:

assets:
  - assets/
  - pubspec.yaml

如果您有一个小部件,您需要像这样显示应用版本:

...
Container(
  child: Text('Version: 1.0.0+1'),
),
...

用这样的 FutureBuilder 包装您的小部件:

import 'package:flutter/services.dart';
import 'package:yaml/yaml.dart';

...
        FutureBuilder(
            future: rootBundle.loadString("pubspec.yaml"),
            builder: (context, snapshot) 
              String version = "Unknown";
              if (snapshot.hasData) 
                var yaml = loadYaml(snapshot.data);
                version = yaml["version"];
              

              return Container(
                child: Text(
                  'Version: $version'
                ),
              );
            ),
...

servicesrootBundle 属性包含在构建应用程序时与应用程序一起打包的资源。

如果你想显示没有版本号的版本,你可以像这样拆分字符串:

'Version: $version.split("+")[0]'

更新:正如@wildsurfer 所述,这种方法在网络开发中存在潜在的安全风险,因为 pubspec.yaml 与浏览器共享!

【讨论】:

您的建议非常好。一种更简单的方法,无需使用 3rd 方包:) 请注意,当您在 Flutter Web 应用程序中这样做时,您的 pubspec.yml 文件将被浏览器获取。这是一个潜在的安全风险。 完美而简单的方法,效果很好,干得好【参考方案4】:

因此,假设这是针对 dart cli 应用程序,那么 @Robert 的建议将不起作用。

dart_config 不适用于 dart 2.x,并且您的 pubspec.yaml 不会与您的 cwd 相关,除非您在开发环境中

因此您需要获取相对于库可执行路径的 pubspec.yaml。

此示例使用“路径”包,但不是必需的。

这可以通过以下方式获得:

import 'package:path/path.dart'; 

String pathToYaml =  join(dirname(Platform.script.toFilePath()), '../pubspec.yaml');

您现在可以阅读 yaml:

import 'package:path/path.dart'; 
import 'package:yaml/yaml.dart';

String pathToYaml = join(dirname(Platform.script.toFilePath()), '../pubspec.yaml');

File f = new File(pathToYaml);
String yamlText =   f.readAsStringSync();
      Map yaml = loadYaml(yamlText);
      print(yaml['name']);
      print(yaml['description']);
      print(yaml['version']);
      print(yaml['author']);
      print(yaml['homepage']);
      print(yaml['dependencies']);
    );                                       

【讨论】:

【参考方案5】:

仅适用于 Flutter(WebAndroidIOS)...自 2020 年 10 月起

如果您希望您的应用在 WebAndroidIOS 上运行,请改用“Package info_plus”。

【讨论】:

【参考方案6】:

如何将自动化版本信息合并到 Dart 命令行应用程序中

要更新代码中的版本信息,而不必在运行时打包要解析的资源文件,您可以将信息硬编码到自动生成的 dart 源文件中,该文件将编译到您的二进制文件中。以下示例将版本、名称和描述信息硬编码到 meta.dart 文件中的 Map 对象“元”中。每次在开发中运行测试套件时,都会重新创建和覆盖 meta.dart 文件。为了验证源代码具有正确的版本信息,应用程序的代码会根据 pubspec.yaml 文件中的属性验证版本和其他元信息(但仅限于在开发中作为解释代码运行时)。如果与 pubspec.yaml 有差异,则会引发异常。一旦编译成二进制文件,它将跳过该检查,因为它找不到 pubspec.yaml 文件,因此二进制文件不会引发错误。即使 pubspec.yaml 文件恰好在附近并被找到,它也只会抛出异常并且不会创建“meta.dart”源文件。

1。创建一个 MetaUpdate 类并将其保存为“meta_update.dart”:

import 'dart:io';
import 'package:yaml/yaml.dart';
import 'meta.dart';

class MetaUpdate 
  String pathToYaml = "";
  String metaDartFileContents = "";
  MetaUpdate(this.pathToYaml);

  void writeMetaDartFile(String metaDartFilePath) 
    File metaDartFile = File(metaDartFilePath);

    String metaDartFileContents = """
/// DO NOT EDIT THIS FILE EXCEPT TO ENTER INITIAL VERSION AND OTHER META INFO 
/// THIS FILE IS AUTOMATICALLY OVER WRITTEN BY MetaUpdate 

Map<String, String> meta = <String, String>
  "name": "$getPubSpec('name')",
  "description":
      // ignore: lines_longer_than_80_chars
      "$getPubSpec('description')",  
  "version":"$getPubSpec('version')",
;
  """;

    metaDartFile.writeAsStringSync(metaDartFileContents);
  

  String getPubSpec(String pubSpecParam) 
    File f = File(pathToYaml);

    String yamlText = f.readAsStringSync();
    // ignore: always_specify_types
    Map yaml = loadYaml(yamlText);

    return yaml[pubSpecParam];
  

  void verifyLatestVersionFromPubSpec() 
    try 
      File f = File(pathToYaml);
      //exit if no pubspec found so no warning in production
      if (!f.existsSync()) return;
      //compare meta.dart with pubspec meta and give warning if difference
      if (meta.keys
          .where((dynamic e) => (meta[e] != getPubSpec(e)))
          .isNotEmpty) 
        throw Exception(
            """Version number and other meta attributes in code are different from pubspec.yaml.  Please check pubspec.yaml and then run test so that MetaUpdate can update meta information in code, then recompile""");
      
     on Exception 
      rethrow;
    
  



2。创建一个“meta.dart”文件:

/// DO NOT EDIT THIS FILE EXCEPT TO ENTER INITIAL VERSION AND OTHER META INFO 
/// THIS FILE IS AUTOMATICALLY OVER WRITTEN BY MetaUpdate 

Map<String, String> meta = <String, String>
  "name": "Acme Transmogrifier",
  "description":      
      "The best dart application ever.",  
  "version":"2021.09.001",
;

当您最初创建 meta.dart 文件时,请从 pubspec.yaml 复制您的特定信息。这将在以后每次运行 MetaUpdate.writeMetaDartFile() 时被覆盖,每当 pubspec.yaml 中的信息发生更改时都会更改内容。

3。在您的测试代码中实现版本更新

在你的测试代码的 Main() 的第一行添加以下内容(不是主程序的源代码,我们不希望它被编译成二进制文件),根据需要更改 meta.dart 的路径:

MetaUpdate("pubspec.yaml").writeMetaDartFile("lib/src/meta.dart");

4。在主代码中添加元检查

将其放入您的应用代码中,使其成为您的应用运行时首先执行的方法之一 - 如果 meta.dart 和 pubspec.yaml 中显示的属性之间存在差异,它将生成异常:

    MetaUpdate("pubspec.yaml").verifyLatestVersionFromPubSpec();

5。使用

确保 pubspec.yaml 中的名称、版本和描述信息包含您希望在代码中反映的最新信息。 导入“meta.dart”并在需要显示的地方插入 meta['name']、meta['version'] 等(例如,在要打印到的 --help 或 --version 消息中控制台)。 只要您在编译代码之前运行测试,元信息就会准确地反映在您的代码中。

【讨论】:

以上是关于从 Dart 应用访问 pubspec.yaml 属性(版本)的主要内容,如果未能解决你的问题,请参考以下文章

初步了解flutter pubspec.yaml

在颤振中运行我的 Pubspec.yaml 文件时出错

Flutter小记8修复几个pub cache引起的错误 Could not find ... “pubspec.yaml“ 或 Flutter SDK is not available

Flutter小记8修复几个pub cache引起的错误 Could not find ... “pubspec.yaml“ 或 Flutter SDK is not available

Flutter小记8修复几个pub cache引起的错误 Could not find ... “pubspec.yaml“ 或 Flutter SDK is not available

Flutter开发 Flutter 包和插件 ( Flutter 包和插件简介 | 创建 Flutter 插件 | 创建 Dart 包 )