Flutter 鸿蒙宿主能否迁到 API 26:先验证四条兼容链

原生 HarmonyOS SDK 发布了 API 26,Flutter 团队便收到一句需求:“把我们的多端应用也升到 26。”听起来只是改一个版本号,实际涉及 Flutter framework、engine、OpenHarmony/HarmonyOS embedder、Hvigor 插件和业务三方插件。任何一层没有支持目标平台,都可能出现构建阶段失败、HAP 能安装却白屏,或者页面可用但原生能力失效。

在这里插入图片描述

本文以跨平台应援灯牌控制应用的开发场景为例,给出迁移前的证据清单和最小验证路径。参考工程当前使用 Flutter 3.35.8-ohos-1.0.3-beta、Dart 3.9.2,ohos/build-profile.json5 为 OpenHarmony API 20。这个基线没有 API 26 构建和设备运行证据,所以下文是可行性评估方法,不是“Flutter 已成功适配 HarmonyOS 7”的经验复盘。

1. 先分清 Flutter OH 与 HarmonyOS SDK 是两条发布链

HarmonyOS API 26 是系统与开发套件版本;Flutter OH 是社区维护的 Flutter/Engine 适配。当前 CPF-Flutter 项目说明 将其描述为面向 OpenHarmony 的 Flutter SDK 与 Engine 适配版本,并列出自身的分支和标签命名。一个 SDK 的发布不等于另一条分支自动兼容,必须找到目标 Flutter 标签、对应 engine、支持的宿主 SDK 与设备版本的明确资料。

层迁移前必须得到的答案
Flutter framework用哪个确切 tag/commit,Dart 约束是否变化?
Engineframework 对应哪份 engine artifact,架构是否覆盖目标设备?
宿主/embedder目标 runtimeOS 和 API 26 由谁支持,能否启动 FlutterAbility?
构建插件Flutter Hvigor 插件支持哪套 DevEco/Hvigor?
三方插件相机、媒体、连接等插件是否有目标平台版本?

如果只能回答“有一个最新 Flutter”,不足以建立兼容性结论。版本要精确到可复现的提交、产物和目标系统。

在这里插入图片描述

2. 从工程读出当前可验证的事实

打开项目根目录,用下面几条只读命令先记录环境和配置。示例命令需要读者在自己的工程里执行;不要把本文电脑上的 SDK 目录照搬到 CI。

flutter --version
flutter doctor -v
Get-Content .\pubspec.yaml | Select-String 'sdk:|flutter:'
Get-Content .\ohos\build-profile.json5 |
  Select-String 'runtimeOS|compileSdkVersion|targetSdkVersion|compatibleSdkVersion'

参考工程读取结果表明:Dart 约束为 ^3.9.2,宿主是 OpenHarmony API 20,且 ohos/package.json 引用了本机 Flutter SDK 中的 flutter-hvigor-plugin。这些是迁移前的起点。flutter doctor -v 即使显示 Flutter/OpenHarmony 环境可用,也不代表 API 26、特定三方插件和真实设备已通过;它只覆盖环境自检能观察到的部分。

3. 第一条闸门:Framework 与 Engine 必须成对

Flutter framework 与 engine 不是随意组合。项目终端会输出 framework revision 与 engine hash;若升级时只替换其中一项,就可能在 Dart snapshot、原生库或运行时协议处失败。可以将版本指纹记录到任务单:

flutter --version
git -C $env:FLUTTER_ROOT rev-parse HEAD

第二条命令仅在 FLUTTER_ROOT 指向 Git checkout 时可用,环境变量未设置就跳过并记录实际 SDK 位置。团队应按所选 Flutter OH 标签或维护者指南拿到配套 engine,不从其他 Flutter 发行版随手拷一份 libflutter.so。这是版本成对原则,不是说本文已经验证了某个 API 26 组合。

若维护者没有明确列出 API 26 兼容矩阵,第一轮应做最小空工程启动,而不是先把完整业务应用的依赖全部拉进来。空工程在目标设备上稳定启动,是继续评估插件的前置条件。

在这里插入图片描述

4. 第二条闸门:宿主的 FlutterAbility 能不能正常启动

参考工程的 EntryAbility.ets 继承 FlutterAbility,并在配置引擎时调用生成的插件注册器。这段代码揭示启动链路:系统启动 Ability,宿主准备 FlutterEngine,随后注册平台插件,最后才渲染 Dart 页面。

import { FlutterAbility, FlutterEngine } from '@ohos/flutter_ohos';
import { GeneratedPluginRegistrant } from '../plugins/GeneratedPluginRegistrant';

export default class EntryAbility extends FlutterAbility {
  configureFlutterEngine(flutterEngine: FlutterEngine) {
    super.configureFlutterEngine(flutterEngine)
    GeneratedPluginRegistrant.registerWith(flutterEngine)
  }
}

若目标 SDK 改变 Ability 生命周期或 embedder 依赖,可能出现安装成功但 Flutter 首帧不出现。排查时先看宿主启动日志,再看引擎装载和资源路径,不能把白屏直接解释为 Dart Widget 错误。对接 API 26 时,具体受影响接口与处理方式必须参照目标 Flutter OH 版本的 release notes 和官方 API 26 升级适配说明。

5. 第三条闸门:构建插件与本地路径不能拖后腿

这个工程在 ohos/hvigorfile.ts 接入 flutterHvigorPlugin,ohos/package.json 用 file: 本地依赖指向 Flutter SDK。迁移电脑或切换 fork 后,旧路径可能仍存在,却指向错误版本。仅检查目录存在不够,还要确认目录属于当前 flutter --version 所指向的同一份 SDK。

