做 Flutter 开发这几年,我一直觉得跨端方案的尽头就是“能跑的地方全都跑”。所以当 OpenHarmony 开始支持 Flutter 时,我第一时间就开始折腾,这中间踩过的坑加起来比过去一年还多。这篇文章把我在 OpenHarmony 设备上接入“扫一扫”功能的完整过程记录下来,从环境搭建、功能接入到各种报错修复,希望能让后面接手的人少走几步弯路。
先交代一下背景。我这边的项目是在已有的 Flutter 业务代码上做鸿蒙适配,核心需求是在 OpenHarmony 设备上调用相机实现二维码扫描。听起来不复杂,但实际做下来发现,这个需求牵扯到 Flutter 引擎编译、鸿蒙原生插件、相机权限、UI 线程调度好几个层面,每个环节都可能埋雷。整篇文章按照“环境准备 — 依赖接入 — 核心实现 — 踩坑复盘 — 性能调优”的顺序展开,适合手里已经有一些 Flutter 基础、正要往 OpenHarmony 上迁移的人参考。
1. 项目整体思路与方案选型
1.1 为什么选择 Flutter 做 OpenHarmony 端的扫一扫
先说说方案选型。OpenHarmony 的官方应用开发推荐的是 ArkTS 和 ArkUI,但团队里大部分人只会 Dart,如果为了扫一扫功能单独维护一套 ArkTS 原生页面,成本太高。而且后续的业务迭代还要继续跨端,不可能每加一个功能就在鸿蒙侧写一套原生实现。所以最终决定沿用 Flutter 作为 UI 层和业务层框架,OpenHarmony 只负责提供平台能力和相机硬件接口。
这个思路的关键在于:把 Flutter 当成 UI 引擎,把 OpenHarmony 当成底层操作系统来适配。Flutter 本身具备完整的三端能力抽象,比如 MethodChannel、EventChannel 之类的平台通道设计,天然适合来做这种桥接。扫一扫的核心是相机采集和图像识别,这两块完全可以丢给原生层,Flutter 层只负责调用和展示结果。
还有一点,OpenHarmony 社区的 Flutter 适配项目(flutter_flutter)已经持续维护了一段时间,对 API 的支持度比想象中好。至少在我做的这个版本上,基础渲染、事件分发、平台通道都能跑通,只是细节上还需要额外适配。
1.2 扫一扫功能的技术栈拆解
扫一扫这个功能,从技术上看可以拆成四个模块:
- 相机采集模块:负责打开相机、设置预览分辨率、回调帧数据。
- 图像处理模块:对采集到的图像做灰度化、裁剪、旋转等预处理。
- 码识别模块:识别二维码或条形码内容,返回字符串和码类型。
- 业务回调模块:把识别结果通过通道回传给 Flutter 层,并触发下一步业务。
在 OpenHarmony 上,相机采集一般使用 @ohos.multimedia.camera 接口,码识别可以借助 OpenHarmony 的多媒体能力,也可以直接用开源库如 ZXing 做二次开发。考虑到 OpenHarmony 的 native 接口和 Android 不同,我采用的是“系统相机采集 + ZXing 识别”的组合。系统的 CameraManager 负责拿帧,ZXing 负责对字节流做解码,这样代码的可移植性好,后续如果要在其他设备上用,也能直接搬。
架构上的分层大致是这样:
| 层级 | 职责 | 技术选型 |
|---|---|---|
| UI 层 | 扫码界面、结果展示、交互逻辑 | Flutter / Dart |
| 桥接层 | Flutter 与 OpenHarmony 通信 | MethodChannel / EventChannel |
| 能力层 | 相机控制、权限申请、生命周期绑定 | ArkTS / OpenHarmony SDK |
| 算法层 | 二维码识别、图像预处理 | ZXing(C++ 或 Java 移植) |
1.3 选 TypeScript 桥还是自己写平台通道
OpenHarmony 的 Flutter 适配版里,官方推荐用 TypeScript 编写插件代码,然后通过 flutter 命令打包生成原生依赖。不过实际用下来,TS 插件的调试链路长,编译期报错信息也不友好。我最后选择了直接在当前工程的 entry/src/main 目录下写 ArkTS 代码,通过 MethodChannel 暴露原生方法,这样能直接利用 OpenHarmony SDK 的能力,也能在 DevEco Studio 里做原生调试,链路最短。
对比一下两种方案:
| 对比维度 | TS 插件方案 | 直接写 ArkTS |
|---|---|---|
| 集成速度 | 中间多一层转换 | 直接写,一步到位 |
| 调试体验 | 需要编译成原生代码才能断点 | 可调试 ArkTS 原生代码 |
| 代码复用 | 可在多个 Flutter 工程间复用 | 绑死在当前项目里 |
| 依赖复杂度 | 需要维护 pub 包和原生包两套配置 | 只需改当前工程 |
如果你只是“一次性接入”,比如只做一个扫码页,直接写 ArkTS 就够了。如果你要做成 SDK 给团队里多个项目用,再考虑拆成 TS 插件。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 环境准备与工程配置
2.1 工具链版本组合
OpenHarmony 的 Flutter 开发环境和标准 Flutter 开发有一个很大区别:不能直接用 flutter.dev 下载的官方 Flutter SDK,要用 OpenHarmony 社区维护的分支。我一开始没注意这点,用官方 Flutter 版本跑 flutter doctor,结果设备列表里根本看不到鸿蒙设备。
最终确定的版本组合是:
- Flutter SDK:OpenHarmony 社区版 v3.7 分支(对应 OpenHarmony 5.0)
- DevEco Studio:5.0.0 Release
- OpenHarmony SDK:API 12
- Node.js:18.x 以上(用于部分工具链)
- 命令行工具:
ohpm(OpenHarmony 包管理器)
这里要特别提醒一句:社区分支的版本号命名和官方不同,不要在 flutter --version 的结果上纠结。只要 flutter doctor 能正常识别出 OpenHarmony 设备,基本就说明环境没问题。
2.2 使用 FVM 管理多版本 Flutter
因为手头同时维护着 Android 和鸿蒙两个项目,官方 Flutter 和 OpenHarmony 分支需要切换,我一直用 FVM 来管理。FVM 的好处是可以按目录锁定 Flutter 版本,不同项目切目录就自动切版本,不用手动改 PATH。
安装和使用流程:
bash复制# 安装 fvm
dart pub global activate fvm
# 添加 OpenHarmony 分支
fvm add 3.7.0-ohos
# 在项目目录下指定版本
fvm use 3.7.0-ohos
# 查看当前版本
fvm flutter --version
注意,FVM 在首次添加 OpenHarmony 分支时,需要你本地已经有该分支的源码或者能够从合法渠道获取。建议直接去 OpenHarmony 官方代码仓库拉取,拉到本地后通过 fvm add <路径> 的方式注册,最稳妥。
2.3 解决 Gradle 与 Visual Studio 工具链报错
在环境配置阶段,我先后遇到了两个热门问题,网上问的
