Flutter怎么在HarmonyOS鸿蒙Next中把图片保存到手机相册
Flutter怎么在HarmonyOS鸿蒙Next中把图片保存到手机相册 我做了一个定制侠的APP,用户定制完需要把效果图保存到手机相册。
但是,申请权限不给过
申请权限:ohos.permission.WRITE_IMAGEVIDEO
申请原因:因为用户上传照片设计好手机壳后,需要将效果图保存本地相册
谁有能跑起来的flutter示例代码能保存图片到相册的,不能使用ohos.permission.WRITE_IMAGEVIDEO权限,又要实现写图片到相册。
【解决方案】
image_gallery_saver是一个Flutter插件,用于将图片或者视频保存到设备相册。由于Flutter的image_picker插件只能选择图片而无法保存图片到相册,此插件提供了该功能。以下提供4种方式保存图片或者视频到设备相册。
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Save image to gallery"),
),
body: Center(
child: Column(
children: <Widget>[
SizedBox(height: 15),
// `RepaintBoundary` 的作用是将这个蓝色矩形的绘制区域隔离出来,以便在需要时可以独立处理它的绘制和重绘。`_globalKey` 则用于在代码的其他部分访问这个 `RepaintBoundary` 小部件。
RepaintBoundary(
key: _globalKey,
child: Container(
alignment: Alignment.center,
width: 300,
height: 300,
color: Colors.blue,
),
),
Container(
padding: EdgeInsets.only(top: 15),
child: ElevatedButton(
onPressed: _saveLocalImage,
child: Text("Save Local Image"),
),
width: 300,
height: 44,
),
Container(
padding: EdgeInsets.only(top: 15),
child: ElevatedButton(
onPressed: _saveNetworkImage,
child: Text("Save Network Image"),
),
width: 300,
height: 44,
),
Container(
padding: EdgeInsets.only(top: 15),
child: ElevatedButton(
onPressed: _saveNetworkGifFile,
child: Text("Save Network Gif Image"),
),
width: 300,
height: 44,
),
Container(
padding: EdgeInsets.only(top: 15),
child: ElevatedButton(
onPressed: _saveNetworkVideoFile,
child: Text("Save Network Video"),
),
width: 300,
height: 44,
),
],
),
));
}
保存本地图片到相册,参考代码如下:
GlobalKey _globalKey = GlobalKey(); // 创建一个`GlobalKey`类型的全局键对象,并将其赋值给变量 `_globalKey`
// 从指定的Widget中获取渲染对象(Render Object),然后将该Widget的内容转换成一个图像(Image)
_saveLocalImage() async {
RenderRepaintBoundary boundary =
_globalKey.currentContext!.findRenderObject() as RenderRepaintBoundary;
ui.Image image = await boundary.toImage();
ByteData? byteData =
await (image.toByteData(format: ui.ImageByteFormat.png));
if (byteData != null) {
final result =
await ImageGallerySaver.saveImage(byteData.buffer.asUint8List());
print(result);
Utils.toast(result.toString());
}
}
保存网络图片到相册,参考代码如下:
_saveNetworkImage() async {
var response = await Dio().get(
"https://example.jpg",
options: Options(responseType: ResponseType.bytes));
final result = await ImageGallerySaver.saveImage(
Uint8List.fromList(response.data),
quality: 60,
name: "hello");
print(result);
Utils.toast("$result");
}
保存网络gif图到相册,参考代码如下:
_saveNetworkGifFile() async {
var appDocDir = await getTemporaryDirectory();
String savePath = appDocDir.path + "/temp.gif";
String fileUrl =
"https://example.gif";
await Dio().download(fileUrl, savePath);
final result =
await ImageGallerySaver.saveFile(savePath, isReturnPathOfIOS: true);
print(result);
Utils.toast("$result");
}
保存网络video到相册,参考代码如下:
_saveNetworkVideoFile() async {
var appDocDir = await getTemporaryDirectory();
String savePath = appDocDir.path + "/temp.mp4";
String fileUrl =
"https://example.mp4";
await Dio().download(fileUrl, savePath, onReceiveProgress: (count, total) {
print((count / total * 100).toStringAsFixed(0) + "%");
});
final result = await ImageGallerySaver.saveFile(savePath);
print(result);
Utils.toast("$result");
}
更多关于Flutter怎么在HarmonyOS鸿蒙Next中把图片保存到手机相册的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
用已经适配过鸿蒙那个 image_gallery_saver 版本 https://gitcode.com/openharmony-sig/flutter_image_gallery_saver
但这个版本没有支持 gradle8 ,在安卓上可能会编译失败,如果要修复安卓的编译失败,可以按照 https://github.com/hui-z/image_gallery_saver/issues/400 这个修改源码。
实际上调用 image_gallery_saver 保存图片的代码就一行,我最近刚刚测试过保存单张照片是不需要请求权限的。

