Flutter媒体资源管理插件media_asset_utils的使用

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

Flutter媒体资源管理插件media_asset_utils的使用

媒体资源管理插件media_asset_utils

本库可以在Android和iOS上运行。

写在前面

工作繁忙,只能不定期更新,还望网友们见谅!

各平台最低要求:

  • Android 24+
  • iOS 12.0+

项目描述

  1. 图片压缩使用 Luban(鲁班)—— 图片压缩工具
    • 仿微信朋友圈压缩策略,不支持控制 quality。
  2. 视频压缩 使用硬件编码,并未使用ffmpeg
    • 根据 quality 对 width、height 进行自动缩放以及 bitrate 计算。
    • bitrate 计算公式 width * height * fps * 0.07。
  3. Native 获取视频、图片信息。
  4. 保存图片、视频到系统相册。

配置

Android

由于库依赖于 Kotlin 版本 1.7.10,请更改项目级别的 build.gradle 文件来确保项目中的最低 kotlin 版本。

AndroidManifest.xml 中添加如下权限:

API < 29

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission
    android:name="android.permission.WRITE_EXTERNAL_STORAGE"
    android:maxSdkVersion="28"
    tools:ignore="ScopedStorage" />

API >= 29

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"
android:maxSdkVersion="32"/>

API >= 33

<uses-permission android:name="android.permission.READ_MEDIA_VIDEO"/>

iOS

将以下内容添加到您的 Info.plist 文件中:

<key>NSPhotoLibraryUsageDescription</key>
<string>${PRODUCT_NAME} library Usage</string>

完整示例Demo

import 'dart:async';
import 'dart:io';
import 'dart:math';

import 'package:flutter/material.dart';
import 'package:media_asset_utils/media_asset_utils.dart';
import 'package:media_asset_utils_example/permission_utils.dart';
import 'package:path_provider/path_provider.dart';
import 'package:wechat_assets_picker/wechat_assets_picker.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  [@override](/user/override)
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  File? outputFile;
  File? file;
  int? outputFileSize;
  int? fileSize;

  [@override](/user/override)
  void initState() {
    super.initState();
  }

  Future<void> initThumbnail(BuildContext context) async {
    final bool isGranted = await GGPermissionUtil.album();
    if (isGranted) {
      final List<AssetEntity>? assets = await AssetPicker.pickAssets(
        context,
        pickerConfig: AssetPickerConfig(
          requestType: RequestType.video,
          maxAssets: 1,
        ),
      );
      if ((assets ?? []).isNotEmpty) {
        file = await assets!.first.file;
        setState(() {
          fileSize = file!.lengthSync();
        });
        Directory? directory;
        directory = await getApplicationDocumentsDirectory();
        outputFile =
            File('${directory.path}/thumbnail_${Random().nextInt(100000)}.jpg');
        return;
      } else {
        throw Exception("No files selected");
      }
    }
    throw Exception("Permission denied");
  }

  Future<void> initCompress(BuildContext context, RequestType type) async {
    final bool isGranted = await GGPermissionUtil.album();
    if (isGranted) {
      final List<AssetEntity>? assets = await AssetPicker.pickAssets(
        context,
        pickerConfig: AssetPickerConfig(
          requestType: type,
          maxAssets: 1,
        ),
      );
      if ((assets ?? []).isNotEmpty) {
        Directory? directory;

        directory = await getApplicationDocumentsDirectory();
        if (Platform.isIOS) {
          file = await assets!.first.originFile;
        } else {
          file = await assets!.first.file;
        }
        setState(() {
          fileSize = file!.lengthSync();
        });
        if (type == RequestType.video) {
          outputFile =
              File('${directory.path}/video_${Random().nextInt(100000)}.mp4');
        } else {
          Directory('${directory.path}/abdd/12233').createSync(recursive: true);
          outputFile = File('${directory.path}/abdd/12233/image_1.jpg');
        }
        return;
      } else {
        throw Exception("No files selected");
      }
    }
    throw Exception("Permission denied");
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Plugin example app'),
        ),
        body: Builder(builder: (_) {
          return Column(
            children: [
              Container(
                width: double.infinity,
                constraints: BoxConstraints(minHeight: 200),
                child: Column(
                  children: [
                    Text(
                        '当前选择: $file, 文件大小: ${fileSize != null ? (fileSize! / 1024 / 1024).toStringAsFixed(2) : 0}'),
                    Text(
                        '处理后: $outputFile, 文件大小: ${outputFileSize != null ? (outputFileSize! / 1024 / 1024).toStringAsFixed(2) : 0}'),
                  ],
                ),
              ),
              TextButton(
                onPressed: () async {
                  await initCompress(_, RequestType.video);
                  outputFile = await MediaAssetUtils.compressVideo(
                    file!,
                    saveToLibrary: true,
                    quality: VideoQuality.high,
                    thumbnailConfig: ThumbnailConfig(),
                    onVideoCompressProgress: (double progress) {
                      print(progress);
                    },
                  );
                  setState(() {
                    outputFileSize = outputFile!.lengthSync();
                  });
                },
                child: Text('Compress Video'),
              ),
              TextButton(
                onPressed: () async {
                  await initThumbnail(_);
                  outputFile = await MediaAssetUtils.getVideoThumbnail(
                    file!,
                    quality: 50,
                    saveToLibrary: true,
                    thumbnailFile: outputFile!,
                  );
                  setState(() {
                    outputFileSize = outputFile!.lengthSync();
                  });
                },
                child: Text('Get Video Thumbnail'),
              ),
              TextButton(
                onPressed: () async {
                  await initCompress(_, RequestType.video);
                  final result = await MediaAssetUtils.getVideoInfo(file!);
                  print(result.toJson());
                },
                child: Text('Get Video Info'),
              ),
              TextButton(
                onPressed: () async {
                  await initCompress(_, RequestType.image);
                  final result = await MediaAssetUtils.getImageInfo(file!);
                  print(result.toJson());
                },
                child: Text('Get Image Info'),
              ),
              TextButton(
                onPressed: () async {
                  await initCompress(_, RequestType.image);
                  print(outputFile);
                  final result = await MediaAssetUtils.compressImage(
                    file!,
                    saveToLibrary: true,
                    outputFile: outputFile,
                  );
                  print(result);
                  setState(() {
                    outputFileSize = outputFile!.lengthSync();
                  });
                },
                child: Text('Compress Image'),
              ),
              TextButton(
                onPressed: () async {
                  await initCompress(_, RequestType.image);
                  await MediaAssetUtils.saveToGallery(file!);
                },
                child: Text('Save To Media Store'),
              ),
            ],
          );
        }),
      ),
    );
  }
}

