Flutter元数据管理插件metadata_god的使用

发布于 1周前 作者 songsunli 来自 Flutter

Flutter元数据管理插件metadata_god的使用

metadata_god 是一个用于从音频文件中检索和写入音频标签/元数据的Flutter插件。它支持几乎所有类型的音频文件。

支持的音频格式

文件格式 元数据格式
mp3 id3v2.4
m4a, mp4 MPEG-4音频元数据
flac Vorbis评论

安装

在终端运行以下命令:

$ flutter pub add metadata_god

要求

确保已安装 rustup

配置

Android

在Android上使用 metadata_god 需要 READ_EXTERNAL_STORAGEWRITE_EXTERNAL_STORAGE 权限。

android/app/src/main/AndroidManifest.xml 文件中添加以下行:

<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.example">
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

    <application 
        android:label="Example"
        android:name="${applicationName}"
        android:icon="@mipmap/ic_launcher"
        android:usesCleartextTraffic="true"
        android:requestLegacyExternalStorage="true"
    >
        <!-- 其余配置 -->
    </application>
</manifest>

最后,使用 permission_handler 等包请求存储权限:

// 在调用任何metadata_god方法之前检查是否已经授予存储权限
initState(){
  final hasStorageAccess = Platform.isAndroid ? await Permission.storage.isGranted : true;
  if(!hasStorageAccess){
    await Permission.storage.request();
    if(!await Permission.storage.isGranted){
      return;
    }
  }
  // ... 从这里调用所有metadata_god的方法
}

注意: 下列配置适用于显式允许的文件路径。如果您需要访问整个存储空间,则需要 MANAGE_EXTERNAL_STORAGE 权限,并请求用户在应用信息设置中启用访问整个存储空间。

其他平台

Linux、Windows 和 MacOS 不需要额外配置,在安装后即可直接使用。

使用

import 'package:flutter/material.dart';
import 'package:mime/mime.dart';
import 'package:metadata_god/metadata_god.dart';

// 初始化插件
Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await MetadataGod.initialize();
  runApp(const MyApp());
}

// 获取文件元数据
Metadata metadata = await MetadataGod.getMetadata("/path/to/audio-file");

// 设置文件元数据
await MetadataGod.writeMetadata(
  "/path/to/audio-file",
  Metadata(
    title: "Leave the Door Open",
    artist: "Bruno Mars, Anderson .Paak, Silk Sonic",
    album: "An Evening with Silk Sonic",
    genre: "R&B, Soul",
    year: 2021,
    albumArtist: "Bruno Mars, Anderson .Paak",
    trackNumber: 1,
    trackTotal: 12,
    discNumber: 1,
    discTotal: 5,
    durationMs: 248000,
    fileSize: file.lengthSync(),
    picture: Picture(
      data: File("/path/to/cover-image").readAsBytesSync(),
      mimeType: lookupMimeType("/path/to/cover-image"),
    ),
  ),
);

示例代码

以下是完整的示例代码:

import 'dart:io';

import 'package:flutter/material.dart';

import 'package:metadata_god/metadata_god.dart';
import 'package:file_picker/file_picker.dart';
import 'package:metadata_god_example/reader_data_view.dart';
import 'package:metadata_god_example/writer_view.dart';

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  MetadataGod.initialize();
  runApp(const MyActualApp());
}

