在RK3568开发板上把Flutter跑起来的经历,比我预想的要曲折得多。原本以为Flutter for OpenHarmony已经发展了好几个版本,装好SDK就能顺畅开发,结果光是设备树选型、SDK版本匹配就折腾了两天,等真机跑起第一个Hello World时,我才意识到这个生态里值得记录的东西太多了。这篇文章以我正在做的智慧学习助手App中的快速笔记功能为主线,把Flutter for OpenHarmony从环境准备、数据库设计、交互实现到平台能力调用、真机部署优化的完整链路写出来,尤其是那些搜索引擎里不太容易找到的坑。适合准备在OpenHarmony设备上做Flutter开发、或者想把笔记类工具移植到鸿蒙生态的开发者参考。
1. 开工前的关键决策:设备选择、SDK版本与工程初始化
1.1 RK3568设备树怎么选:同样是3568,开发板之间差异很大
先说设备树。这是我在OpenHarmony上遇到的第一个大坑。RK3568是一颗很常用的芯片,很多OpenHarmony开发板都在用它,但这并不意味着同一份固件能通吃所有板子。设备树(Device Tree)本质上是描述硬件资源的配置文件,屏幕分辨率、触摸IC型号、WiFi模组、内存大小、GPIO引脚分配全在里面。同样是RK3568,A开发板用的是MIPI DSI屏幕,B开发板用的是HDMI输出,C开发板可能接了eDP屏,设备树必然不同。
我一开始图省事,直接刷了手头开发板厂商提供的基础镜像,结果启动后屏幕完全黑着,串口日志刷了一堆面板初始化失败的报错。后来才意识到,OpenHarmony在启动阶段会通过设备树去匹配显示控制器和屏幕面板的时序参数,选错了就是黑屏,而且这种黑屏不像应用崩溃有日志,非常难排查。
踩过这次坑之后,我总结了一个相对靠谱的选型流程:先确认开发板的硬件版本,看底板丝印上的版本号;再找厂商提供的device目录,通常在OpenHarmony源码的vendor/你的板子/hardware/路径下,里面有board.json或类似配置文件描述使用的设备树;最后用串口工具接上开发板,在uboot阶段按任意键进入命令行,执行fbinfo或者查看内核启动日志里的Kernel command line,能直接看到加载了哪个dtb文件。
经验是:不要凭芯片型号相同就随意替换设备树,哪怕同一个厂商不同批次的产品,也可能因为屏幕驱动IC更换而需要不同的设备树。这块折腾一次之后,建议把开发板的设备树文件单独备份一份,后面编译内核或者升级镜像时还能对比,省得重新踩坑。
1.2 Flutter SDK与OpenHarmony SDK版本匹配的硬约束
设备树解决之后,紧接着就是开发环境。Flutter for OpenHarmony有一个很特殊的地方:你不能直接下载官网最新的Flutter SDK,必须使用OpenHarmony SIG社区维护的flutter_flutter仓库分支。这个分支会落后官方主线一段时间,而配套的Dart SDK、引擎版本、和OpenHarmony SDK之间都有一套固定的对应关系。
我的建议是先把以下组件准备好:DevEco Studio(建议5.0以上版本)、配套的OpenHarmony SDK、Node.js和ohpm包管理器,以及flutter_flutter仓库对应OpenHarmony-5.0版本的分支。安装完成后,执行flutter doctor,正常情况下会识别出OpenHarmony相关的条目。如果这里报错,大概率是环境变量DEVECO_SDK_HOME没有指向DevEco Studio自带的SDK目录,需要在~/.bashrc或~/.zshrc里显式配置。
版本不匹配的典型报错有两种。一种是Dart SDK版本冲突,比如你本地有其他Flutter项目用了一个较高版本的Dart语法,切到OpenHarmony分支后编译直接失败,报错信息会指向某个Dart SDK API不存在。另一种是编译HAP时找不到ohos SDK的platform版本,类似于Android开发里的compileSdkVersion不匹配。我的处理方式是严格参照flutter_flutter仓库README里标注的版本对应表,不要自己随便升级任何一环,否则后面依赖拉取阶段会连锁报错。
另外建议把OpenHarmony SDK的API版本固定下来,不要DevEco Studio一提示升级就升级。曾经遇到过一次,DevEco Studio升级后自动更新了SDK,结果Flutter引擎适配层还是旧版本,构建出来的HAP在真机上直接安装失败。后来强制回退SDK版本才解决。
1.3 初始工程的依赖锁定:避免"版本不对导致依赖包下不下来"
版本问题的第二波冲击发生在flutter pub get阶段。OpenHarmony分支的Flutter版本往往落后官方主线好几个小版本,而很多第三方插件在最新版本里已经依赖了官方主线的新特性,直接拉最新版就会报各种奇怪的约束冲突。
最开始我在pubspec.yaml里写了sqflite: ^2.0.0,结果pub get直接失败,提示某一个传递依赖要求Flutter版本大于当前版本。这种问题在纯Android开发里很少遇到,因为官方Flutter持续在向前迭代,但在OpenHarmony分支上非常常见。
我的解决方案是两件事。第一,针对常用插件维护一个版本清单,把经过验证的版本写到pubspec.lock里锁定,不要轻易整体升级。第二,在依赖解析失败时使用dependency_overrides强制指定某个传递依赖的版本,这个手段偶尔能救急,但需要注意可能会引入运行时问题,所以每次 override 之后都要在真机上跑一遍核心流程。
还有一类"依赖包下不下来"的问题跟代码版本无关,纯粹是网络源的问题。Flutter在国内环境的依赖下载经常超时,pub get卡在某个包上不动,然后报网络异常。这个问题的处理方式很常规:在环境变量里设置PUB_HOSTED_URL和FLUTTER_STORAGE_BASE_URL指向可用的国内镜像源。我自己用的就是社区里常见的镜像配置,设置完之后`pub