更多关于Flutter媒体资源管理插件media_asset_utils的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter媒体资源管理插件media_asset_utils的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是如何在Flutter项目中使用media_asset_utils插件来管理媒体资源的一个基本示例。这个插件可以帮助你更方便地访问和管理设备的媒体文件,比如图片和视频。

首先,确保你已经在你的pubspec.yaml文件中添加了media_asset_utils依赖项:

dependencies:
  flutter:
    sdk: flutter
  media_asset_utils: ^x.y.z  # 请替换为最新版本号

然后,运行flutter pub get来安装依赖项。

接下来,让我们编写一些代码来演示如何使用这个插件。以下是一个简单的示例,展示了如何获取设备的媒体文件列表并显示它们。

1. 导入必要的包

在你的Dart文件中,导入media_asset_utils和其他必要的包:

import 'package:flutter/material.dart';
import 'package:media_asset_utils/media_asset_utils.dart';

2. 初始化插件并获取媒体文件

在你的Flutter组件中,初始化MediaAssetUtils插件并获取媒体文件列表。

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Media Asset Utils Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MediaAssetScreen(),
    );
  }
}

class MediaAssetScreen extends StatefulWidget {
  @override
  _MediaAssetScreenState createState() => _MediaAssetScreenState();
}

class _MediaAssetScreenState extends State<MediaAssetScreen> {
  List<MediaAsset> mediaAssets = [];

  @override
  void initState() {
    super.initState();
    _getMediaAssets();
  }

  Future<void> _getMediaAssets() async {
    try {
      // 初始化插件
      final MediaAssetUtils mediaAssetUtils = MediaAssetUtils();

      // 获取图片和视频文件
      final List<MediaAsset> images = await mediaAssetUtils.getImages();
      final List<MediaAsset> videos = await mediaAssetUtils.getVideos();

      // 合并结果
      setState(() {
        mediaAssets = [...images, ...videos];
      });
    } catch (e) {
      print("Error fetching media assets: $e");
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Media Assets'),
      ),
      body: mediaAssets.isEmpty
          ? Center(child: Text('Loading media assets...'))
          : GridView.builder(
              gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                  crossAxisCount: 2,
                  crossAxisSpacing: 4.0,
                  mainAxisSpacing: 4.0),
              itemCount: mediaAssets.length,
              itemBuilder: (context, index) {
                final MediaAsset asset = mediaAssets[index];
                return GridTile(
                  child: Image.file(File(asset.path)),
                  footer: GridTileBar(
                    title: Text(asset.name),
                  ),
                );
              }),
    );
  }
}

3. 权限处理

由于访问设备的媒体文件需要特定的权限,你需要在AndroidManifest.xmlInfo.plist中声明这些权限。此外,你可能还需要在运行时请求这些权限(尤其是在Android上)。

Android

AndroidManifest.xml中添加以下权限:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

iOS

Info.plist中添加以下键:

<key>NSPhotoLibraryUsageDescription</key>
<string>We need access to your photo library to display your media assets.</string>
<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
</dict>

注意:iOS的权限请求通常是通过UIAlertController在运行时进行的,这超出了media_asset_utils插件的范围,因此你可能需要额外的代码来处理。

总结

以上代码展示了如何使用media_asset_utils插件来获取设备的媒体文件,并在Flutter应用中显示它们。请注意,实际使用时你可能需要处理更多的错误情况和权限请求。希望这个示例对你有所帮助!

回到顶部
AI 助手
你好,我是IT营的 AI 助手
您可以尝试点击下方的快捷入口开启体验!