必须先调用 uni.startAccelerometer 才能触发 uni.onAccelerometerChange;常见错误包括未启动传感器、iOS 首次加载静默失败、误将 setFrequency 当启动开关;有效摇动需计算合加速度及帧间差值平方和,并防连发与及时注销监听。

App 端必须调用 uni.startAccelerometer 才能拿到加速度数据,否则 uni.onAccelerometerChange 一毛钱都不会触发——这不是监听没写对,是传感器压根没启动。
为什么 uni.onAccelerometerChange 没回调?
常见错误现象:注册了监听但完全收不到数据;console.log 一句都不打;iOS 真机首次加载页面就调用也静默失败。
- 没调
uni.startAccelerometer()—— 它不是可选步骤,是硬性前置条件 -
uni.getAccelerometerFrequency只设频率,不启动采集,别把它当开关用 - iOS WKWebView 下,页面刚 load 完就调用,JSBridge 可能还没就绪,建议绑定到用户点击后触发
- Android 后台运行时系统会限频甚至停采,摇一摇功能必须在前台活跃态下使用
uni.startAccelerometer 的参数和兼容性坑
interval 参数不是“越高越好”,不同平台实际表现差异大:
-
"game":理论最快(iOS 100Hz、Android 50Hz),但 iOS 常被系统降频,Android 部分厂商(如华为 EMUI)直接忽略 -
"ui":实测最稳,约 30–40Hz,功耗与灵敏度平衡点,推荐默认值 -
"normal":太慢(~10Hz),抖动细节丢失严重,慎用 - 设错值不会报错,但会静默 fallback 到平台默认频率
怎么算一次“有效摇动”?别只看单轴绝对值
真实摇动是三维空间里的快速矢量变化,单看 res.x > 15 这种判断在走路、放手机、甚至呼吸时都会误触发。
- 每次取
Math.sqrt(res.x * res.x + res.y * res.y + res.z * res.z)得合加速度(单位:g) - 缓存最近 3–5 帧,计算帧间差值平方和:
dx*dx + dy*dy + dz*dz(避免开方,省性能) - 连续 2–3 帧该值 > 20,才记为一次有效抖动起始
- 再叠加时间窗口防连发:检测到后设
isShaking = true,1500ms 内 ignore 所有新触发
最后注意:这个监听是全局的,页面 onHide 或 onUnload 时必须手动 uni.offAccelerometerChange 注销,否则回调还在执行,容易引发 Cannot read property 'xxx' of null 或持续耗电。别指望 GC 自动清理。











