人们眼中的天才之所以卓越非凡,并非天资超人一等而是付出了持续不断的努力。1 万小时的锤炼是任何人从平凡变成超凡的必要条件。------------ 马尔科姆·格拉德威尔
🌟 Hello,我是 Xxtaoaooo!
🌈 "代码是逻辑的诗篇,架构是思想的交响"
React Native 跨平台鸿蒙开发实战:JS 与 ArkTS/Native 的通信机制详解
在 React Native (RN) 开发中,JavaScript 运行在独立的线程中,而设备的原生能力(如相机、传感器、分布式软总线)则位于原生层。如何高效、安全地打通这两者,是跨平台开发的核心。在鸿蒙系统(HarmonyOS)中,我们通过 TurboModules 和 NativeModules 机制,实现 JS 与 ArkTS 的无缝双向通信。
一、鸿蒙原生能力调用的架构基础
鸿蒙系统提供了强大的分布式能力和丰富的硬件 API,要让 RN 应用享受到这些红利,必须通过 Bridge(桥接)或 JSI(JavaScript Interface)技术。
1.1 通信架构概览
RN 在鸿蒙上的通信机制主要分为两类:
- 异步通信 (Native Modules):基于 Bridge,适用于非高频、耗时操作(如文件读写、网络请求)。
- 同步通信 (TurboModules / JSI):基于 C++ 绑定,适用于高频、低延迟场景(如动画驱动、传感器数据)。
下图展示了 JS 侧调用鸿蒙原生 Sensor 能力的时序交互。
HarmonyOS SDK ArkTS/Native Layer TurboModule Bridge JS Thread (RN) HarmonyOS SDK ArkTS/Native Layer TurboModule Bridge JS Thread (RN) 传感器数据订阅流程 loop [传感器数据回调] 1. subscribeSensor('accelerometer') 2. Invoke Native Method 3. sensor.on(SENSOR_TYPE_ID_ACCELEROMETER) 4. Data Changed Event 5. Send Event to JS 6. DeviceEventEmitter.emit()
图 1:JS 与 ArkTS 传感器数据交互时序图
二、实现 JS 调用 ArkTS 模块
让我们通过一个具体案例------调用鸿蒙系统的弹窗(Toast)能力,来演示如何编写一个自定义的 Native Module。
2.1 ArkTS 侧实现
首先,在鸿蒙工程的 entry/src/main/ets 目录下创建一个 Native Module。我们需要继承 RNModule 并实现相关接口。
typescript
// HarmonyToastModule.ts
import { RNModule, TurboModuleContext } from '@rnoh/react-native-openharmony/ts'
import promptAction from '@ohos.promptAction'
export class HarmonyToastModule extends RNModule {
constructor(ctx: TurboModuleContext) {
super(ctx)
}
// 定义模块名称,JS 端将通过此名称调用
getName() {
return 'HarmonyToast'
}
// 暴露给 JS 的方法
show(message: string, duration: number) {
promptAction.showToast({
message: message,
duration: duration,
})
}
}
核心点评 :
ArkTS 代码直接调用了 @ohos.promptAction,这是鸿蒙原生提供的轻量级提示接口。通过继承 RNModule,我们将这个能力包装成了 RN 可识别的模块。
2.2 JS 侧封装
在 React Native 项目中,我们需要创建一个对应的 TS 接口文件,以便在业务代码中获得类型提示。
typescript
// HarmonyToast.ts
import { TurboModule, TurboModuleRegistry } from 'react-native'
export interface Spec extends TurboModule {
show(message: string, duration: number): void
}
// 获取 Native 模块,如果获取不到则返回 null
export default TurboModuleRegistry.get<Spec>('HarmonyToast')
三、实现 ArkTS 主动发送事件到 JS
除了 JS 主动调用,原生层也经常需要主动向 JS 发送消息,例如系统电量变化、分布式设备连接状态变更等。
3.1 ArkTS 发送事件
使用 RNInstance 提供的 emitDeviceEvent 方法。
typescript
// 在某个 ArkTS 服务或组件中
this.ctx.rnInstance.emitDeviceEvent('onDeviceConnected', {
deviceId: 'device_123',
deviceType: 'tablet',
})
3.2 JS 监听事件
在 RN 组件中,使用 DeviceEventEmitter 进行监听。
javascript
import { DeviceEventEmitter, useEffect } from 'react-native'
function DeviceMonitor() {
useEffect(() => {
const subscription = DeviceEventEmitter.addListener(
'onDeviceConnected',
(event) => {
console.log('新设备连接:', event.deviceId)
}
)
return () => {
subscription.remove() // 记得清理监听
}
}, [])
return null
}
四、安全性与权限处理建议
在调用原生能力时,权限管理是不可忽视的一环。
- 最小权限原则 :仅申请业务必需的权限(如
ohos.permission.CAMERA)。 - 动态申请:对于敏感权限,必须在运行时向用户请求授权。
4.1 权限申请流程
已授权
未授权
是
否
JS 发起调用
检查权限
执行原生逻辑
调用 requestPermissionsFromUser
用户同意?
返回权限拒绝错误
图 2:鸿蒙应用运行时权限申请流程
在 ArkTS 中,使用 abilityAccessCtrl 来管理权限:
typescript
import abilityAccessCtrl from '@ohos.abilityAccessCtrl'
// 检查并申请权限
async function requestCameraPermission(context: any) {
const atManager = abilityAccessCtrl.createAtManager()
const result = await atManager.requestPermissionsFromUser(context, [
'ohos.permission.CAMERA',
])
return result.authResults[0] === 0
}
🌟 嗨,我是 Xxtaoaooo!
⚙️ 【点赞】让更多同行看见深度干货
🚀 【关注】持续获取行业前沿技术与经验
🧩 【评论】分享你的实战经验或技术困惑
作为一名技术实践者,我始终相信:
每一次技术探讨都是认知升级的契机,期待在评论区与你碰撞灵感火花 🔥
欢迎加入开源鸿蒙跨平台社区: https://openharmonycrossplatform.csdn.net