class MyActualApp extends StatelessWidget {
  const MyActualApp({super.key});

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Metadata God',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyApp(),
    );
  }
}

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  [@override](/user/override)
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  Metadata? metadata;
  PlatformFile? selectedFile;

  [@override](/user/override)
  void initState() {
    super.initState();
    debugPrint("Calling: initState");
    selectedFile = PlatformFile(
      name: "test.m4a",
      path: "assets/test.m4a",
      size: 3700,
    );
    WidgetsBinding.instance.addPostFrameCallback((_) async {
      final metadata = await MetadataGod.readMetadata(
        file: "assets/test.m4a",
      );
      setState(() {
        this.metadata = metadata;
      });
      debugPrint("metadata.album: ${metadata.album}");
      debugPrint("metadata.albumArtist: ${metadata.albumArtist}");
      debugPrint("metadata.artist: ${metadata.artist}");
      debugPrint("metadata.discNumber: ${metadata.discNumber}");
      debugPrint("metadata.discTotal: ${metadata.discTotal}");
      debugPrint("metadata.durationMs: ${metadata.durationMs}");
      debugPrint("metadata.fileSize: ${metadata.fileSize}");
      debugPrint("metadata.genre: ${metadata.genre}");
      debugPrint("metadata.picture: ${metadata.picture?.mimeType}");
      debugPrint("metadata.title: ${metadata.title}");
      debugPrint("metadata.trackNumber: ${metadata.trackNumber}");
      debugPrint("metadata.trackTotal: ${metadata.trackTotal}");
      debugPrint("metadata.year: ${metadata.year}");
    });
    debugPrint("End: initState");

    WidgetsBinding.instance.addPostFrameCallback((_) async {
      final entities = await Directory("/Users/krtirtho/Music/Spotube")
          .list(recursive: true)
          .toList();

      for (final entity in entities) {
        if (entity is! File || !entity.path.endsWith(".m4a")) continue;
        final metadata = await MetadataGod.readMetadata(file: entity.path);

        debugPrint("[${entity.path}] metadata.title: ${metadata.title}");
      }
    });
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Native Packages'),
      ),
      body: SingleChildScrollView(
        child: Center(
          child: Wrap(
            alignment: WrapAlignment.center,
            runAlignment: WrapAlignment.center,
            children: [
              Padding(
                padding: const EdgeInsets.all(16.0),
                child: Column(
                  children: [
                    Text("Select a audio file: ${selectedFile?.name ?? ""}"),
                    const SizedBox(height: 16),
                    Row(
                      mainAxisSize: MainAxisSize.min,
                      children: [
                        ElevatedButton(
                          onPressed: () async {
                            final result = await FilePicker.platform.pickFiles(
                              type: FileType.custom,
                              allowCompression: false,
                              allowMultiple: false,
                              withData: false,
                              withReadStream: false,
                              allowedExtensions: [
                                "mp3",
                                "m4a",
                                "flac",
                                "wav",
                                "ogg",
                                "aac",
                                "wma",
                              ],
                            );

                            if (result == null) return;
                            final fileMetadata = await MetadataGod.readMetadata(
                                file: result.files.first.path!);

                            setState(() {
                              metadata = fileMetadata;
                              selectedFile = result.files.first;
                            });
                          },
                          child: const Text("Select"),
                        ),
                        const SizedBox(width: 16),
                        ElevatedButton.icon(
                          onPressed: selectedFile == null
                              ? null
                              : () async {
                                  final writable = await showDialog<Metadata?>(
                                    context: context,
                                    builder: (context) => WriterView(metadata: metadata),
                                  );

                                  if (writable == null) return;
                                  await MetadataGod.writeMetadata(
                                    file: selectedFile!.path!,
                                    metadata: writable,
                                  );
                                  final fileMetadata = await MetadataGod.readMetadata(
                                    file: selectedFile!.path!,
                                  );
                                  setState(() {
                                    metadata = fileMetadata;
                                  });
                                },
                          label: const Text("Edit"),
                          icon: const Icon(Icons.edit_outlined),
                        ),
                      ],
                    ),
                  ],
                ),
              ),
              if (metadata != null)
                ReaderDataView(
                  metadata: metadata!,
                ),
            ],
          ),
        ),
      ),
    );
  }
}

更多关于Flutter元数据管理插件metadata_god的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter元数据管理插件metadata_god的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,下面是一个关于如何使用Flutter元数据管理插件metadata_god的代码示例。假设你已经将这个插件添加到了你的pubspec.yaml文件中,并且已经运行了flutter pub get命令。

首先,确保你的pubspec.yaml文件中包含以下依赖项:

dependencies:
  flutter:
    sdk: flutter
  metadata_god: ^latest_version  # 替换为实际的最新版本号

然后,你可以在你的Flutter项目中按照以下步骤使用metadata_god插件。

1. 导入插件

在你的Dart文件中导入metadata_god插件:

import 'package:metadata_god/metadata_god.dart';

2. 初始化元数据管理器

假设metadata_god插件提供了一个元数据管理器类MetaDataManager,你可以这样初始化它:

void main() {
  // 初始化元数据管理器(假设有一个全局的初始化方法)
  MetaDataManager.initialize();

  runApp(MyApp());
}

3. 设置和获取元数据

假设MetaDataManager提供了设置和获取元数据的方法,例如setMetaDatagetMetaData。以下是如何使用这些方法的示例:

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Metadata Management Example'),
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              ElevatedButton(
                onPressed: () {
                  // 设置元数据
                  MetaDataManager.instance.setMetaData(
                    key: 'appName',
                    value: 'My Flutter App',
                  );

                  // 设置其他元数据
                  MetaDataManager.instance.setMetaData(
                    key: 'appVersion',
                    value: '1.0.0',
                  );

                  // 获取并显示元数据
                  MetaDataManager.instance.getMetaData('appName').then((appName) {
                    print('App Name: $appName');
                  });

                  MetaDataManager.instance.getMetaData('appVersion').then((appVersion) {
                    print('App Version: $appVersion');
                  });
                },
                child: Text('Set and Get MetaData'),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

4. 异步处理

由于元数据管理可能涉及异步操作(例如从存储中读取或写入数据),因此setMetaDatagetMetaData方法很可能是异步的。上面的示例代码已经展示了如何使用then方法来处理异步结果。

注意事项

  • 上述代码示例是基于假设的MetaDataManager类及其方法的用法。实际使用时,请查阅metadata_god插件的官方文档以获取准确的API和使用说明。
  • 确保你理解并处理任何可能的异常或错误情况,特别是在进行异步操作时。
  • 如果metadata_god插件提供了其他功能(如监听元数据变化、批量设置元数据等),请查阅文档以充分利用这些功能。

希望这个示例能帮助你开始在Flutter项目中使用metadata_god插件进行元数据管理!

回到顶部