上个月接了个需求,要把现有 React Native 应用移植到鸿蒙上。业务功能里大多数页面迁移都很顺利,唯独“Bluetooth 扫描蓝牙设备”这个模块让我折腾了将近一周。不是鸿蒙蓝牙 API 本身多难调,而是“React Native + 鸿蒙”这个组合天然存在信息差:社区里搜不到现成方案,官方文档又偏向纯 ArkTS 工程,RN 桥接层的资料少得可怜。这篇博客就是把这段经历完整复盘一遍,从环境搭建、原生模块封装、桥接调用,到权限适配、踩坑排查,把所有能复现的步骤和能绕开的坑都写清楚。想搞 React Native 鸿蒙版硬件能力开发、或者正在做蓝牙相关适配的同行,可以直接拿来参考。
1. “RN + 鸿蒙 + 蓝牙”这个组合,难点到底在哪
1.1 现状:RN 不是不能跑鸿蒙,而是生态还算不上熟
React Native 官方目前没有直接发布鸿蒙版本,这一点要先有心理预期。目前能用的方案是社区和厂商共同维护的 react-native-harmony 适配库,它通过鸿蒙的 ArkTS 运行时加载 RN 的 JS Bundle,让原本的 React 组件逻辑可以在鸿蒙设备上运行。我建议在动手之前先花半天时间把这套适配机制读透,别急着写代码,因为你后面遇到的很多问题,本质上都不是业务代码的问题,而是适配层的行为和 Android/iOS 有差异。
从我实测的版本来看,react-native-harmony 对 RN 0.72 系列的兼容性相对稳定,鸿蒙侧需要 DevEco Studio 4.0 及以上版本。这里容易踩一个认知误区:有人以为鸿蒙全面兼容 Android 的 RN 库,直接把依赖拖过来就能跑,结果编译期各种报错。实际上,react-native-harmony 有自己独立的 npm 包名和配置方式,不能简单地把它当成 Android 原封不动的移植,第三方原生模块几乎都要做二次适配。
所以对团队来说,是否选择 RN 鸿蒙版,不只是技术验证的问题,还得评估团队有没有能力维护原生侧的兼容代码。如果你只是写纯 UI 页面,RN 鸿蒙版体验还行;一旦涉及蓝牙、Wi-Fi、摄像头这类系统能力,就必须做好自己封装原生模块的心理准备。
1.2 蓝牙功能为什么不能照搬社区库
在 Android 和 iOS 上,RN 社区有很成熟的蓝牙库,比如 react-native-ble-plx、react-native-bluetooth-classic。但在鸿蒙上,这些库基本不可用,原因很简单:它们底层依赖 Android 的 BluetoothAdapter 和 iOS 的 CoreBluetooth,这些 Native 实现并没有鸿蒙版本。鸿蒙系统提供的是自己的蓝牙 API(@ohos.bluetooth),很多概念相似,但接口签名、权限模型、回调机制都不相同,没法直接映射到现有库上。
这意味着你必须自己写一层原生桥接:在鸿蒙侧用 ArkTS 调用系统蓝牙能力,把扫描结果转换成 RN 侧能消费的数据,再通过 TurboModule 或 NativeEventEmitter 传给 JavaScript 层。这层桥接不复杂,但要考虑的细节很多,比如回调时序、内存释放、线程切换、权限结果回传等等,任何一个环节没处理好,出现的现象都是“扫描没反应”或“设备列表空白”。
还有一点容易被忽略:鸿蒙对应用后台使用蓝牙有比较强的限制,尤其当应用切到后台时,扫描可能被系统自动挂起。你在 RN 侧写的扫描逻辑会影响用户的真实体验。这些坑不调试到真机上根本发现不了。
1.3 我的落地策略:先打通最小链路,再补功能
面对这种“官方文档单薄、社区无现成方案”的局面,我的策略是先做垂直切片:不管 UI 和业务状态怎么设计,先把“鸿蒙原生扫描蓝牙设备 -> 数据传给 RN -> RN 渲染出设备列表”这条最小的技术链路跑通。跑通之后,再做权限、过滤、连接、异常处理这些旁支功能。
事实证明这个方法很有效。因为链路短,定位问题快,能快速验证“RN 鸿蒙版是否能满足硬件场景”这个核心问题。如果一开始就想着把完整项目迁移过来,遇到白屏或反射失败时,你很难判断问题出在桥接层还是业务层。对任何涉及到跨语言边界的功能,垂直切片都是最稳妥的启动方式。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 环境准备:搭一个既跑得动 RN、又能碰硬件的鸿蒙工程
2.1 版本选型:用哪些版本能少折腾
我整理了一份经过实际验证的版本组合,不同时期可能略有出入,但大方向可以参考:
| 组件 | 建议版本 | 说明 |
|---|---|---|
| DevEco Studio | 4.0 Release 及以上 | 鸿蒙应用 IDE,必须官方渠道下载 |
| HarmonyOS SDK | API 10 或更高 | API 10 的蓝牙接口比较稳定 |
| React Native | 0.72.x | react-native-harmony 对这个版本适配最好 |
| react-native-harmony | 跟随 RN 版本选择配套版本 | 具体以 npm 包发布页为准 |
| Node.js | 18 及以上 | 打包 RN Bundle 需要 |
选型时有两点值得注意。第一,RN 版本不是越新越好,react-native-harmony 的适配进度一般会滞后于 RN 官方版本,用太新的 RN 版本可能导致桥接不兼容。第二,DevEco Studio 和 SDK 版本要保持一致,否则编译阶段经常会碰到莫名其妙的符号找不到。
2.2 集成步骤:从空工程到 RN 页面渲染
以我用过的流程为例,核心步骤大致如下:
- 用 DevEco Studio 新建一个空白的鸿蒙工程,包名按你自己的业务域名配置。
- 在工程根目录的
oh-package.json5中声明@react-native-oh/react-native-harmony依赖,并执行ohpm install。 - 把 RN 项目打包出
