Files
conti-docs/POC/Flutter-OH-POC.md
T
Guangfei.Zhao 2704ba5445 refactor: update README and project structure for native integration and OHOS support
- Enhanced README to clarify native integration methods for Android/iOS and OHOS.
- Updated project structure documentation to reflect changes in native capabilities and dependencies.
- Revised native integration documentation to specify transport methods for Android/iOS and OHOS.
- Documented the current implementation strategy for OHOS, emphasizing the use of MethodChannel for ArkTS.
- Adjusted SDK versioning notes to clarify the separation between Android/iOS and OHOS SDKs.
2026-09-02 23:32:16 +08:00

508 lines
37 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Flutter_OH(OpenHarmony)适配 POC 验证报告
> **文档状态:** 部分实施;OHOS 工程生成与 debug HAP 构建已通过
>
> **验证范围:** 现有 Flutter Android / iOS App 基线 → `harmony` 分支 → OpenHarmony 模拟器
>
> **结论边界:** 本轮没有真机。本文只用于判断开发、构建、业务代码复用和集成路径的可行性;不得将模拟器结果表述为鸿蒙生产可用或真机功能已验证。
## 修订历史
| 版本 | 日期 | 状态 | 说明 |
| --- | --- | --- |
| 0.1 | 2026-09-02 | POC 方案已冻结 | 定义范围、验收矩阵、证据要求及决策规则,实施后持续回写实际结果 |
| 0.2 | 2026-09-02 | 部分通过 | 记录 Flutter_OH 3.41.10-ohos-1.0.0 / Dart 3.11.5 的依赖解析和 `main_dev.dart` debug HAP 构建通过;确定首期 ArkTS 采用宿主 `entry` MethodChannel 路径 |
## 0. 结论摘要(实施后填写)
### 0.1 本 POC 回答的问题
本 POC 不回答抽象的“Flutter 能不能做鸿蒙”,而基于 Continental Retail APP 已可运行的 Android / iOS Flutter 基线,回答以下可交付的问题:
1. 能否用 Flutter_OH 在 OpenHarmony 模拟器上完成工程生成、构建、安装、启动和调试?
2. 当前 Dart 业务层、Flutter UI、状态管理、网络、路由和 H5 容器能复用多少;哪些部分必须做 OHOS 专项适配?
3. Dart 公共 API → App 宿主 `entry` → ArkTS 的原生能力链路是否可实现;当前 `native_*` facade 是否适合接入 OHOS?
4. 嵌入 H5 的 WebView / JSBridge 容器能否按现有协议工作?
5. 是否值得进入真机验证与正式鸿蒙适配阶段;需要投入什么改造和持续维护成本?
### 0.2 最终结论卡(实施后填写)
| 项目 | 结果 |
| --- | --- |
| 推荐级别 | `部分通过;尚不足以给出 Conditional Go` |
| 使用的 Flutter_OH 版本 | Flutter `3.41.10-ohos-1.0.0`;Dart `3.11.5` |
| App 基线 | `harmony_3.41.9` 分支;本轮使用 `lib/main_dev.dart` |
| 模拟器基线 | 待记录 DevEco Studio、SDK、设备镜像/API、系统 Build |
| 已证明的能力 | OHOS 工程存在;依赖解析完成;debug HAP 可由 Flutter_OH + hvigor 构建输出 |
| 未证明的能力 | 模拟器运行/热重载、Dart/ArkTS 桥接、真机相机与实体扫码、相册/文件、权限、定位、推送、性能、签名发布、真实 F6 页面 |
| 下一阶段 Gate | 先完成宿主 MethodChannel 探针与模拟器运行,再至少一台目标真机上的原生能力、真实 H5/F6、稳定性与发布验证 |
**结论规则:** 本轮 HAP 构建通过仅证明工具链和 Dart 编译链路可用,不能推导出 App 已可运行或原生能力已接通。没有真机时,即使模拟器中所有计划项通过,本 POC 的最高结论也只能是 **Conditional Go**。只有工具链、代表性业务闭环、JSBridge 和 ArkTS 原生桥接均不存在不可控阻塞时,才能建议进入真机阶段。
### 0.3 已获得的构建证据与未关闭项
在 App 仓库根目录执行 `. .\enable-ohos.ps1`,再进入 `app` 目录执行:
```powershell
flutter build hap --debug -t lib\main_dev.dart
```
依赖解析及 hvigor 构建成功,输出 `app/ohos/entry/build/default/outputs/default/entry-default-unsigned.hap`。该产物是**未签名的 debug HAP**,不等同于已安装、已启动或可发布的完整验证。构建期间仍有 `targetSdkVersion` 未显式配置的 hvigor warning,需在后续 OHOS 工程配置中处理。
首次依赖解析曾因 Dart `3.11.5` 不满足 `^3.12.0`,以及 Flutter 固定 `meta 1.17.0` 与较新 Riverpod generator 的 analyzer 约束冲突而失败。当前 `harmony` 兼容组合为 `flutter_riverpod 3.2.1`、`riverpod_annotation 4.0.2`、`riverpod_generator 4.0.3`、`pigeon 26.3.1`;已对受影响包重新执行 Riverpod codegen 后构建通过。`native_scan` 现存 Pigeon 产物的生成版本标头仍须在后续以锁定的 Pigeon 26.3.1 重新生成或核验,这是生成物完整性检查,不代表 OHOS bridge 已完成。
## 1. 验证对象、范围与边界
### 1.1 POC 对象
- **代码基线:** 已有、可运行的 Android / iOS Flutter App 源码;实施开始前记录一个确定的 Git Commit。
- **工作分支:** 从该 Commit 创建 `harmony` 分支。POC 不直接向主干回灌鸿蒙改造。
- **运行环境:** DevEco Studio 的 OpenHarmony 模拟器;设备型号、系统镜像、API 级别和 Build 均须记录。
- **H5 验证对象:** POC 自带的可控测试页,而不是 F6 正式页面;因此验证的是 App 容器与桥接契约,不代表真实 F6 已完成联调。
- **后端数据:** 如需调用真实接口,只能使用开发/测试环境及测试账号,不使用生产数据。
### 1.2 本轮范围
1. Flutter_OH 工具链、OHOS 工程、依赖解析、编译、安装、启动、调试和热重载可行性。
2. 一个代表性业务闭环:登录/已有会话 → 首页 → 一个真实业务页面,覆盖路由、状态管理、网络、加载态、空态和错误态。
3. 现有 WebView 容器及 JSBridge:可控 H5 页完成握手、H5→App 调用、App→H5 回调、成功/失败回包、未知方法和来源校验。
4. OHOS 原生宿主桥接路径:Dart 公共 API → `native_*` 内部 MethodChannel → `app/ohos/entry` ArkTS 实现 → 成功结果与标准错误回传。
5. 当前依赖与原生能力的 OHOS 兼容矩阵、实际代码改动分类和维护成本评估。
6. Android / iOS 共享代码的回归检查,确认鸿蒙分支没有破坏既有行为。
### 1.3 明确不在本轮结论内
| 能力 | 本轮处理方式 | 原因与后续 Gate |
| --- | --- | --- |
| 相机实拍、二维码/条码实体扫码、车牌/VIN 识别 | 仅验证编译、注册、调用及错误语义 | 模拟器不能替代真实镜头、权限和硬件 SDK;必须真机验证 |
| 相册、文件选择、真实文件上传、运行时权限 | 可记录模拟器观察,但不关闭验收 | 与真实设备系统服务、路径和权限行为有关 |
| 定位、蓝牙、推送、后台任务、埋点/崩溃 SDK | 登记兼容性与实现路径 | 未纳入代表性最小闭环,留待真机专项验证 |
| 真实 F6 页面、票据、账号与业务联调 | 仅验证共同的 JSBridge 契约 | 依赖外部环境、账号和排期 |
| 性能、功耗、包体、机型兼容、商店上架 | 不评估 | 需要真机、正式签名和稳定性测试 |
| 全部业务模块 | 不评估 | 本 POC 只证明一条代表性链路,不能外推为全量适配完成 |
## 2. Flutter_OH 技术现状与调研方法
### 2.1 术语与上游边界
本文中的 **Flutter_OH** 指 OpenHarmony-SIG 维护的 Flutter OpenHarmony 适配分支及其工具链,不是 Google Flutter 主线内置的平台。安装前不得把“`flutter_harmony`”作为既定的工具或包名;应以实际选定的上游仓库、Tag/Commit、安装说明和命令输出为准。
当前调研以 OpenHarmony-SIG 的 `flutter_flutter` 仓库和其环境搭建指南作为一手资料。官方资料说明该仓库是 OpenHarmony Flutter SDK 的来源,并以 `dev` / `master` 等分支说明安装与开发环境;POC 必须锁定实际使用的 Tag 或 Commit,避免“使用最新版”这种不可复现的描述。[Flutter_OH 上游 README](https://gitee.com/openharmony-sig/flutter_flutter/blob/master/README.md?force_mobile=true) · [OpenHarmony Flutter 环境搭建指南](https://gitee.com/openharmony-sig/flutter_samples/blob/master/ohos/docs/03_environment/%E9%B8%BF%E8%92%99%E7%89%88Flutter%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA%E6%8C%87%E5%AF%BC.md)
### 2.2 调研记录表(实施前先补齐)
| 维度 | 需要记录的事实 | 证据来源 |
| --- | --- | --- |
| 上游治理 | 维护组织、仓库、许可证、分支策略、发布机制 | 上游仓库 README、LICENSE、Release、治理页面 |
| 版本匹配 | App 当前 Flutter/Dart 与 Flutter_OH Tag/Commit 的对应关系和版本滞后 | `flutter --version`、Git Tag/Commit、构建日志 |
| 社区健康度 | 最近 12 个月提交、Release、Issue/PR 活跃度及关键问题响应 | 上游仓库公开记录,注明采集日期 |
| 构建链路 | Windows、DevEco Studio、OpenHarmony SDK、ohpm/hvigor、Node/Java 的实际要求 | 官方环境文档 + 本地命令输出 |
| 插件生态 | 项目实际依赖的 OHOS 状态与替代方案 | 插件官方仓库/包说明 + 本 POC 构建结果 |
| 可维护性 | 项目团队需自维护的 ArkTS、fork、版本升级和 CI 工作 | POC 改动清单、Issue、风险登记 |
### 2.3 首个硬门禁:SDK 匹配
现有工程文档把 Flutter `3.44.9` 作为未来 OHOS 的兼容窗口,但这个假设不能替代实际验证。POC 首先执行以下判断:
1. 选定 Flutter_OH 的可复现 Tag/Commit;不直接使用会变化的“最新 `dev`”。
2. 记录该 SDK 的 Flutter/Dart 版本,并与 Android/iOS 基线、`pubspec.lock`、插件约束逐项比较。
3. 用未改业务的 App 基线完成依赖解析和 OHOS 编译。
4. 若版本无法兼容,立即记录为阻塞:是需要升级/降级 Flutter、替换依赖,还是当前无可行版本;不得通过私自改动业务代码或跳过插件来宣称“原代码可复用”。
只有该门禁通过,才能进入业务和原生能力验证。
## 3. 基线、分支与环境冻结
### 3.1 分支策略
1. 在实际 App 仓库确认 Android/iOS 基线已构建和测试通过。
2. 记录基线 Commit、当前 Flutter/Dart/FVM 版本、`pubspec.lock`、Android/iOS 构建结果。
3. 由该 Commit 创建 `harmony` 分支;所有 OHOS 改动仅在该分支提交。
4. 不改变既有 Android/iOS 对外业务 API;平台差异收敛在构建配置、`native_*` 内部 transport 与 App 宿主 `ohos/entry` ArkTS 层。Feature、H5 和 Dart entrypoint 不直接调用 OHOS channel。
5. 每次关键里程碑提交均在本文附录登记 Commit、变更摘要、构建命令和结果。
### 3.2 环境锁定表(实施时填写)
| 项目 | 固定值 | 证据 |
| --- | --- | --- |
| Windows 版本 / 架构 | 待填写 | `winver` / 系统信息 |
| DevEco Studio | 待填写 | About 截图 / 版本命令 |
| OpenHarmony SDK / API | 待填写 | SDK Manager 截图 / 配置 |
| 模拟器镜像与 Build | 待填写 | Device Manager / 系统设置截图 |
| Node / Java / ohpm / hvigor | 待填写 | 版本命令输出 |
| Flutter_OH 来源、Tag、Commit | 待填写 | `git remote -v`、`git rev-parse HEAD` |
| Flutter / Dart 版本 | 待填写 | `flutter --version` |
| App 基线 Commit | 待填写 | `git rev-parse HEAD` |
| Pub 缓存、镜像与代理 | 待填写 | 环境变量与配置,脱敏后归档 |
### 3.3 证据归档规则
- 每条验证结论至少附一个可复现命令日志和一个可观察证据(截图、录屏、构建产物或测试输出)。
- 截图、录屏和日志放入 `tech-selection/assets/flutter-oh-poc/<YYYYMMDD>/`;正文只引用相对路径和简短说明。
- 日志中出现 Token、Cookie、账号、内网地址、签名或密钥时,归档前必须脱敏。
- 失败项保留完整报错、最小复现命令、尝试过的版本/方案和最终阻塞判断,不能只写“暂不支持”。
## 4. 可执行教程:从现有 App 跑到鸿蒙模拟器
本章是 POC 的操作手册。请严格按顺序执行:每一步先记录实际命令和输出,再进入下一步。遇到失败时,不要通过删除依赖、注释业务代码或改用空白 Demo 来“跑通”;先把失败作为兼容矩阵的一条证据记录下来。
### 4.1 我们如何分工
| 阶段 | 我可协助完成的工作 | 需要你在本机 / GUI 中完成的工作 | 你需要回传的最小信息 |
| --- | --- | --- | --- |
| 基线确认 | 检查 Git、Flutter、依赖、现有测试与改造差异 | 打开实际 App 源码仓库 | 仓库路径、基线分支/Commit、`flutter --version` |
| Flutter_OH 安装 | 给出命令、检查版本和环境变量、解释报错 | 下载/克隆 SDK,配置本机工具 | Flutter_OH 路径、Tag/Commit、版本输出 |
| DevEco 与模拟器 | 根据截图判断配置与设备识别问题 | 安装 DevEco Studio/SDK,在 Device Manager 创建并启动模拟器 | DevEco 版本、模拟器截图、系统/API Build |
| 项目迁移与构建 | 分析依赖、代码和构建报错,给出最小修复建议 | 在真实 App 仓库执行命令、打开/运行 OHOS 工程 | 完整命令、报错文本、相关文件片段 |
| 运行效果验证 | 制定逐页检查单,核查截图/录屏和日志 | 在模拟器中登录、点击页面、观察 Flutter UI 与调试输出 | 截图/录屏、用例编号、实际/预期差异 |
| 原生能力与 H5 | 审查 ArkTS/Flutter 接口、JSBridge 协议和错误语义 | 触发可在模拟器中操作的调用,保存日志 | 请求/响应、插件日志、模拟器表现 |
### 4.2 开始前:确认 App 基线没有问题
**目标:** 证明后续问题来自 OHOS 接入,而不是原 Android/iOS 基线本身。
在实际 Flutter App 仓库根目录执行。以下命令中的 `<...>` 是你需要替换的占位符;输出不要包含账号、Token 或内网地址。
```powershell
git status --short
git branch --show-current
git rev-parse HEAD
flutter --version
flutter doctor -v
flutter pub get
```
然后执行该仓库既有的静态检查和测试命令;若项目使用 Melos、FVM 或 CI 脚本,优先用项目已有脚本,不能自行换一套命令。记录:
- 当前分支和 Commit;必须是 Android/iOS 已可运行、可复现的基线。
- Flutter、Dart、FVM(如有)和依赖锁文件版本。
- 已通过的检查及失败项;失败项先在原平台澄清,不带入鸿蒙 POC。
**检查点 G-00:** 只有基线可复现时,才创建 `harmony` 分支。
```powershell
git switch -c harmony
git status --short
```
预期结果是当前分支为 `harmony`,工作区没有与本 POC 无关的未提交改动。将基线 Commit 和创建分支后的 Commit 写入“3.2 环境锁定表”。
### 4.3 安装 Flutter_OH:先锁版本,再配置 PATH
**目标:** 不使用模糊的“安装鸿蒙 Flutter”,而是得到一个能追溯到上游 Commit 的 SDK。
1. 阅读上游 README 和环境搭建指南,选择一个候选 Tag 或 Commit。不要直接把当前 Android/iOS Flutter 版本假定为已有对应 OHOS 版本。
2. 在 Windows 上将 Flutter_OH、实际 App 工程及其本地插件放在**同一个磁盘分区**;这是上游 Windows 环境说明中的约束。建议使用空间充足的开发盘,例如 `D:\dev\`。
3. 克隆上游后固定 Commit,再把该 SDK 的 `bin` 临时加入当前 PowerShell 会话的 PATH。示例:
```powershell
$flutterOhRoot = 'D:\dev\flutter_flutter'
git clone https://gitee.com/openharmony-sig/flutter_flutter.git $flutterOhRoot
git -C $flutterOhRoot fetch --tags
git -C $flutterOhRoot checkout <已确认的Tag或Commit>
git -C $flutterOhRoot rev-parse HEAD
$env:Path = "$flutterOhRoot\bin;$env:Path"
flutter --version
flutter doctor -v
```
4. 把 `git remote -v`、最终 Commit、`flutter --version` 和 `flutter doctor -v` 的输出归档到附录 A 的 E-01。只有这些信息完整时,才可以称为“某版本 Flutter_OH 的验证结果”。
**检查点 G-01:** `flutter --version` 必须来自 Flutter_OH 路径,且其 Flutter/Dart 版本与 App 基线及 `pubspec.lock` 的约束不存在立即冲突。若 `pub get` 已经失败,停止向后执行,先在 4.7 的故障表登记版本/依赖问题。
### 4.4 DevEco Studio 与模拟器:由你操作的 GUI 步骤
1. 安装与选定 OpenHarmony SDK 匹配的 DevEco Studio,并通过 SDK Manager 安装目标 API、模拟器镜像、ohpm/hvigor 所需组件。
2. 打开 DevEco Studio 的 Device Manager,创建一个 Phone 模拟器;启动后进入系统设置,截图记录设备型号、OpenHarmony/HarmonyOS 版本、API 级别和 Build。
3. 保持模拟器运行,在 PowerShell 中执行:
```powershell
flutter devices
```
4. 从输出中找到 OHOS 模拟器对应的 `<device-id>`。不要手工猜测设备 ID;将完整输出保存到 E-01。
**检查点 G-02:** `flutter devices` 能列出正在运行的 OHOS 模拟器。若只显示 Windows/Chrome/Android 等设备,先不要执行 `flutter run`;检查模拟器是否真的启动、DevEco SDK/环境变量是否与 Flutter_OH 匹配,再保存 `flutter doctor -v` 和 `flutter devices` 输出供排查。
### 4.5 使用既有 OHOS 工程首次运行
`app/ohos` 已在本轮生成并完成 HAP 构建,**不得重复执行** `flutter create --platforms ohos .`,也不创建新的 Dart `main` 文件。现有环境入口使用 `lib/main_dev.dart`、`lib/main_uat.dart` 和 `lib/main_prod.dart`。
只有在一个新的 `harmony` 工作树中确认 `app/ohos` 缺失、并在运行前后人工审查 Git diff 时,才允许在 `app` 目录执行一次 `flutter create --platforms ohos .`。当前工作树的后续运行与构建从仓库根目录执行:
```powershell
. .\enable-ohos.ps1
cd app
flutter pub get
flutter devices
flutter run --debug -d <device-id> -t lib\main_dev.dart
```
上游 README 公开了 `flutter create --platforms ohos <projectName>`、`flutter devices`、`flutter run --debug -d <device-id>` 和 `flutter build hap --release` 作为 OHOS 工程的创建、设备发现、调试运行和正式构建入口。本 POC 仅在 OHOS 平台目录缺失时使用一次 `--platforms ohos` 生成;任何生成操作前后都要看 Git diff,防止工具意外改写 Android/iOS 配置。[上游 Flutter_OH README](https://gitee.com/openharmony-sig/flutter_flutter/blob/master/README.md?force_mobile=true)
首次运行时你的操作是:
1. 在模拟器中观察 App 是否安装、是否出现启动页、是否白屏/闪退。
2. 在终端保留完整输出;运行中的 Flutter 工具可用 `r` 触发热重载、`R` 触发热重启、`q` 退出。
3. 截取首屏和终端成功日志;若失败,复制第一段真正的 `Error` / `Exception` 及其前后上下文,不要只发最后一行。
首次可运行后执行一次构建验证(若只需复现本轮已通过的编译证据,也可直接执行本命令):
```powershell
flutter build hap --debug -t lib\main_dev.dart
git status --short
git diff --stat
```
**检查点 G-03:** HAP 调试构建已通过;调试运行和热重载仍待执行。只有三者均成功、OHOS 生成物及必要配置可在 `harmony` 分支中解释,且 Android/iOS 文件没有出现非预期改动时,才关闭本检查点。
### 4.6 观察 Flutter 业务代码的实际运行效果
工具链启动成功后,不要马上开始大面积改插件。先用现有业务代码跑完以下最小闭环,借此区分“Flutter 共享代码可以直接复用”与“某个插件阻塞启动”。
1. 在模拟器进入登录页,或按项目已有方式恢复测试登录态。
2. 完成登录后确认首页可显示,依次检查文本、图片、列表、底部导航、路由进入/返回和加载态。
3. 打开一项依赖接口数据的真实业务页面,记录成功、空数据、网络异常或服务端异常时的表现。
4. 对一个纯 Dart/Flutter 的可见文案做极小修改,执行 `r` 热重载,截图记录修改前后;这证明 Flutter 调试循环正常,不等于全量业务已适配。
5. 对每个异常记录:页面、操作、预期、实际、终端日志、截图路径、初步归属(Dart/UI、插件、OHOS 工程、服务端)。
建议回传给我的单条问题格式如下,我可以据此继续分析并给出下一步代码改动:
```text
用例编号:B-03
当前 Commit:<harmony 分支 commit>
操作:登录后点击“库存”进入列表
预期:显示列表;网络失败时显示已有重试页
实际:页面白屏 / 正常 / 报错文案
终端完整异常:<从第一行 Error 到堆栈结束>
截图或录屏:<相对路径>
是否可复现:每次 / 偶发;复现步骤
```
### 4.7 逐个处理依赖,而不是一次性删掉所有插件
首次 `flutter pub get`、`flutter run` 或 `flutter build hap` 很可能暴露不支持 OHOS 的依赖。处理顺序固定如下:
1. 从**第一个阻塞错误**开始,记录包名、版本、错误、调用方和业务影响。
2. 查该依赖的官方仓库/包说明及 OpenHarmony 适配实现;把结论写入 5.2 的兼容矩阵。
3. 判定为“直接复用 / 小幅适配 / OHOS 专项实现 / 替换依赖 / 当前不可行”之一。
4. 对不影响启动的非核心依赖,可临时显式返回 `Unsupported` 以继续验证业务主链路;该临时降级必须在风险台账中登记,不能删除调用或伪造成功。
5. 每完成一个依赖的处理,重新执行 `flutter pub get`、`flutter build hap --debug` 和最小业务闭环,确保没有引入回归。
建议优先级如下:
| 优先级 | 依赖/能力类别 | 原因 |
| --- | --- | --- |
| P0 | Flutter SDK、状态管理、路由、网络、认证、基础存储 | 决定 App 能否启动和承载真实业务 |
| P0 | WebView / JSBridge | 该项目的核心业务链路会嵌入 F6 页面 |
| P1 | 扫码、相机、文件、权限的原生注册与桥接 | 验证可维护的 ArkTS 宿主接入路径;真实硬件留待真机 |
| P2 | 定位、蓝牙、推送、埋点、崩溃上报、弱网 | 本轮记录实现路径与风险,不阻塞代表性闭环 |
### 4.8 验证 WebView 与可控 H5 测试页
本轮不等待 F6 环境。先在 App 内加载一个由 POC 管理的测试页,验证容器与 JSBridge 的安全协议。测试页只用于调试,不能替代真实业务 H5。
1. 沿用 `core_webview` 中已有的目标白名单、来源校验、请求 ID 和回包格式;不要新建一套“POC 专用协议”。
2. 测试页依次发起 `ping` / 获取 App 信息、一个纯 Dart 回包、一个需进入原生适配层的调用,以及一个故意错误的调用。
3. 每个请求在页面上显示 `{ id, method, params }`,并显示来自 App 的成功回包或错误码;App 日志同时记录相同 `id`,以便定位跨端问题。
4. 验证未知方法、类型错误参数和非白名单来源被拒绝,且不会触发原生能力。
5. 再由 App 向 H5 回发一个事件或结果,确认 H5 可关联到原请求。
当你在模拟器中执行时,请对每条 W-01 至 W-06 用例保存一张“请求 + 回包”的截图,并附同一 `id` 的 Flutter 日志。若 WebView 本身无法编译或加载,这本身是 P0 兼容性结论,不要绕过它改为浏览器打开测试页。
### 4.9 验证 Dart → ArkTS 原生宿主桥接
模拟器不能证明相机和扫码可用,但可以验证“项目有能力把原生功能接进来”。按以下最小路径实现和验证:
1. 找到项目当前原生能力的公共 Dart API;架构上始终由 `native_*` 对外暴露,Feature 和 H5 不直接依赖通道实现。
2. 不给 `native_*` 添加 OHOS plugin 声明,也不创建 package 内 `ohos/` 目录。在 `app/ohos/entry/src/main/ets/` 增加宿主桥接注册和 ArkTS 实现;`EntryAbility.ets` 只保留生命周期、Flutter engine 与 bridge 注册。
3. 先实现不使用硬件的 `getPlatformInfo` 或 `echo` 探针:`native_*` 内部 MethodChannel 传入固定参数,ArkTS 返回平台信息/同一参数,Dart 映射为类型化结果。
4. 人为触发一个可预期失败,例如未知操作或硬件不可用;验证 Dart 最终收到标准错误,而不是裸 `PlatformException`、空值或无限等待。
5. 再接通现有 `native_scan` / `native_media` 的入口,只验证 facade 能进入 OHOS 分支、宿主 bridge 可编译,并正确报告“待真机”的硬件不可用状态。
对每一个 Dart ↔ ArkTS 方法,在本文附录或实际宿主实现目录维护一行契约:`channel 名`、`方法名`、`参数`、`返回值`、`错误码`、`Dart 调用点`、`ArkTS 实现文件`。Pigeon 不生成 ArkTS,且不得人工复刻其 `BasicMessageChannel`、自定义 codec 和生成 envelope;这张契约表是手写 MethodChannel 防止接口漂移的最低要求。
### 4.10 常见失败的处理顺序
| 现象 | 优先检查 | 不应采取的做法 |
| --- | --- | --- |
| `flutter` 仍指向官方 SDK | `Get-Command flutter`、PATH 优先级、`flutter --version` | 混用两个 SDK 后继续构建 |
| `flutter devices` 没有 OHOS 模拟器 | DevEco 中设备是否启动、SDK/环境变量、`flutter doctor -v` | 手工伪造 device-id |
| `flutter create` 或构建报版本/引擎错误 | Flutter_OH Commit、Flutter/Dart 版本、同盘约束、完整错误日志 | 强行升级/降级依赖而不记录 |
| 某个插件没有 OHOS 实现 | 兼容矩阵、插件说明、调用影响范围;区分第三方 plugin 与 App 宿主 bridge | 直接删除依赖或把业务调用注释掉 |
| 启动白屏/闪退 | 第一个异常、`EntryAbility` bridge 注册、OHOS 工程配置、最小业务入口 | 只截最后一行错误 |
| WebView 加载失败 | WebView 依赖 OHOS 支持、白名单、控制台/Flutter 日志 | 改用外部浏览器来宣称 H5 通过 |
| 相机/扫码不可用 | 是否为模拟器硬件限制、插件是否已注册、错误码 | 以 mock 成功结果替代真机测试 |
### 4.11 每日回填与协作节奏
每完成一个 Gate,在“附录 A. POC 证据索引”新增一行,并在对应验证表将状态从“待填写”改为“通过 / 部分通过 / 失败 / 待真机”。建议以以下最小包回传,我可以据此继续带着你推进:
1. 当前 `harmony` 分支 Commit 与本次执行的命令。
2. 原始终端输出或脱敏后的完整日志文件。
3. 模拟器截图/录屏,以及对应的用例编号。
4. `git diff --stat`;若改了配置或插件,再附相关文件的 diff。
5. 你对“预期 / 实际”的一句话说明。
我会据此判断是环境问题、Flutter_OH 版本问题、第三方插件问题、共享 Dart 代码问题还是必须留待真机的问题,并给出下一条最小可执行操作,而不是让你一次性排查整套鸿蒙工具链。
## 5. 实施步骤与记录模板
### 5.1 工具链与 OHOS 工程
| 步骤 | 实施动作 | 通过标准 | 实际结果 / 证据 |
| --- | --- | --- | --- |
| T-01 | 按官方资料安装 Flutter_OH 与依赖工具 | `flutter --version` 显示锁定版本;环境变量配置可复现 | 待填写 |
| T-02 | 配置 DevEco Studio、OpenHarmony SDK 和模拟器 | 模拟器可启动并被工具识别 | 待填写 |
| T-03 | 在 `harmony` 分支生成/补齐 OHOS 工程 | 工程结构完整,配置不污染 Android/iOS | 待填写 |
| T-04 | 执行依赖解析和调试构建 | 无阻塞性依赖或编译错误 | 待填写 |
| T-05 | 安装并启动 App | 首屏正常显示,无启动崩溃 | 待填写 |
| T-06 | 调试与热重载 | 可附加调试器;关键 Dart 修改生效 | 待填写 |
### 5.2 代码复用与依赖兼容矩阵
对每个实际依赖和代码层做如下分类,禁止使用笼统的“基本兼容”。
| 分类 | 定义 | 典型处理 |
| --- | --- | --- |
| 直接复用 | 不改源码或仅改构建声明即可运行 | 纯 Dart 模型、业务规则、通用 Flutter UI |
| 小幅适配 | 局部条件分支、配置或 API 替换后运行 | 平台判断、路径、主题或插件初始化 |
| OHOS 专项实现 | 需要新增 ArkTS 宿主实现或已验证的第三方 OHOS 实现 | App `ohos/entry` bridge、特定系统能力 |
| 替换依赖 | 原依赖不支持 OHOS,需使用功能等价方案 | WebView、存储、设备/媒体 SDK 等 |
| 当前不可行 | 没有可控实现路径或风险不可接受 | 记录最小复现、影响范围和 No-Go 条件 |
实施后至少填充以下矩阵:
| 层 / 能力 | 当前实现或依赖 | OHOS 分类 | 改造内容 | 证据 | 风险与责任方 |
| --- | --- | --- | --- | --- | --- |
| Dart 业务模型与 Use Case | 待填写 | 待填写 | 待填写 | 待填写 | 待填写 |
| Flutter UI、主题、路由、Riverpod | 待填写 | 待填写 | 待填写 | 待填写 | 待填写 |
| 网络、认证、错误处理、存储 | 待填写 | 待填写 | 待填写 | 待填写 | 待填写 |
| WebView / JSBridge | `core_webview` | 待填写 | 待填写 | 待填写 | 待填写 |
| 扫码、相机、媒体、文件 | `native_*` 或实际项目实现 | 待填写 | 待填写 | 待填写 | 真机 Gate |
| 权限、定位、推送、蓝牙 | 实际项目实现 | 待填写 | 待填写 | 待填写 | 真机 Gate |
| 日志、埋点、崩溃上报 | 实际项目实现 | 待填写 | 待填写 | 待填写 | 待填写 |
### 5.3 代表性业务闭环
业务闭环选用真实 App 中已经存在的页面和状态流,而不使用新的 Demo 页面伪造成功结果。建议顺序为:
`已有登录态或测试登录 → 首页 → 一项需要接口数据、路由跳转和状态管理的业务页面 → loading / data / empty / error 状态`
| 用例 | 前置条件 | 操作与预期 | 状态 | 证据 |
| --- | --- | --- | --- | --- |
| B-01 启动与会话恢复 | 已配置测试环境 | App 启动后按既有逻辑进入登录或首页 | 待填写 | 待填写 |
| B-02 登录 / 测试会话 | 测试账号或可控会话 | 鉴权成功,凭据和门店上下文按预期处理 | 待填写 | 待填写 |
| B-03 首页与路由 | 已登录 | 首页渲染,进入选定业务页并可返回 | 待填写 | 待填写 |
| B-04 业务数据成功态 | 测试接口可用 | 数据正常加载和展示 | 待填写 | 待填写 |
| B-05 空态与错误态 | 可控响应或测试数据 | 提示、重试和错误映射符合既有约定 | 待填写 | 待填写 |
### 5.4 WebView 与 JSBridge
当前架构将 Embedded H5 及 JSBridge 收敛在 `core_webview`,并由 `native_*` 暴露原生能力;POC 必须沿用该边界,不能为了临时跑通而让 H5 直接调用 ArkTS。现有设计请参见 [Embedded H5 容器与 JSBridge](../flutter-app/10-webview-h5.md) 和 [原生能力集成方式](../flutter-app/07-native-integration.md)。
POC 自带的 H5 测试页必须可显示每次请求的 `id`、`method`、参数、响应及错误码,并覆盖:
| 用例 | 预期 |
| --- | --- |
| W-01 页面加载与桥接就绪 | 白名单页面加载后可确认 App Bridge 已就绪 |
| W-02 H5 → App 合法调用 | 参数通过校验,App 调用现有能力并回传与协议一致的结果 |
| W-03 App → H5 回调 | H5 正确收到事件/结果,`id` 可关联请求与回包 |
| W-04 未知方法 / 非法参数 | 返回明确错误,不执行任何原生能力 |
| W-05 非白名单来源 | 拒绝调用并记录安全日志,不泄露内部信息 |
| W-06 原生能力不可用 | 返回标准化 `UNSUPPORTED`、`PERMISSION_DENIED` 或 `HARDWARE_UNAVAILABLE`,不静默返回空值 |
本节通过只能说明 **App 容器和桥接协议** 可行。F6 真页的页面加载、登录态、文件上传、票据和业务流程仍必须在后续联调中单独验收。
### 5.5 OHOS 原生宿主桥接与 ArkTS 验证
目标是证明项目有可维护的原生接入路径,而不是在没有真机时伪造扫码成功。
1. 在既有 `native_*` 的 Dart facade 内增加 OHOS transport,并在 App 宿主 `ohos/entry` 实现 ArkTS bridge;若基线尚未包含目标能力,可新增仅限 POC 的 `native_capability_probe`,但不能把它伪装成正式扫码实现。
2. 以一个不依赖相机硬件的探针方法验证完整通道:Dart facade 发起调用、`EntryAbility` 注册宿主 bridge、ArkTS 接收参数、返回类型化结果、Dart 映射成功与失败。
3. 以现有 `native_scan` / `native_media` 对外 API 的调用路径验证 facade 分派、宿主 bridge 编译和错误语义;没有硬件时,结果必须标为“待真机”,不得以模拟值代替扫描结果。
4. 记录手写 ArkTS MethodChannel 的 channel 名、方法名、参数/返回值、错误码和接口漂移防护方案;不要求、也不尝试为 Pigeon 生成或手写 ArkTS wire protocol。
5. 不向业务 Feature 暴露 `MethodChannel`、ArkTS 或平台判断;业务和 H5 只能依赖 `native_*` 公共 Dart API。
| 用例 | 验收标准 | 模拟器结论 |
| --- | --- | --- |
| N-01 宿主 bridge 编译与注册 | OHOS 工程可编译;启动日志证明 `EntryAbility` 已注册 bridge | 可关闭 |
| N-02 Dart → ArkTS → Dart | 参数、返回值及异常可在两端对应 | 可关闭 |
| N-03 不支持/硬件不可用错误 | 返回明确、可追踪的标准错误 | 可关闭 |
| N-04 相机与实体扫码 | 真实打开相机、完成识别、处理拒绝权限 | **必须待真机** |
| N-05 文件/相册与权限 | 真实系统服务、路径、取消与拒绝场景 | **必须待真机** |
## 6. 验收、回归与决策
### 6.1 验收状态定义
| 状态 | 使用条件 |
| --- | --- |
| 通过 | 有完整命令、日志和可观察证据,达到预期结果 |
| 部分通过 | 主链路可行,但存在明确限制、人工步骤或未关闭风险 |
| 失败 | 当前版本或实现无法达到验收标准,附最小复现和阻塞原因 |
| 待真机 | 模拟器不能代表真实设备;不记为失败,也不记为通过 |
### 6.2 Android / iOS 回归
- `harmony` 分支的共享 Dart 改动必须继续通过现有静态检查、单元测试、Widget 测试及既有集成测试。
- 若 App 当前已有 Android/iOS CI,记录实施前和实施后的流水线链接或关键输出;若尚无 CI,至少记录本地执行的等价命令与结果。
- 新增 OHOS 条件分支必须覆盖 Android、iOS、OHOS 和未知平台的行为,尤其是不支持能力的显式异常路径。
### 6.3 最终判定
| 判定 | 条件 | 后续动作 |
| --- | --- | --- |
| Conditional Go | SDK 匹配、构建运行、代表性业务、JSBridge、Dart/ArkTS 桥接均通过或有可控适配;硬件能力保留真机 Gate | 进入真机专项验证和正式适配估算 |
| No-Go | 当前基线没有兼容 SDK,或核心业务/桥接/原生插件有不可接受阻塞且无可控替代 | 停止扩面,给出版本调整或替代技术路线建议 |
不得使用“模拟器没问题,所以鸿蒙没问题”作为结论。任何 Conditional Go 必须同时给出下列真机关闭条件:相机、实体扫码、运行时权限、文件/相册、WebView 差异、真实 F6、签名安装、性能稳定性和目标机型验证。
## 7. 成本与风险登记(实施后填写)
### 7.1 成本口径
成本不只统计首轮代码行数,按以下维度记录:
- **一次性接入成本:** OHOS 工程、构建环境、依赖替换、ArkTS 插件、测试页和 CI。
- **业务适配成本:** 共享代码调整、条件分支、UI/渲染差异、接口与存储适配。
- **原生能力成本:** 每个 `native_*` 的 OHOS 实现、权限、SDK 集成、真实设备测试。
- **长期维护成本:** Flutter_OH 跟随 Flutter 主线、插件 fork、ArkTS 接口漂移、社区 Issue 跟进、CI 和发布链路。
代码复用率只有在统计了确定基线和实际差异后才填写;必须同时给出统计范围,不能用一个无范围的百分比代替兼容矩阵。
### 7.2 风险台账
| 编号 | 风险 | 当前证据 | 影响 | 缓解措施 | 关闭条件 | 状态 |
| --- | --- | --- | --- | --- | --- | --- |
| R-OH-01 | Flutter_OH 与当前 Flutter/Dart 基线版本不匹配 | 待验证 | 高 | SDK 匹配作为首个硬门禁 | 基线编译、运行、依赖解析通过 | 待验证 |
| R-OH-02 | 社区分支发布滞后或关键问题依赖外部修复 | 待调研 | 高 | 锁定 Commit、跟踪上游、评估 fork 能力 | 有版本升级与问题响应策略 | 待验证 |
| R-OH-03 | Android/iOS plugin 或三方依赖不具备 OHOS 实现 | 待矩阵验证 | 高 | 逐项分类、优先核心插件、明确替代方案 | 核心原生能力真机通过 | 待验证 |
| R-OH-04 | ArkTS 手写 MethodChannel 产生接口漂移 | 已决定不复刻 Pigeon wire protocol | 中 | 固定 channel 契约、契约测试、`native_*` 公共 API 封装 | Dart/ArkTS 契约自动/人工校验通过 | 开放 |
| R-OH-05 | 模拟器结论与真机不一致 | 已知限制 | 高 | 所有硬件项标记待真机 | 目标真机专项验收完成 | 开放 |
| R-OH-06 | F6 WebView 在 OHOS 的内核与行为差异 | 本轮仅验证可控页 | 高 | 后续真实 F6 联调 | F6 核心流程和 JSBridge 通过 | 开放 |
## 附录 A. POC 证据索引(实施后填写)
| 编号 | 验证项 | 命令/日志 | 截图/录屏/产物 | 代码 Commit | 状态 |
| --- | --- | --- | --- | --- | --- |
| E-01 | SDK 与环境 | 待填写 | 待填写 | 待填写 | 待填写 |
| E-02 | OHOS 构建与安装 | 待填写 | 待填写 | 待填写 | 待填写 |
| E-03 | 业务闭环 | 待填写 | 待填写 | 待填写 | 待填写 |
| E-04 | WebView / JSBridge | 待填写 | 待填写 | 待填写 | 待填写 |
| E-05 | Dart / ArkTS 原生桥接 | 待填写 | 待填写 | 待填写 | 待填写 |
| E-06 | Android / iOS 回归 | 待填写 | 待填写 | 待填写 | 待填写 |
## 附录 B. 真机验收 Checklist(下一阶段)
- [ ] 目标 HarmonyOS / OpenHarmony 真机的签名安装、冷启动、升级与卸载重装。
- [ ] 相机权限:首次授权、拒绝、永久拒绝后的引导、从设置页恢复。
- [ ] 二维码/条码扫描、低光、连续扫码、取消、超时与异常恢复。
- [ ] 车牌/VIN 采集链路及网络异常时的手工降级入口。
- [ ] 相册、拍照、文件选择、取消、无权限、文件路径、压缩与上传进度。
- [ ] 定位、蓝牙、通知/推送、后台恢复及弱网场景。
- [ ] 真实 F6 登录、票据、双向 JSBridge、上传与返回栈。
- [ ] 多台目标机型上的 UI、WebView、性能、功耗、崩溃和日志脱敏。
- [ ] 发布签名、包体、合规声明及目标分发渠道的安装验证。