Flutter 三方库 adaptive_image_picker 鸿蒙化适配指南
随着鸿蒙生态的快速发展,越来越多的 Flutter 开发者希望将现有应用迁移到鸿蒙平台。然而,许多依赖原生能力的三方库在鸿蒙上无法直接运行,需要经过适配改造。本文以 adaptive_image_picker 为例,详细介绍如何将该 Flutter 三方库进行鸿蒙化适配,帮助开发者少走弯路。
1. 背景与适配目标
adaptive_image_picker 是一个用于图片选择的 Flutter 插件,它通过平台通道调用原生相册能力。在 Android 和 iOS 上,该库分别依赖系统相册接口;而在鸿蒙上,需要改用鸿蒙的 PhotoViewPicker 等能力来实现同等功能。
本次适配的目标是:在不改变 Flutter 层 API 的前提下,为鸿蒙平台补齐原生实现,使现有业务代码无需改动即可运行。
2. 适配前准备
在开始适配之前,需要准备好以下环境和工具:
- DevEco Studio 5.0 及以上版本,用于创建鸿蒙原生工程。
- Flutter 鸿蒙版 SDK,建议使用支持鸿蒙的 Flutter 3.x 分支。
- 鸿蒙真机或模拟器,用于验证适配效果。
- 从 adaptive_image_picker:基于 Flutter 生态的跨平台图片选择与处理项目 - AtomGit 拉取源码。
环境搭建的详细步骤请直接参考官方文档:Flutter 鸿蒙环境搭建指南。这里不再赘述,下面重点说明从源码拉取到适配完成的完整过程。
2.1 同步上游仓库到 AtomGit
首先,将上游仓库 fork 或同步到自己的 AtomGit 账号下,方便后续管理和提交适配分支。在 AtomGit 上进入目标仓库页面,点击「Fork」按钮,将 adaptive_image_picker 仓库复制到自己的命名空间下。
如果上游仓库后续有更新,可以通过 AtomGit 的「同步上游」功能,将最新代码拉取到自己的仓库中,保持与上游一致。
2.2 将代码拉取到宿主机
在宿主机(开发电脑)上,使用 git clone 命令将 Fork 后的仓库克隆到本地:
git clone https://atomgit.com/你的用户名/adaptive_image_picker.git
cd adaptive_image_picker
克隆完成后,还需要将上游仓库添加为远程仓库,方便后续同步上游的最新代码。执行以下命令添加上游仓库:
git remote add upstream https://atomgit.com/oh-flutter/adaptive_image_picker.git
添加完成后,可以通过 git remote -v 查看远程仓库列表,确认 origin 指向自己 Fork 的仓库、upstream 指向上游仓库。后续需要同步上游更新时,执行 git fetch upstream 拉取上游代码即可。
2.3 创建分支并自动补全 ohos 适配结构
在目标仓库根目录下,先创建一个适配分支,分支命名统一采用 feat/ohos_库名称_版本号 的格式:
git checkout -b feat/ohos_adaptive_image_picker_1.0.0
接着,使用 Flutter 鸿蒙版的适配工具,自动完成 ohos 目录结构的补全。执行以下命令:
flutter create --platforms ohos .
该命令会在工程根目录下自动生成 ohos 目录,并补齐鸿蒙插件模块所需的基础文件(如 oh-package.json5、module.json5、Index.ets 等),省去手动搭建工程结构的繁琐步骤。
3. 工程结构分析
首先,我们需要了解 adaptive_image_picker 的工程结构。该插件采用标准的 Flutter 插件结构,主要包含以下部分:
adaptive_image_picker/
├── lib/ # Dart 层代码
│ └── adaptive_image_picker.dart
├── android/ # Android 原生实现
├── ios/ # iOS 原生实现
├── ohos/ # 鸿蒙原生实现(需新增)
└── pubspec.yaml
适配的核心工作,就是在工程中新增 ohos 目录,并实现与 Android/iOS 对应的平台通道逻辑。
4. 鸿蒙原生实现
接下来,我们逐步实现鸿蒙侧的原生代码。
4.1 创建鸿蒙插件模块
在工程根目录下创建 ohos 目录,并在 DevEco Studio 中新建一个 HarmonyOS 插件模块。模块名称建议与插件名保持一致,便于管理。
4.2 实现平台通道
鸿蒙侧需要注册 MethodChannel,并实现图片选择方法。核心代码如下:
import { MethodCall, MethodChannel } from '@ohos/flutter_ohos';
import { photoAccessHelper } from '@kit.MediaLibraryKit';
import { BusinessError } from '@kit.BasicServicesKit';
export class AdaptiveImagePickerPlugin {
private channel: MethodChannel;
constructor() {
this.channel = new MethodChannel('adaptive_image_picker');
this.channel.setMethodCallHandler(this.handleMethodCall.bind(this));
}
private async handleMethodCall(call: MethodCall): Promise<any> {
if (call.method === 'pickImage') {
return this.pickImage();
}
throw new Error('Unsupported method: ' + call.method);
}
private async pickImage(): Promise<string> {
try {
const picker = new photoAccessHelper.PhotoViewPicker();
const result = await picker.select({
MIMEType: photoAccessHelper.PhotoViewMIMETypes.IMAGE_TYPE,
maxSelectNumber: 1
});
if (result.photoUris.length > 0) {
return result.photoUris[0];
}
return '';
} catch (error) {
const err = error as BusinessError;
throw new Error('Image pick failed: ' + err.message);
}
}
}
4.3 注册插件
在鸿蒙模块的入口文件中注册插件实例,确保 Flutter 引擎启动时能够加载:
import { AdaptiveImagePickerPlugin } from './AdaptiveImagePickerPlugin';
export default {
onRegister(): void {
new AdaptiveImagePickerPlugin();
}
}
5. Dart 层适配
鸿蒙原生实现完成后,还需要检查 Dart 层代码是否兼容。大多数情况下,由于平台通道接口保持一致,Dart 层无需改动。但需要注意以下几点:
- 确认 MethodChannel 名称与鸿蒙侧注册的名称一致。
- 检查返回的数据类型是否与 Dart 层预期一致,例如图片路径的格式。
- 如果鸿蒙返回的 URI 与 Android 的 content URI 格式不同,需要在 Dart 层做兼容处理。
6. 使用 Demo 验证适配效果
适配完成后,我们需要通过一个 Demo 来验证功能是否正常。对于 Flutter 插件,可以直接使用仓库根目录下的 example 工程作为 Demo;如果仓库没有提供 example,则需要自行创建一个 Flutter 工程来验证。
6.1 在 Demo 中引入三方库
在 pubspec.yaml 中,通过 AtomGit 链接方式引入本地或远程的三方库依赖。推荐使用本地路径方式,直接指向我们刚才适配好的仓库目录:
dependencies:
flutter:
sdk: flutter
adaptive_image_picker:
path: ../adaptive_image_picker # 指向本地适配后的仓库
如果希望直接引用 AtomGit 远程仓库,也可以在 pubspec.yaml 中通过 git 方式引入:
dependencies:
adaptive_image_picker:
git:
url: https://atomgit.com/你的用户名/adaptive_image_picker.git
ref: feat/ohos_adaptive_image_picker_1.0.0
配置完成后,在工程根目录执行 flutter pub get 拉取依赖。
6.2 调用接口实现功能
在 Demo 的页面中,调用 AdaptiveImagePicker 提供的接口,实现图片选择功能。示例代码如下:
import 'package:flutter/material.dart';
import 'package:adaptive_image_picker/adaptive_image_picker.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('adaptive_image_picker Demo')),
body: const Center(child: PickImageButton()),
),
);
}
}
class PickImageButton extends StatelessWidget {
const PickImageButton({super.key});
@override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: () async {
final picker = AdaptiveImagePicker();
final String? imagePath = await picker.pickImage();
if (imagePath != null && imagePath.isNotEmpty) {
// ignore: use_build_context_synchronously
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('选中图片:$imagePath')),
);
}
},
child: const Text('选择图片'),
);
}
}
6.3 在鸿蒙设备上运行
连接鸿蒙真机或启动模拟器后,执行以下命令构建并运行应用:
flutter run -d <设备ID>
应用启动后,点击「选择图片」按钮,系统会弹出鸿蒙相册选择器。选中一张图片后,页面会显示所选图片的 URI 路径,说明平台通道调用成功,适配生效。
7. 常见问题与解决方案
在适配过程和使用过程中,开发者可能会遇到以下常见问题:
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| 调用图片选择无响应 | 插件未正确注册 | 检查 onRegister 是否被调用,确认模块配置正确 |
| 返回路径无法访问 | URI 格式与 Dart 层预期不一致 | 在 Dart 层增加 URI 格式转换逻辑 |
| 编译报错缺少依赖 | 缺少 MediaLibraryKit 依赖 | 在 module.json5 中补充所需依赖声明 |
| 相册权限被拒绝 | 未声明相册读取权限 | 在 module.json5 中声明 ohos.permission.READ_IMAGEVIDEO |
7.1 库本身存在问题,如何在对应仓库提交 Issue
当你在适配或使用过程中发现库本身存在 Bug(例如平台通道调用异常、接口行为与文档不符、缺少鸿蒙平台支持等),建议直接到上游仓库提交 Issue,让维护者知晓并修复。具体步骤如下:
- 提交 Issue,说明问题和复现步骤
从文末 链接 进入 fluttertpc_map_launcher 鸿蒙适配仓库,打开 Issues 页面,先搜索有没有相同的问题。如果没有,点击右上角的「新建 Issue」,填写问题标题和复现信息。
报告时把 pubspec.yaml 的依赖配置贴出来,再附上 pubspec.lock 中实际解析的主包/平台接口/ohos 包版本,说明预期什么、实际报什么错,以及 Flutter 版本、设备系统、提交号和关键日志。2. Fork 项目 ,在自己的仓库中修改。如果问题能自己修,点击上游仓库右上角的 Fork。在 Fork 页面确认项目名称、自己的账号和要复制的分支,再点击 创建 Fork 项目。
Fork 完成后,把自己的仓库克隆到本地,并添加上游仓库 git clone https://atomgit.com/你的用户名/adaptive_image_picker.git cd adaptive_image_picker git checkout -b fix/ohos_pick_image_issue -
能解决,如何在对应仓库提交 PR
当开发者修复了库的问题或新增了功能,可以通过提交 Pull Request(PR)回馈社区。具体步骤如下。

