Flutter元数据管理插件metadata_god的使用
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_STORAGE
和 WRITE_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
更多关于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
提供了设置和获取元数据的方法,例如setMetaData
和getMetaData
。以下是如何使用这些方法的示例:
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. 异步处理
由于元数据管理可能涉及异步操作(例如从存储中读取或写入数据),因此setMetaData
和getMetaData
方法很可能是异步的。上面的示例代码已经展示了如何使用then
方法来处理异步结果。
注意事项
- 上述代码示例是基于假设的
MetaDataManager
类及其方法的用法。实际使用时,请查阅metadata_god
插件的官方文档以获取准确的API和使用说明。 - 确保你理解并处理任何可能的异常或错误情况,特别是在进行异步操作时。
- 如果
metadata_god
插件提供了其他功能(如监听元数据变化、批量设置元数据等),请查阅文档以充分利用这些功能。
希望这个示例能帮助你开始在Flutter项目中使用metadata_god
插件进行元数据管理!