找HarmonyOS工作还需要会Flutter的哦,有需要Flutter教程的可以学学大地老师的教程,很不错,B站免费学的哦:https://www.bilibili.com/video/BV1S4411E7LY/?p=17
好的 我抽空试试你的代码方案,
用 image_gallery_saver 这个库啊,保存单张图片都不用申请权限的。
我使用了,但是没有跑通。你有flutter demo不,可以提供一个只带这个image_gallery_saver的,
在HarmonyOS鸿蒙Next中,Flutter通过image_gallery_saver插件保存图片到手机相册。首先在pubspec.yaml中添加依赖,然后使用saveImage方法将图片数据写入相册。需要确保应用已获取相册访问权限。
在HarmonyOS Next中,由于系统架构和安全策略的升级,传统的WRITE_IMAGEVIDEO权限已不再适用于直接写入相册的场景。你需要使用HarmonyOS提供的媒体库管理接口来实现图片保存,这不需要申请敏感的文件写入权限。
核心方法是使用PhotoAccessHelper(媒体库管理模块)的createAsset接口,将图片数据写入媒体库,系统会自动将其纳入相册管理。
以下是关键步骤和Flutter插件侧代码思路:
-
环境与权限:
- 确保你的Flutter项目已正确集成HarmonyOS Next的Native能力(通过FFI或Platform Channel)。
- 在
module.json5配置文件中声明媒体库只读权限即可,无需声明WRITE_IMAGEVIDEO:"requestPermissions": [ { "name": "ohos.permission.READ_IMAGEVIDEO" } ]
-
Native侧(ArkTS)核心代码示例: 你需要通过Flutter的MethodChannel调用以下HarmonyOS Native代码。
import photoAccessHelper from '@ohos.file.photoAccessHelper'; import fs from '@ohos.file.fs'; // 1. 获取媒体库管理实例 let phAccessHelper = photoAccessHelper.getPhotoAccessHelper(context); // 2. 准备要保存的图片数据(这里假设从Flutter侧接收图片的Uint8Array数据) // imageData: Uint8Array 类型,由Flutter侧传入 // fileName: 自定义文件名,如 "custom_design_20240520.jpg" // 3. 创建媒体资源选项 let createOption: photoAccessHelper.PhotoCreateOptions = { title: fileName // 保存到相册中显示的文件名 }; // 4. 执行创建(保存)操作 try { let assetUri = await phAccessHelper.createAsset(photoAccessHelper.PhotoType.IMAGE, createOption); // assetUri 示例: file://media/Photo/1/IMG_20240520_123456.jpg // 5. 打开该URI的文件描述符,并写入图片数据 let file = await fs.open(assetUri, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE); await fs.write(file.fd, imageData); await fs.close(file.fd); // 保存成功,可返回URI或成功信息给Flutter侧 console.info('Image saved successfully: ' + assetUri); } catch (err) { console.error('Failed to save image: ' + err.message); // 处理错误 } -
Flutter侧(Dart)调用示例:
import 'package:flutter/services.dart'; // 初始化MethodChannel const _channel = MethodChannel('your_channel_name'); Future<void> saveImageToGallery(Uint8List imageData, String fileName) async { try { // 调用Native侧方法,传递图片数据和文件名 final result = await _channel.invokeMethod('saveImage', { 'imageData': imageData, 'fileName': fileName, }); print('Save result: $result'); } on PlatformException catch (e) { print('Failed to save image: ${e.message}'); } }
关键点总结:
- 无需
WRITE_IMAGEVIDEO权限:通过PhotoAccessHelper的系统接口写入,符合HarmonyOS Next的安全规范。 - 数据格式:确保从Flutter传递到Native的图片数据是
Uint8Array(ArkTS)或Uint8List(Dart)格式。 - 文件命名:通过
createOption.title指定文件名,系统可能会自动添加后缀或调整名称以避免冲突。 - 异步处理:整个过程是异步的,注意在UI线程中处理好加载状态。
这种方案完全遵循HarmonyOS Next的设计规范,能稳定地将图片保存到系统相册,且能通过应用商店的权限审核。