-
PR 提交后,维护者会进行 Code Review,根据反馈修改代码,最终合并到主分支。
为帮助读者更好地理解和复现本文内容,补充以下资源与说明。
8. 完整示例工程
为了方便读者快速上手,这里提供一个完整的示例工程结构,涵盖鸿蒙插件模块、平台通道实现、Dart 层调用以及 Demo 验证的完整链路。你可以直接基于该结构搭建自己的适配工程。
adaptive_image_picker_ohos_demo/
├── lib/
│ └── main.dart # Demo 入口,调用图片选择接口
├── ohos/
│ ├── entry/
│ │ └── src/main/
│ │ ├── ets/
│ │ │ ├── entryability/
│ │ │ │ └── EntryAbility.ets
│ │ │ └── pages/
│ │ │ └── Index.ets # 鸿蒙侧页面,展示选择结果
│ │ └── module.json5 # 声明权限与依赖
│ └── plugin/
│ └── src/main/ets/
│ ├── AdaptiveImagePickerPlugin.ets # 平台通道实现
│ └── Index.ets # 插件注册入口
├── pubspec.yaml # 依赖声明
└── README.md # 使用说明
其中,鸿蒙插件模块的核心文件 AdaptiveImagePickerPlugin.ets 负责注册 MethodChannel 并调用 PhotoViewPicker 实现图片选择;Index.ets 在引擎启动时完成插件注册;Dart 层通过统一的 AdaptiveImagePicker 接口调用,无需关心平台差异。
9. 适配检查清单
在完成鸿蒙化适配后,建议对照以下清单逐项检查,确保适配质量与功能完整性:
| 检查项 | 说明 | 状态 |
|---|---|---|
| ohos 目录结构完整 | 包含 oh-package.json5、module.json5、Index.ets 等基础文件 | ☐ |
| 平台通道名称一致 | Dart 层与鸿蒙侧 MethodChannel 名称完全匹配 | ☐ |
| 插件已正确注册 | onRegister 被调用,模块配置无误 | ☐ |
| 权限声明完整 | module.json5 中已声明相册读取等所需权限 | ☐ |
| 返回数据格式兼容 | URI 格式与 Dart 层预期一致,或已做兼容转换 | ☐ |
| 编译无错误 | DevEco Studio 单独编译鸿蒙工程通过 | ☐ |
| 真机功能验证 | 在鸿蒙真机或模拟器上运行 Demo,图片选择功能正常 | ☐ |
| 异常处理完善 | 对用户取消、权限拒绝等场景有合理处理 | ☐ |
10. 相关链接
以下资源对鸿蒙化适配具有重要参考价值,建议收藏备用:
- 上游仓库:adaptive_image_picker 源码仓库,用于 Fork、同步与提交 PR。
- Flutter 鸿蒙环境搭建指南:官方环境搭建文档,涵盖 SDK 安装与工程配置。
- 鸿蒙开发者文档:HarmonyOS 官方文档,查阅 PhotoViewPicker、MediaLibraryKit 等 API 详情。
- Flutter 鸿蒙适配工具:通过
flutter create --platforms ohos .自动生成 ohos 目录结构,相关说明见 Flutter 鸿蒙版 SDK 文档。 - AtomGit 平台:AtomGit 官网,用于仓库托管、Fork 与 Pull Request 协作。
更多推荐


所有评论(0)