ReactNative项目OpenHarmony三方库集成实战:react-native-sensors(设备传感器)
在移动应用开发中,传感器数据获取是一项重要功能,特别是在运动健康、游戏交互、增强现实等场景中。是一个功能强大的传感器库,提供了加速度计、陀螺仪、磁力计、气压计等多种传感器的访问能力,支持 RxJS 风格的数据流处理,是获取设备传感器数据的理想选择。库名称版本信息7.2.1支持 RN 0.72 版本官方仓库鸿蒙仓库主要功能📱 加速度计 (Accelerometer)🔄 陀螺仪 (Gyroscop
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net
项目基于 RN 0.72.90 开发
📋 前言
在移动应用开发中,传感器数据获取是一项重要功能,特别是在运动健康、游戏交互、增强现实等场景中。react-native-sensors 是一个功能强大的传感器库,提供了加速度计、陀螺仪、磁力计、气压计等多种传感器的访问能力,支持 RxJS 风格的数据流处理,是获取设备传感器数据的理想选择。
🎯 库简介
基本信息
- 库名称:
react-native-sensors - 版本信息:
7.2.1支持 RN 0.72 版本 - 官方仓库: https://github.com/react-native-sensors/react-native-sensors
- 鸿蒙仓库: https://atomgit.com/openharmony-sig/rntpc_react-native-sensors
- 主要功能:
- 📱 加速度计 (Accelerometer)
- 🔄 陀螺仪 (Gyroscope)
- 🧭 磁力计 (Magnetometer)
- 🌡️ 气压计 (Barometer)
- 🧭 方向传感器 (Orientation)
- ⬇️ 重力传感器 (Gravity)
- 📱 跨平台支持(iOS、Android、HarmonyOS)
为什么需要传感器库?
| 特性 | 原生方案 | react-native-sensors |
|---|---|---|
| 跨平台一致性 | ⚠️ 需分别开发 | ✅ 统一 API |
| 数据流处理 | ⚠️ 手动实现 | ✅ RxJS 支持 |
| 传感器类型 | ⚠️ 需封装 | ✅ 开箱即用 |
| 数据过滤 | ⚠️ 手动实现 | ✅ 内置过滤 |
| HarmonyOS 支持 | ⚠️ 需适配 | ✅ 完善适配 |
核心功能
| 功能 | 说明 | HarmonyOS 支持 |
|---|---|---|
| accelerometer | 加速度计 | ✅ |
| gyroscope | 陀螺仪 | ✅ |
| magnetometer | 磁力计 | ✅ |
| barometer | 气压计 | ✅ (我的手机好像不支持) |
| orientation | 方向传感器 | ✅ |
| gravity | 重力传感器 | ✅ |
| setUpdateIntervalForType | 设置更新频率 | ✅ |
| setLogLevelForType | 设置日志级别 | ✅ |
兼容性验证
在以下环境验证通过:
- RNOH: 0.72.90; SDK: HarmonyOS-6.0.0 IDE: DevEco Studio 6.0.2; ROM: 6.0.0
📦 安装步骤
1. 安装依赖
# RN 0.72 版本
npm install @react-native-ohos/react-native-sensors@7.2.2-rc.2
# 或者使用 yarn
yarn add @react-native-ohos/react-native-sensors
2. 验证安装
安装完成后,检查 package.json 文件:
{
"dependencies": {
"@react-native-ohos/react-native-sensors": "^7.2.2-rc.2"
}
}
3. 配置类型定义(TypeScript 项目)
如果遇到类型错误,需要在项目中添加类型定义文件。在 src/types 目录下创建 react-native-sensors.d.ts 文件:
declare module "react-native-sensors" {
export interface SensorData {
x: number;
y: number;
z: number;
timestamp: string;
}
export interface BarometerData {
pressure: number;
}
export interface OrientationData {
qx: number;
qy: number;
qz: number;
qw: number;
pitch: number;
roll: number;
yaw: number;
timestamp: string;
}
export interface Observable<T> {
subscribe: (
callback: (data: T) => void,
error?: (error: any) => void
) => { unsubscribe: () => void };
pipe?: (...operators: any[]) => Observable<T>;
}
export const accelerometer: Observable<SensorData>;
export const gyroscope: Observable<SensorData>;
export const magnetometer: Observable<SensorData>;
export const barometer: Observable<BarometerData>;
export const orientation: Observable<OrientationData>;
export const gravity: Observable<SensorData>;
export enum SensorTypes {
accelerometer = "accelerometer",
gyroscope = "gyroscope",
magnetometer = "magnetometer",
barometer = "barometer",
orientation = "orientation",
gravity = "gravity",
}
export function setUpdateIntervalForType(
type: SensorTypes | string,
interval: number
): void;
export function setLogLevelForType(
type: SensorTypes | string,
level: number
): void;
}
⚠️ 重要:库 bug 修复
react-native-sensors 库本身存在 bug,原生端(HarmonyOS)发送的事件名称是 accelerometerClick、gyroscopeClick 等,但 JS 端监听的事件名称是 Accelerometer、Gyroscope 等,两者不一致导致无法收到数据。
需要修改 node_modules/@react-native-ohos/react-native-sensors/src/sensors.js 文件中的 listenerKeys 映射:
// 修改前(错误)
const listenerKeys = new Map([
["accelerometer", "Accelerometer"], // ❌ 与原生端不匹配
["gyroscope", "Gyroscope"], // ❌ 与原生端不匹配
["magnetometer", "Magnetometer"], // ❌ 与原生端不匹配
["barometer", "Barometer"], // ❌ 与原生端不匹配
["orientation", "Orientation"], // ❌ 与原生端不匹配
["gravity", "gravityClick"], // ✅ 本来就匹配
]);
// 修改后(正确)
const listenerKeys = new Map([
["accelerometer", "accelerometerClick"],
["gyroscope", "gyroscopeClick"],
["magnetometer", "magnetometerClick"],
["barometer", "barometerClick"],
["orientation", "orientationClick"],
["gravity", "gravityClick"],
]);
🔧 HarmonyOS 平台配置 ⭐
1. 引入原生端代码
打开 harmony/entry/oh-package.json5,添加以下依赖:
"dependencies": {
"@react-native-ohos/react-native-sensors": "file:../../node_modules/@react-native-ohos/react-native-sensors/harmony/sensors.har"
}
点击右上角的 sync 按钮,或者在终端执行:
cd entry
ohpm install
2. 配置 CMakeLists
打开 entry/src/main/cpp/CMakeLists.txt,添加:
set(OH_MODULES "${CMAKE_CURRENT_SOURCE_DIR}/../../../oh_modules")
# RNOH_BEGIN: manual_package_linking_1
add_subdirectory("${OH_MODULES}/@react-native-ohos/react-native-sensors/src/main/cpp" ./sensors)
# RNOH_END: manual_package_linking_1
# RNOH_BEGIN: manual_package_linking_2
target_link_libraries(rnoh_app PUBLIC rnoh_sensors)
# RNOH_END: manual_package_linking_2
3. 引入 SensorsPackage
打开 entry/src/main/cpp/PackageProvider.cpp,添加:
#include "RNOH/PackageProvider.h"
#include "generated/RNOHGeneratedPackage.h"
+ #include "SensorsPackage.h"
using namespace rnoh;
std::vector<std::shared_ptr<Package>> PackageProvider::getPackages(Package::Context ctx) {
return {
std::make_shared<RNOHGeneratedPackage>(ctx),
+ std::make_shared<SensorsPackage>(ctx)
};
}
打开 entry/src/main/ets/RNPackagesFactory.ts,添加:
+ import { SensorsPackage } from '@react-native-ohos/react-native-sensors/harmony/sensors/ts';
export function createRNPackages(ctx: RNPackageContext): RNPackage[] {
return [
new SamplePackage(ctx),
+ new SensorsPackage(ctx)
];
}
4. 配置权限
在 entry/src/main/module.json5 中添加传感器权限:
{
"module": {
"requestPermissions": [
{
"name": "ohos.permission.ACCELEROMETER",
},
{
"name": "ohos.permission.GYROSCOPE",
}
]
}
}
📖 API 详解
accelerometer - 加速度计
获取设备的加速度数据,包括 x、y、z 三个轴的加速度值。
类型:Observable<{x: number, y: number, z: number, timestamp: string}>
使用场景:
- 摇一摇功能
- 计步器
- 运动检测
- 设备倾斜检测
import { accelerometer } from "react-native-sensors";
const subscription = accelerometer.subscribe(({ x, y, z, timestamp }) => {
console.log("加速度数据", { x, y, z, timestamp });
});
subscription.unsubscribe();
gyroscope - 陀螺仪
获取设备的角速度数据,包括 x、y、z 三个轴的旋转速度。
类型:Observable<{x: number, y: number, z: number, timestamp: string}>
使用场景:
- 设备旋转检测
- 游戏控制
- VR/AR 应用
- 姿态估计
import { gyroscope } from "react-native-sensors";
const subscription = gyroscope.subscribe(({ x, y, z, timestamp }) => {
console.log("陀螺仪数据", { x, y, z, timestamp });
});
magnetometer - 磁力计
获取设备的磁场数据,包括 x、y、z 三个轴的磁场强度。
类型:Observable<{x: number, y: number, z: number, timestamp: string}>
使用场景:
- 电子罗盘
- 金属检测
- 方向导航
- 地磁定位
import { magnetometer } from "react-native-sensors";
const subscription = magnetometer.subscribe(({ x, y, z, timestamp }) => {
console.log("磁力计数据", { x, y, z, timestamp });
});
barometer - 气压计(我在我的手机上测试不支持)
获取设备的气压数据。
类型:Observable<{pressure: number}>
使用场景:
- 海拔测量
- 天气预测
- 室内定位
- 楼层检测
import { barometer } from "react-native-sensors";
const subscription = barometer.subscribe(({ pressure }) => {
console.log("气压数据", { pressure });
});
orientation - 方向传感器
获取设备的方向数据,包括四元数和欧拉角。
类型:Observable<{qx: number, qy: number, qz: number, qw: number, pitch: number, roll: number, yaw: number, timestamp: string}>
使用场景:
- 屏幕旋转
- 方向指示
- 姿态控制
- 导航应用
import { orientation } from "react-native-sensors";
const subscription = orientation.subscribe(({ pitch, roll, yaw, timestamp }) => {
console.log("方向数据", { pitch, roll, yaw, timestamp });
});
gravity - 重力传感器
获取设备的重力数据,不包括线性加速度。
类型:Observable<{x: number, y: number, z: number, timestamp: string}>
使用场景:
- 重力感应
- 屏幕旋转
- 设备姿态
- 游戏控制
import { gravity } from "react-native-sensors";
const subscription = gravity.subscribe(({ x, y, z, timestamp }) => {
console.log("重力数据", { x, y, z, timestamp });
});
setUpdateIntervalForType - 设置更新频率
设置传感器的数据更新频率。
类型:(type: SensorTypes, interval: number) => void
参数:
type: 传感器类型interval: 更新间隔(毫秒)
import { setUpdateIntervalForType, SensorTypes } from "react-native-sensors";
setUpdateIntervalForType(SensorTypes.accelerometer, 100);
setUpdateIntervalForType(SensorTypes.gyroscope, 50);
📋 完整示例

import React, { useState, useEffect } from "react";
import {
View,
Text,
StyleSheet,
ScrollView,
TouchableOpacity,
SafeAreaView,
StatusBar,
Alert,
} from "react-native";
import {
accelerometer,
gyroscope,
magnetometer,
barometer,
orientation,
gravity,
setUpdateIntervalForType,
SensorTypes,
} from "react-native-sensors";
type SensorData = {
x?: number;
y?: number;
z?: number;
pressure?: number;
pitch?: number;
roll?: number;
yaw?: number;
timestamp?: string;
};
type SensorType = "accelerometer" | "gyroscope" | "magnetometer" | "barometer" | "orientation" | "gravity";
const App: React.FC = () => {
const [activeSensor, setActiveSensor] = useState<SensorType>("accelerometer");
const [sensorData, setSensorData] = useState<SensorData>({});
const [isListening, setIsListening] = useState(false);
const [subscription, setSubscription] = useState<any>(null);
useEffect(() => {
return () => {
if (subscription) {
subscription.unsubscribe();
}
};
}, [subscription]);
const startListening = () => {
if (subscription) {
subscription.unsubscribe();
}
setUpdateIntervalForType(SensorTypes[activeSensor], 100);
let newSubscription: any;
switch (activeSensor) {
case "accelerometer":
newSubscription = accelerometer.subscribe((data) => {
setSensorData(data);
});
break;
case "gyroscope":
newSubscription = gyroscope.subscribe((data) => {
setSensorData(data);
});
break;
case "magnetometer":
newSubscription = magnetometer.subscribe((data) => {
setSensorData(data);
});
break;
case "barometer":
newSubscription = barometer.subscribe((data) => {
setSensorData(data);
});
break;
case "orientation":
newSubscription = orientation.subscribe((data) => {
setSensorData({
pitch: data.pitch,
roll: data.roll,
yaw: data.yaw,
timestamp: data.timestamp,
});
});
break;
case "gravity":
newSubscription = gravity.subscribe((data) => {
setSensorData(data);
});
break;
}
setSubscription(newSubscription);
setIsListening(true);
};
const stopListening = () => {
if (subscription) {
subscription.unsubscribe();
setSubscription(null);
}
setIsListening(false);
setSensorData({});
};
const handleSensorChange = (sensor: SensorType) => {
if (isListening) {
stopListening();
}
setActiveSensor(sensor);
setSensorData({});
};
const renderSensorButton = (type: SensorType, label: string) => (
<TouchableOpacity
key={type}
style={[
styles.sensorButton,
activeSensor === type && styles.sensorButtonActive,
]}
onPress={() => handleSensorChange(type)}
>
<Text
style={[
styles.sensorButtonText,
activeSensor === type && styles.sensorButtonTextActive,
]}
>
{label}
</Text>
</TouchableOpacity>
);
const renderDataValue = (label: string, value?: number) => {
if (value === undefined) return null;
return (
<View style={styles.dataRow}>
<Text style={styles.dataLabel}>{label}</Text>
<Text style={styles.dataValue}>{value.toFixed(4)}</Text>
</View>
);
};
const getSensorDescription = () => {
switch (activeSensor) {
case "accelerometer":
return "测量设备的线性加速度(包括重力),单位:m/s²";
case "gyroscope":
return "测量设备的角速度,单位:rad/s";
case "magnetometer":
return "测量设备周围的磁场强度,单位:μT";
case "barometer":
return "测量大气压力,单位:hPa";
case "orientation":
return "测量设备的方向角度,单位:度";
case "gravity":
return "测量重力加速度(不包括线性加速度),单位:m/s²";
}
};
return (
<SafeAreaView style={styles.container}>
<StatusBar barStyle="dark-content" backgroundColor="#FFFFFF" />
<View style={styles.header}>
<Text style={styles.headerTitle}>传感器示例</Text>
<TouchableOpacity
style={[styles.controlButton, isListening && styles.stopButton]}
onPress={isListening ? stopListening : startListening}
>
<Text style={styles.controlButtonText}>
{isListening ? "停止" : "开始"}
</Text>
</TouchableOpacity>
</View>
<View style={styles.sensorList}>
{renderSensorButton("accelerometer", "加速度计")}
{renderSensorButton("gyroscope", "陀螺仪")}
{renderSensorButton("magnetometer", "磁力计")}
{renderSensorButton("barometer", "气压计")}
{renderSensorButton("orientation", "方向")}
{renderSensorButton("gravity", "重力")}
</View>
<ScrollView style={styles.content}>
<View style={styles.infoCard}>
<Text style={styles.infoTitle}>当前传感器</Text>
<Text style={styles.infoValue}>
{activeSensor === "accelerometer" && "加速度计"}
{activeSensor === "gyroscope" && "陀螺仪"}
{activeSensor === "magnetometer" && "磁力计"}
{activeSensor === "barometer" && "气压计"}
{activeSensor === "orientation" && "方向传感器"}
{activeSensor === "gravity" && "重力传感器"}
</Text>
<Text style={styles.infoDescription}>{getSensorDescription()}</Text>
</View>
<View style={styles.dataCard}>
<Text style={styles.dataTitle}>实时数据</Text>
{!isListening && (
<Text style={styles.noDataText}>点击"开始"按钮获取传感器数据</Text>
)}
{isListening && Object.keys(sensorData).length === 0 && (
<Text style={styles.noDataText}>正在获取数据...</Text>
)}
{isListening && Object.keys(sensorData).length > 0 && (
<>
{renderDataValue("X 轴", sensorData.x)}
{renderDataValue("Y 轴", sensorData.y)}
{renderDataValue("Z 轴", sensorData.z)}
{renderDataValue("气压", sensorData.pressure)}
{renderDataValue("俯仰角 (Pitch)", sensorData.pitch)}
{renderDataValue("翻滚角 (Roll)", sensorData.roll)}
{renderDataValue("偏航角 (Yaw)", sensorData.yaw)}
{sensorData.timestamp && (
<View style={styles.dataRow}>
<Text style={styles.dataLabel}>时间戳</Text>
<Text style={styles.dataValue}>{sensorData.timestamp}</Text>
</View>
)}
</>
)}
</View>
<View style={styles.tipsCard}>
<Text style={styles.tipsTitle}>使用提示</Text>
<Text style={styles.tipsText}>• 加速度计:可用于摇一摇、计步等功能</Text>
<Text style={styles.tipsText}>• 陀螺仪:可用于游戏控制、VR/AR 应用</Text>
<Text style={styles.tipsText}>• 磁力计:可用于电子罗盘、方向导航</Text>
<Text style={styles.tipsText}>• 气压计:可用于海拔测量、楼层检测</Text>
<Text style={styles.tipsText}>• 方向传感器:可用于屏幕旋转、姿态控制</Text>
<Text style={styles.tipsText}>• 重力传感器:可用于重力感应、游戏控制</Text>
</View>
</ScrollView>
</SafeAreaView>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#F5F5F5",
},
header: {
flexDirection: "row",
alignItems: "center",
justifyContent: "space-between",
padding: 16,
backgroundColor: "#FFFFFF",
borderBottomWidth: 1,
borderBottomColor: "#E5E5EA",
},
headerTitle: {
fontSize: 20,
fontWeight: "700",
color: "#333333",
},
controlButton: {
backgroundColor: "#007AFF",
paddingHorizontal: 20,
paddingVertical: 10,
borderRadius: 8,
},
stopButton: {
backgroundColor: "#FF3B30",
},
controlButtonText: {
color: "#FFFFFF",
fontSize: 16,
fontWeight: "600",
},
sensorList: {
flexDirection: "row",
flexWrap: "wrap",
backgroundColor: "#FFFFFF",
paddingHorizontal: 16,
paddingVertical: 12,
gap: 8,
},
sensorButton: {
paddingHorizontal: 16,
paddingVertical: 8,
backgroundColor: "#F0F0F0",
borderRadius: 20,
},
sensorButtonActive: {
backgroundColor: "#007AFF",
},
sensorButtonText: {
fontSize: 14,
color: "#666666",
fontWeight: "500",
},
sensorButtonTextActive: {
color: "#FFFFFF",
},
content: {
flex: 1,
padding: 16,
},
infoCard: {
backgroundColor: "#FFFFFF",
borderRadius: 12,
padding: 16,
marginBottom: 16,
},
infoTitle: {
fontSize: 14,
color: "#999999",
marginBottom: 8,
},
infoValue: {
fontSize: 24,
fontWeight: "700",
color: "#333333",
marginBottom: 8,
},
infoDescription: {
fontSize: 14,
color: "#666666",
lineHeight: 20,
},
dataCard: {
backgroundColor: "#FFFFFF",
borderRadius: 12,
padding: 16,
marginBottom: 16,
},
dataTitle: {
fontSize: 18,
fontWeight: "600",
color: "#333333",
marginBottom: 16,
},
noDataText: {
fontSize: 14,
color: "#999999",
textAlign: "center",
paddingVertical: 20,
},
dataRow: {
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center",
paddingVertical: 12,
borderBottomWidth: 1,
borderBottomColor: "#F0F0F0",
},
dataLabel: {
fontSize: 16,
color: "#666666",
},
dataValue: {
fontSize: 16,
fontWeight: "600",
color: "#007AFF",
fontFamily: "monospace",
},
tipsCard: {
backgroundColor: "#FFFFFF",
borderRadius: 12,
padding: 16,
marginBottom: 16,
},
tipsTitle: {
fontSize: 18,
fontWeight: "600",
color: "#333333",
marginBottom: 12,
},
tipsText: {
fontSize: 14,
color: "#666666",
lineHeight: 22,
marginBottom: 4,
},
});
export default App;
⚠️ 注意事项
权限要求
使用传感器功能需要在 module.json5 中配置相应权限:
| 传感器 | 所需权限 |
|---|---|
| 加速度计 | ohos.permission.ACCELEROMETER |
| 陀螺仪 | ohos.permission.GYROSCOPE |
| 磁力计 | 无需特殊权限 |
| 气压计 | 无需特殊权限 |
| 方向传感器 | 无需特殊权限 |
| 重力传感器 | 无需特殊权限 |
使用建议
- 及时取消订阅: 传感器数据是持续流式的,在不使用时应及时调用
unsubscribe()取消订阅,避免资源浪费 - 合理设置更新频率: 根据实际需求设置合适的更新频率,过高的频率会增加耗电
- 数据过滤: 使用 RxJS 的
pipe和filter对数据进行过滤,减少无效数据处理 - 错误处理: 添加错误处理逻辑,处理传感器不可用的情况
常见问题
Q: 传感器数据为 0 或不变化?
A: 检查是否正确配置了权限,部分传感器需要在 module.json5 中声明权限才能正常工作。
Q: 应用耗电严重?
A: 检查是否在不使用时及时取消了传感器订阅,建议在组件卸载时取消订阅。
Q: 数据更新频率不符合预期?
A: 使用 setUpdateIntervalForType 设置更新频率,但实际频率可能因设备性能而异。
Q: 某些传感器不可用?
A: 部分设备可能不支持某些传感器,建议在使用前检查传感器是否可用。
性能优化
- 按需订阅: 只在需要时订阅传感器数据
- 降低频率: 根据实际需求降低更新频率
- 数据过滤: 使用 RxJS 操作符过滤数据
- 及时清理: 组件卸载时取消所有订阅
📚 参考资源
- 官方文档: https://github.com/react-native-sensors/react-native-sensors
- 鸿蒙适配仓库: https://atomgit.com/openharmony-sig/rntpc_react-native-sensors
- 问题反馈: https://github.com/react-native-oh-library/react-native-sensors/issues
更多推荐


所有评论(0)