
引言智能手机上集成了丰富的传感器加速度计能感知你拿起手机的动作陀螺仪能追踪你转动设备的角度光线传感器能根据环境亮度自动调节屏幕背光磁力计能告诉你北在哪个方向。这些传感器共同构成了设备感知物理世界的能力——它们是体感游戏、运动追踪、AR、导航等应用的技术基座。HarmonyOS 通过ohos.sensor模块为开发者提供了统一的传感器访问接口。这个模块封装了 10 余种常见传感器的数据订阅机制使用方式极其简洁——调用sensor.on()订阅某个传感器传入回调函数框架在每次传感器数据更新时自动调用你的回调。不需要手动管理采样线程不需要处理硬件寄存器也不需要对原始电信号做滤波——所有脏活累活都被框架封装好了。本文将通过构建一个传感器实验室深入讲解ohos.sensor的核心 APISensorId传感器类型枚举、sensor.on()/sensor.off()的订阅与取消机制、AccelerometerResponse/GyroscopeResponse等响应数据结构、interval采样间隔的控制以及传感器生命周期的正确管理方式。读完本文你将能够使用sensor.on(sensor.SensorId.ACCELEROMETER, callback, options)订阅加速度计数据使用sensor.on(sensor.SensorId.GYROSCOPE, callback, options)订阅陀螺仪数据理解options.interval的纳秒单位及典型取值Game/UI/Normal正确使用sensor.off(sensorId)取消订阅避免电量和性能浪费了解传感器数据结构的差异加速度含重力 vs 线性加速度掌握 8 种常用传感器的用途和数据单位在组件生命周期中正确管理传感器订阅ohos.sensor 模块概述传感器的分类ohos.sensor支持的所有传感器通过sensor.SensorId枚举来标识。常用传感器包括SensorId 枚举传感器名称数据类型单位典型应用ACCELEROMETER加速度计{x, y, z}m/s²摇一摇、计步、姿态检测ACCELEROMETER_UNCALIBRATED未校准加速度计{x, y, z} biasm/s²需要原始数据的高精度场景LINEAR_ACCELERATION线性加速度{x, y, z}m/s²运动检测不含重力GYROSCOPE陀螺仪{x, y, z}rad/s旋转检测、AR、全景照片AMBIENT_LIGHT环境光传感器{intensity}lux自动亮度调节MAGNETIC_FIELD磁力计{x, y, z}μT指南针、地图定向PROXIMITY接近光传感器{distance}cm通话息屏BAROMETER气压计{pressure}hPa楼层定位、天气HALL霍尔传感器{status}bool翻盖皮套检测PEDOMETER计步器{steps}steps健康应用步数统计关键区分ACCELEROMETER加速度计测量的是含重力的总加速度——手机平放时 Z 轴约为 9.8 m/s²。LINEAR_ACCELERATION线性加速度则排除了重力分量反映的是纯粹的运动加速度。对于运动检测步数、挥动用线性加速度对于姿态检测倾斜角度、屏幕方向用含重力的加速度计。采样周期与性能sensor.on()的第三个参数options.interval控制传感器的采样频率单位为纳秒。这是一个需要适应的地方——常规开发者习惯以毫秒ms为单位但传感器 API 使用纳秒ns来表示采样间隔。换算关系1ms 1,000,000ns。典型取值场景场景采样间隔纳秒值适用原因体感游戏20ms20,000,000需要高频采样以保证实时响应UI 动画60ms60,000,000匹配 60fps 刷新率16.7ms/帧留余量常规监测100-200ms100,000,000-200,000,000省电优先数据变化足够平滑后台记录1000ms1,000,000,000极低功耗不需要实时响应采样频率越高数据越细腻但功耗也越大。在每个传感器应用的设计阶段就应该明确采样频率——Game 模式20ms功耗最高但延迟最低Normal 模式200ms是日常应用的推荐默认值。核心 API 逐项解析导入模块import{sensor}fromkit.SensorServiceKit;注意sensor 模块归属于kit.SensorServiceKit不是kit.ArkTS或kit.BasicServicesKit。这是专门为传感器服务设立的套件。sensor.on(id, callback, options?)订阅传感器数据。这是使用传感器最核心的方法sensor.on(sensor.SensorId.ACCELEROMETER,(data:sensor.AccelerometerResponse){this.accelXdata.x;this.accelYdata.y;this.accelZdata.z;// 数据实时更新直接在回调中更新 State 即可驱动 UI 刷新},{interval:100000000}// 100ms 100,000,000ns);参数说明id: 传感器类型sensor.SensorId枚举值。callback: 数据回调函数。传感器每产生一次新数据回调被调用一次。回调的参数类型取决于传感器类型AccelerometerResponse/GyroscopeResponse/LightResponse等。options可选: 采样配置对象。interval字段指定采样间隔纳秒有效范围通常为 5,000,000ns5ms到 200,000,000ns200ms。如果不传options系统使用默认采样周期 200ms。sensor.off(id)取消传感器数据订阅sensor.off(sensor.SensorId.ACCELEROMETER);off()的参数只需要传感器 ID——系统会移除该传感器的所有已注册回调。如果有多个回调注册到同一个传感器off()会一次性取消全部。取消订阅的重要性不亚于发起订阅。正在运行的传感器持续消耗电量——加速度计的典型功耗约为 0.2mA陀螺仪约为 5mA。在用户离开页面后继续采集传感器数据等于在后台偷偷烧用户的电池。正确的做法是在aboutToDisappear()中取消所有订阅aboutToDisappear():void{if(this.accelOn)sensor.off(sensor.SensorId.ACCELEROMETER);if(this.gyroOn)sensor.off(sensor.SensorId.GYROSCOPE);}sensor.once(id, callback)获取一次传感器数据后自动取消订阅。适用于只需要当前值快照的场景如当前环境亮度是多少sensor.once(sensor.SensorId.AMBIENT_LIGHT,(data:sensor.LightResponse){this.brightnessdata.intensity;// 自动取消订阅无需手动 off()});once()在以下场景中特别有用应用启动时获取一次环境光来决定初始主题。拍照前获取一次气压来嵌入照片 EXIF。用户手动点击刷新当前方向按钮。各传感器的响应数据结构AccelerometerResponse / LinearAccelerometerResponse{x:number,y:number,z:number}// 单位: m/s²GyroscopeResponse{x:number,y:number,z:number}// 单位: rad/sLightResponse{intensity:number}// 单位: luxMagneticFieldResponse{x:number,y:number,z:number}// 单位: μTProximityResponse{distance:number}// 单位: cmBarometerResponse{pressure:number}// 单位: hPaHallResponse{status:number}// 0 远离, 1 靠近PedometerResponse{steps:number}// 累计步数各传感器的返回值结构高度一致——多数返回三轴{x, y, z}。这种设计简化了开发者的心智模型加速度计、陀螺仪、磁力计的代码结构完全相同只需改变 SensorId 和响应类型名。Demo 设计传感器实验室本文 Demo 实现了一个传感器实验室同时展示加速度计和陀螺仪的实时数据页面结构Column根容器 ├── Header深色标题栏传感器实验室 ohos.sensor 标签 ├── Scroll │ └── Column │ ├── 状态总览卡片 │ │ ├── 加速度计状态运行中/已关闭 │ │ ├── 陀螺仪状态运行中/已关闭 │ │ ├── 数据点计数 重置按钮 │ │ └── 状态消息 │ ├── 加速度计面板 │ │ ├── X/Y/Z 轴实时数据数值 动态色条 │ │ ├── 合加速度值 │ │ └── 启动/关闭按钮 │ ├── 陀螺仪面板 │ │ ├── X/Y/Z 轴实时数据数值 动态色条 │ │ └── 启动/关闭按钮 │ ├── 采样频率选择区 │ │ ├── Game(20ms) / UI(60ms) / Normal(100ms) / Slow(200ms) │ │ └── 说明文字 │ ├── 常用传感器一览表8 种传感器 用途 单位 │ └── API 参考区 └── 根容器结束4 个交互点启动/关闭加速度计点击按钮 →sensor.on(sensor.SensorId.ACCELEROMETER, ...)订阅 → X/Y/Z 三条色条随设备移动实时变化 → 合加速度数值更新 → 再点击关闭 →sensor.off()取消订阅。启动/关闭陀螺仪点击按钮 →sensor.on(sensor.SensorId.GYROSCOPE, ...)订阅 → 旋转设备时三轴数值实时变化 → 条的长度和颜色反映旋转强度。切换采样频率点击 Game/UI/Normal/Slow 四个按钮之一 → 修改sampleRate→ 重新订阅传感器 → 肉眼观察数据刷新速度的变化。重置峰值点击重置按钮 → 最大加速度/最大角速度峰值归零 → 数据点计数归零 → 可以观察新一轮运动产生的峰值变化。核心实现传感器订阅与取消Demo 中加速度计的订阅逻辑是传感器 API 的标准用法startAccel():void{sensor.on(sensor.SensorId.ACCELEROMETER,(data:sensor.AccelerometerResponse){this.accelXdata.x;this.accelYdata.y;this.accelZdata.z;// 计算合加速度含重力this.accelMagMath.sqrt(data.x*data.xdata.y*data.ydata.z*data.z);// 追踪峰值if(this.accelMagthis.maxAccel){this.maxAccelthis.accelMag;}this.dataPoints;},{interval:this.sampleRate*1000000}// ms → ns);this.accelOntrue;}stopAccel():void{sensor.off(sensor.SensorId.ACCELEROMETER);this.accelOnfalse;}关键细节回调运行在哪个线程传感器回调在事件处理线程中触发但 ArkUI 框架会自动将State的变更同步到 UI 线程——开发者不需要关心线程切换。回调中更新 State直接在回调中给State变量赋值即可触发 UI 刷新。不需要runOnUIThread等手动切换。峰值追踪Demo 在回调中维护maxAccel最大合加速度这是传感器数据统计分析的最基础模式——在实际应用中这个逻辑可以扩展为计步、摇动检测、跌倒检测等。单位换算sampleRate是毫秒方便 UI 显示和用户理解sensor.on()需要的是纳秒所以乘以 1,000,000。动态色条的视觉设计Demo 中有一个精心设计的动态色条组件——它把抽象的加速度数值转化为可视化的条状图BuilderaxisBar(label:string,value:number,maxVal:number,color:string){Row(){Text(label).fontSize(12).width(16)Row(){Row().height(14).width(this.getBarWidth(value,Math.max(maxVal,1))).borderRadius(7).backgroundColor(color).animation({duration:100,curve:Curve.Linear})Blank()}.height(14).layoutWeight(1).borderRadius(7).backgroundColor(#F5F5F5)Text(this.formatNumber(value)).fontSize(11).fontColor(color).width(56)}}色条的宽度通过getBarWidth()计算——根据当前值和历史最大值的比例映射到 0-120vp 区间。.animation({ duration: 100 })是关键属性——它让色条的变化平滑过渡类似 CSS 的transition而不是跳跃式变化。100ms 的动画时长足够短使变化看起来实时又不至于频繁跳变产生闪烁。采样频率的动态切换Demo 中四个采样频率按钮的处理方式值得关注setRate(rate:number):void{this.sampleRaterate;// 修改采样率后如果传感器正在运行需要重新订阅// 因为 interval 参数只在 on() 调用时传入this.statusMsg采样率已设为 rate.toString()ms;}这是一个重要的 API 行为特性sensor.on()的interval在订阅时固定。运行期间修改采样频率需要先off()再on()重新订阅。Demo 中将频率切换与传感器开关分离——用户先手动关闭传感器再调整频率再开启——这样避免了设备正在运行中修改采样频率的复杂逻辑。如果产品需要运行中动态切换频率实现方式为// 动态切换采样率if(this.accelOn){sensor.off(sensor.SensorId.ACCELEROMETER);sensor.on(sensor.SensorId.ACCELEROMETER,callback,{interval:newRate});}生命周期管理传感器订阅的生命周期管理是 Demo 中最容易被忽略但最重要的部分aboutToDisappear():void{if(this.accelOn){sensor.off(sensor.SensorId.ACCELEROMETER);}if(this.gyroOn){sensor.off(sensor.SensorId.GYROSCOPE);}}如果不在aboutToDisappear中取消订阅即使用户离开了页面传感器的回调仍然会持续触发——GPS 和陀螺仪是设备上功耗最高的传感器之一这种泄漏会在用户不知情的情况下快速消耗电量。对于需要后台持续监测的场景如计步器应该使用ContinuousTask长时任务机制来合法地在后台运行传感器。实际应用场景场景一摇一摇功能利用加速度计的合加速度变化来检测摇动动作sensor.on(sensor.SensorId.ACCELEROMETER,(data){letmagMath.sqrt(data.x*data.xdata.y*data.ydata.z*data.z);if(mag15){// 阈值超过 15m/s² 认为是一次有效的摇动this.onShake();}},{interval:20000000});// 20ms 高频采样以捕捉快速摇动场景二指南针利用磁力计和加速度计计算设备方向实现电子指南针sensor.on(sensor.SensorId.MAGNETIC_FIELD,(magData){// 结合加速度计数据计算方位角letazimuthMath.atan2(magData.y,magData.x)*180/Math.PI;if(azimuth0)azimuth360;this.compassAngleazimuth;},{interval:60000000});场景三自动亮度调节根据环境光传感器自动调整应用内的主题亮度和对比度sensor.on(sensor.SensorId.AMBIENT_LIGHT,(data){if(data.intensity10){this.themeModedark;// 暗光环境 → 深色主题}elseif(data.intensity500){this.themeModelight;// 强光环境 → 浅色主题 高对比度}},{interval:500000000});// 500ms 足够了亮度变化不快场景四体感游戏控制利用陀螺仪的高频数据来控制游戏中的角色或视角sensor.on(sensor.SensorId.GYROSCOPE,(data){// 累计旋转角度简单积分this.pitchdata.x*0.02;// 20ms * rad/s ≈ Δanglethis.yawdata.y*0.02;// 将角度映射到游戏中的视角或角色位置this.cameraAnglethis.yaw;},{interval:20000000});// 20ms 高频确保体感操作流畅注意从角速度rad/s推算角度需要积分累加角速度 × 时间间隔。简单的积分会累积误差对于需要精确角度的场景如 AR 中的 3D 对象放置应该使用sensor.on(sensor.SensorId.ROTATION_VECTOR, ...)来获取融合后的姿态数据。注意事项与最佳实践1. 及时取消订阅这是最重要的建议。不在aboutToDisappear()中取消传感器订阅会导致电量持续消耗陀螺仪功耗约为 5mA1000mAh 的电池在 200 小时的连续陀螺仪订阅后耗尽。数据流无用用户在浏览其他页面时传感器数据仍然在回调中更新State——虽然页面不可见但数据更新会触发不必要的组件渲染。2. 选择合适的采样率采样率越高延迟越低但功耗越大。根据场景选择合适的采样率游戏/体感20ms不高于 50Hz 的游戏逻辑需求UI 动画/交互60ms匹配 60fps每帧获取一次数据足够常规监测200ms人眼对 5Hz 以上的刷新率感知不敏感后台记录1000ms省电极致3. 在回调中保持轻量传感器回调在专用事件线程中触发频率可能高达 50Hz每 20ms 一次。如果回调中执行了复杂计算如大数据量的滤波算法、文件 I/O会导致回调队列堆积传感器数据延迟增大。需要复杂处理时将原始数据传给 Worker 线程处理sensor.on(sensor.SensorId.ACCELEROMETER,(data){this.workerInstance.postMessage({raw:data,timestamp:Date.now()});// Worker 线程负责降噪、特征提取、模式匹配等},{interval:20000000});4. 理解坐标系传感器数据使用设备自身的坐标系X 轴水平向右手机横放时指向右侧Y 轴垂直向上手机横放时指向上方Z 轴垂直于屏幕指向外手机平放时指向天花板手机平放在桌面上时加速度计返回{x: ~0, y: ~0, z: ~9.8}。这意味着 Z 轴的正方向和重力方向相反——因为加速度计测量的是施加在设备上的力而平放时桌面给设备的支持力向上Z 方向重力向下Z- 方向。5. 不同设备传感器精度不同低端手机和旗舰手机的传感器精度可能有数量级的差异。为关键阈值如摇一摇的加速度阈值提供校准机制或者使用相对变化而非绝对数值来判断事件。总结本文通过构建一个传感器实验室深入讲解了 HarmonyOSohos.sensor模块的核心用法sensor.SensorId传感器类型枚举ACCELEROMETER、GYROSCOPE、AMBIENT_LIGHT 等 10 余种传感器一应俱全。sensor.on(id, callback, options)订阅传感器数据。interval以纳秒为单位1ms 1,000,000ns典型取值为 20msGame、60msUI、200msNormal。sensor.off(id)取消订阅传感器数据。在aboutToDisappear()中取消订阅是防止电量泄漏的关键。sensor.once(id, callback)获取一次数据后自动取消适用于快照式场景。各传感器的响应数据加速度计和陀螺仪返回{x, y, z}三元组环境光返回{intensity}气压计返回{pressure}等。传感器是连接数字世界和物理世界的桥梁。它们赋予应用感知环境的能力——你的应用不仅知道用户点击了什么还知道用户在怎样移动、周围是亮是暗、朝向哪个方向。掌握ohos.sensorAPI你就能将这种感知能力融入自己的应用创造出更智能、更自然的交互体验。