摘要

在鸿蒙(OpenHarmony)Flutter 3.27-ohos 生态下,saver_gallery 是常用的保存图片/视频到系统相册插件。上游 5.x 已内置 ohos/ 实现,但 SDK 约束面向 Flutter 3.44+。本文记录在 Flutter 3.27.5-ohos-1.0.3 上,将 saver_gallery ^5.1.0 跑通编译并完成 Demo 验证的过程,涵盖环境、依赖对齐、构建与接入方式。

开源仓库(计划)https://gitcode.com/xiaoyangming/flutter_saver_gallery_ohos


一、为什么要做这件事?

image_picker 等插件解决的是从相册选图/选视频;业务里还常见反向需求:把截图、下载的图片或视频写回系统相册saver_gallery 正是补齐这一环。

能力 说明
saveImage 将图片字节(PNG/JPG/GIF 等)保存到相册
saveFile 将本地文件(视频、图片等)保存到相册
saveImages / saveFiles 批量保存
SaveResult 返回 savedUri / savedUris 等保存结果
clearCache 清理插件临时缓存目录

典型场景:分享海报截图、保存网络图片、缓存视频后入库相册。

鸿蒙 Flutter 使用 ohos 平台实现。上游从 4.0.0 起已包含 ohos/ 原生层,但 pub 上 5.x 声明 Flutter >=3.44.0、Dart >=3.12.0,无法直接在 3.27-ohos 工具链(Dart 3.6.2)上使用。本文目标是在 3.27.5-ohos-1.0.3 上完成 SDK 约束对齐、example 依赖修复与 HAP 编译验证。


二、环境与参考

2.1 开发环境

版本 / 说明
Flutter 3.27.5-ohos-1.0.3
Dart 3.6.2
命令 flutter(本地若用 FVM,将下文 flutter 改为 fvm flutter 即可)
IDE DevEco Studio(鸿蒙签名、真机调试)

验证 Flutter 版本:

flutter --version

终端  输出截图

2.2 参考与发布仓库

仓库 作用
fluttercandies/saver_gallery 上游仓库(含 ohos/ 实现)
xiaoyangming/flutter_saver_gallery_ohos 本文适配成果对外发布(计划)
pub.dev/saver_gallery 上游 Dart API(5.1.0)
openharmony-sig/flutter_image_gallery_saver 同类旧 API 插件,可作对比参考

三、适配思路(3.27-ohos)

  1. 浅克隆上游仓库(git clone --depth 1)作为基线,保留已有 SaverGalleryPlugin.ets
  2. pubspec.yaml 中 SDK 约束从上游的 >=3.44.0 放宽至 >=3.0.0 <4.0.0,以匹配 3.27-ohos。
  3. 修复 example 中与 Dart 3.6.2 冲突的 dependency_overrides(见下文第四节)。
  4. 清除 example build-profile.json5 中无效的他人签名路径,避免 Hvigor 编译失败。
  5. 执行 pub getanalyzebuild hap 完成编译级验证;真机保存能力需在 DevEco 签名后进一步验证。

工程关键目录:

flutter_saver_gallery_ohos/
├── lib/                 # Dart API(包名仍为 saver_gallery)
├── ohos/                # 鸿蒙 HAR、SaverGalleryPlugin 原生实现
├── example/
│   ├── lib/main.dart    # 保存截图 / 网络图 / 视频 / GIF 演示
│   └── ohos/            # 示例 App,在此配置签名
└── pubspec.yaml

3.1 鸿蒙原生实现要点

OHOS 侧通过 photoAccessHelper.showAssetsCreationDialog 弹出系统授权对话框,用户确认后将沙箱文件复制到媒体库目标 URI。这意味着:

  • example 通常只需声明 ohos.permission.INTERNET(网络下载示例)。
  • 无需module.json5 中声明 READ_IMAGEVIDEO 等读相册权限。
  • 保存时用户会在系统弹窗中确认,体验与 Android 13+ 的 MediaStore 授权类似。

MethodChannel 名称与上游一致:com.fluttercandies/saver_gallery


四、适配过程中的关键修改

4.1 SDK 约束放宽

插件 pubspec.yaml

environment:
  sdk: '>=3.0.0 <4.0.0'
  flutter: ">=3.0.0"

上游 5.1.0 原声明 Flutter >=3.44.0、Dart >=3.12.0;本适配在不改 Dart API 语义的前提下放宽约束,以通过 3.27-ohos 的 pub getanalyze

4.2 Example 依赖对齐

example 需额外接入鸿蒙生态下的 git 源插件(path_providerpermission_handlerdevice_info_plus 等)。适配过程中移除以下与 Dart 3.6.2 冲突的 override:

移除项 原因
path_provider_android: ^2.3.1 依赖 jni_flutter,要求 Flutter ≥3.35
win32: ^5.15.0 依赖 ffi ^2.1.4,要求 Dart ≥3.7