$flutter = (Get-Command flutter).Source
$spec = (Get-Content .\ohos\package.json -Raw |
  ConvertFrom-Json).dependencies.'flutter-hvigor-plugin'
$plugin = $spec.Substring(5)
Write-Output "flutter command: $flutter"
Write-Output "hvigor plugin: $plugin"
Test-Path -LiteralPath $plugin

这段检查只用于发现“命令与插件指向两套 SDK”的风险;路径一致性还需要人工核对规范化后的目录,不能只看 Test-Path True。若目标工具链已升级到 DevEco Studio 26,先查对应平台的 Hvigor 配套表,再查 Flutter OH 版本是否支持该组合,避免把构建工具报错误诊为业务插件不兼容。

6. 第四条闸门:业务插件有没有目标平台实现

应援灯牌应用如果要做照片导入、视频配乐或外设控制,常会依赖媒体、文件、连接等三方插件。Flutter 包能在 Android 正常运行,不等于它拥有 OpenHarmony/HarmonyOS 实现;即使有 ohos 实现,也不代表支持目标 API 26 和设备形态。插件清单应该按“可用、需迁移、无实现”分类。

插件名 | Dart API | 原生 OH 实现 | 所需 Kit/API | 目标设备 | 验证状态
-------|----------|---------------|--------------|----------|---------
照片导入 | 已有 | 待确认 | 待确认 | 手机/平板 | 未执行
媒体播放 | 已有 | 待确认 | 待确认 | 手机/平板 | 未执行
连接外设 | 已有 | 待确认 | 待确认 | 指定硬件 | 未执行

这里的行是业务排查示例,不是参考工程真实依赖清单。参考工程的 pubspec.yaml 目前没有这些三方插件。做迁移计划时,先从实际 pubspec.lock 和插件仓库建立清单,再逐个打开插件的目标平台实现、版本说明和 issue;只看 pub.dev 的总体支持标签不够。

7. Dart 回退实现能跑,不代表原生桥接已通

参考工程里有一个很好的边界示例:createGreetingGateway() 只在 Android 与 iOS 选择 MethodChannel/KMP,其他平台使用 Dart 本地实现。下面保留分流逻辑,省略与本文无关的内部通道标识。

GreetingGateway createGreetingGateway() {
  final usesKmp = !kIsWeb &&
      (defaultTargetPlatform == TargetPlatform.android ||
       defaultTargetPlatform == TargetPlatform.iOS);
  return usesKmp
      ? const MethodChannelGreetingGateway()
      : const LocalGreetingGateway();
}

这意味着 OpenHarmony 页面即使展示了欢迎文案,也不能据此证明 Android/iOS 的 KMP MethodChannel 在鸿蒙上工作。扩展成真正的灯牌功能时,应为每项平台能力明确“原生实现、Dart 回退、不可用提示”三态;测试不能只断言界面有文字,还要验证实际数据来源、失败提示和状态同步。

8. 最小实验应按什么顺序运行

完整应用一次性升级失败时,定位成本很高。可以按以下顺序逐层增加复杂度;每一层都留独立结果。

  1. 用目标 Flutter OH SDK 创建最小工程,仅验证目标设备启动与首帧。
  2. 加入当前工程相同的宿主结构与 FlutterAbility,确认插件注册阶段无异常。
  3. 迁入一页不依赖三方插件的 Flutter UI,验证深浅色、路由与生命周期。
  4. 一次加入一个三方插件,观察构建、权限、原生回调和异常路径。
  5. 最后迁入灯牌编辑、预览与设备连接等完整业务,再做旧/新设备矩阵。

每一步都应有 commit、工具链版本和 HAP 指纹,不要把多次实验结果混在同一目录里。若第 1 步不能跑通,不应先修改第 5 步的业务页面。

9. 构建与设备验收要分开记

CPF-Flutter 项目文档展示了 flutter build hap 一类构建入口,但不同分支可能有不同参数和 engine 要求。下面是目标分支文档明确支持时才执行的命令形式;本文没有用当前参考工程对 API 26 执行它。

flutter analyze
flutter test
flutter build hap --release

前两项验证 Dart 静态层和已有测试,第三项试图生成 HAP。生成后还需确认包名、签名、产物时间和目标设备安装结果,才能进入启动验证。当前示例工程的 Widget 测试使用一个假的 GreetingGateway,它可以证明页面调用注入接口,但并不会运行 OpenHarmony 宿主或 FlutterEngine。

阶段能得出的结论不能推出的结论
flutter analyzeDart 静态层无报告问题HAP 可生成
flutter test已有测试断言通过原生插件在设备可用
HAP 构建某配置下产物生成设备可安装、可启动
设备首帧embedder 至少完成一次启动灯牌所有业务功能通过

10. 迁移决策与资料入口

发现处理建议
Flutter OH 维护者明确支持目标 SDK/设备进入最小工程与插件验证
仅有系统 API 26 文档,无 Flutter OH 支持记录保持“待评估”,不要宣称已适配
空工程能启动,业务插件失败隔离单个插件、升级或补目标平台实现
旧设备可运行,新设备白屏查宿主生命周期、engine 装载与目标行为变更
新设备运行,旧设备拒装查最低兼容版本与包配置

参考资料:CPF-Flutter/flutter_flutter 项目说明、HarmonyOS API 26 升级适配指南。版本支持范围应以计划采用的确切 tag/commit 和官方文档为准。

Flutter 跨端迁移真正要锁定的是四条兼容链:framework/engine、宿主/embedder、构建插件、业务插件。四条链都拿到构建与设备证据,才能把“可行性”推进为“已适配”;只改 SDK 版本号远远不够。

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