同时将 diodependency_overrides 改为正式依赖(example 下载网络图片/视频时使用)。


五、接入项目

5.1 添加依赖

在业务工程 pubspec.yaml 中:

dependencies:
  saver_gallery:
    git:
      url: https://gitcode.com/xiaoyangming/flutter_saver_gallery_ohos.git
      ref: v5.1.0-ohos-3.27

说明:Git 仓库名计划为 flutter_saver_gallery_ohos,Dart package 名仍是 saver_gallery,无需改 import。

flutter pub get

5.2 权限说明(OHOS)

保存到相册走系统弹窗授权,不需要提前申请读相册权限。

5.3 代码示例

import 'dart:typed_data';
import 'package:saver_gallery/saver_gallery.dart';

// 保存图片字节
final result = await SaverGallery.saveImage(
  imageBytes,
  fileName: 'screenshot.jpg',
  quality: 80,
  skipIfExists: false,
);
print(result.isSuccess ? result.savedUri : result.errorMessage);

// 保存本地视频文件
final fileResult = await SaverGallery.saveFile(
  filePath: '/data/storage/.../video.mp4',
  fileName: 'downloaded_video.mp4',
  skipIfExists: true,
);

// 批量保存
final batchResult = await SaverGallery.saveFiles(
  files: [
    SaveFileItem(filePath: path1, fileName: 'a.gif'),
    SaveFileItem(filePath: path2, fileName: 'b.gif'),
  ],
  skipIfExists: false,
);

六、构建与签名

6.1 编译 HAP

cd example
flutter pub get
flutter build hap --debug

编译通过时,Hvigor assembleHap 任务成功;若尚未配置签名,CLI 可能提示:

请通过DevEco Studio打开ohos工程后配置调试签名
(File -> Project Structure -> Signing Configs 勾选Automatically generate signature)

在这里插入图片描述

此时 assembleHap 编译已通过,仅需在 DevEco 配置签名后即可产出可安装的 HAP。

在这里插入图片描述

6.2 DevEco 签名目录

签名请在 example 的鸿蒙工程 配置:

example/ohos/

步骤:File → Project Structure → Signing Configs → Automatically generate signature

在这里插入图片描述

七、真机功能验证(Demo)

仓库 example 提供以下按钮,建议真机按序测试并截图:

步骤 操作 对应 API
1 Save Local Image saveImage(RepaintBoundary 截图)
2 Save Network Image saveImage + 网络下载
3 Save Network Video saveFile + 临时目录
4 Save Gif to Album saveImage(GIF 字节)
5 Save Two Gifs 并行两次 saveImage

每次保存时,系统应弹出媒体库创建授权对话框;用户确认后,可在系统相册中看到新文件。

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

3.27-ohos 已验证项(编译级)

  • flutter pub get / analyze 无 error
  • flutter build hap --debug → Hvigor assembleHap 成功
  • 真机保存:待 DevEco 签名后补截图(阶段 3)

八、与上游 / 其他平台的差异说明

对比项 上游 pub 5.1.0 本文(3.27-ohos)
Flutter SDK >=3.44.0 3.27.5-ohos-1.0.3
Dart SDK >=3.12.0 >=3.0.0 <4.0.0(Dart 3.6.2)
包版本 5.1.0 对齐 5.1.0
ohos 原生层 上游自带 沿用上游 SaverGalleryPlugin.ets

鸿蒙 API 支持情况(编译与代码审查,节选):

API / 组件 ohos 3.27
SaverGallery.saveImage
SaverGallery.saveFile
SaverGallery.saveImages / saveFiles
SaveResult.savedUri / savedUris
SaverGallery.clearCache
albumPath / relativePath ⚠️ OHOS 原生层当前未处理,保存到默认相册;Android/iOS 支持子目录

九、常见问题

Q1:build hap 提示 Invalid storeFile / 签名路径不存在?
检查 example/ohos/build-profile.json5 是否含有他人机器的绝对路径;清空 signingConfigs 后在 DevEco 重新配置自动签名。

Q2:pub getpath_provider_androidwin32 版本冲突?
勿在 3.27-ohos 工程中使用要求 Flutter 3.35+ / Dart 3.7+ 的 override;OHOS 构建依赖 path_provider_ohos git 源即可。

Q3:保存时没有反应?
确认已弹出系统授权对话框且用户点击允许;若 CLI 仅编译通过但未签名,需先在 DevEco 签名后再安装真机 HAP。

Q4:albumPath 在鸿蒙上不生效?
当前 OHOS 实现未映射 albumPath,文件会保存到系统默认相册位置;若业务强依赖自定义相册目录,需在 SaverGalleryPlugin.ets 中后续补齐。

Q5:依赖报错找不到 saver_gallery
确认 git 地址为 flutter_saver_gallery_ohos,且已 flutter pub get


十、参考链接


Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