如何通过SensorManager替代Google Fit API废弃方法获取步数
问题定位
你现有代码无法通过SensorManager拿到步数、心率数据的核心原因有两点:
- 仅注册了加速度计(
TYPE_ACCELEROMETER)的监听,没有注册计步、心率相关传感器的监听,onSensorChanged回调永远不会收到对应类型的传感器事件 - 混淆了原生SensorManager和Google Fit API的能力边界:SensorManager仅能读取当前设备本地硬件传感器的实时数据,无法获取Google Fit中跨应用、跨设备同步的历史聚合数据,如果需要历史统计数据,需要迁移到Health Connect实现,SensorManager只能完成实时数据采集。
具体实现步骤
1. 传感器选型
先明确三类常用传感器的特性,按需选择:
TYPE_STEP_DETECTOR:每检测到用户走1步就触发1次回调,event.values[0]固定为1.0,适合实时步测触发场景TYPE_STEP_COUNTER:返回设备上次重启以来系统累计统计的总步数,功耗低、准确率高,适合做周期内步数统计,使用时需要自行记录初始值,用当前累计值减去初始值得到统计周期内的步数TYPE_HEART_RATE:返回光学心率传感器采集的实时心率值,单位为次/分钟,使用需要BODY_SENSORS权限,Android 13及以上版本后台采集还需要额外申请BODY_SENSORS_BACKGROUND权限
2. 代码修正
首先替换原有的传感器初始化逻辑,删除不需要单独注册的加速度计(如果不需要原始加速度数据的话),新增需要的传感器实例:
// 步测传感器 private val stepDetectorSensor by lazy { sensorManager.getDefaultSensor(Sensor.TYPE_STEP_DETECTOR) } // 累计计步传感器 private val stepCounterSensor by lazy { sensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER) } // 心率传感器 private val heartRateSensor by lazy { sensorManager.getDefaultSensor(Sensor.TYPE_HEART_RATE) } // 计步统计相关变量 private var stepCounterBaseValue = -1 private var currentSteps = 0
然后修改onResume中的传感器注册逻辑,注册前先判断设备是否支持对应传感器,避免空指针:
override fun onResume() { super.onResume() // 逐个注册需要的传感器 stepDetectorSensor?.let { sensorManager.registerListener(this, it, SensorManager.SENSOR_DELAY_NORMAL) } ?: Log.w("SensorCheck", "当前设备不支持步测传感器") stepCounterSensor?.let { sensorManager.registerListener(this, it, SensorManager.SENSOR_DELAY_NORMAL) } ?: Log.w("SensorCheck", "当前设备不支持累计计步传感器") heartRateSensor?.let { sensorManager.registerListener(this, it, SensorManager.SENSOR_DELAY_NORMAL) } ?: Log.w("SensorCheck", "当前设备不支持心率传感器") }
原有的onPause注销逻辑不需要修改,unregisterListener(this)会注销当前监听器绑定的所有传感器。
最后修改onSensorChanged的回调处理逻辑:
override fun onSensorChanged(event: SensorEvent?) { event ?: return when (event.sensor.type) { Sensor.TYPE_STEP_DETECTOR -> { currentSteps += 1 Log.d("StepData", "检测到新步数,当前累计:$currentSteps") } Sensor.TYPE_STEP_COUNTER -> { val totalSinceReboot = event.values[0].toInt() // 首次收到回调时记录初始基准值 if (stepCounterBaseValue == -1) { stepCounterBaseValue = totalSinceReboot } // 计算统计周期内的步数,跨天/重置统计时把stepCounterBaseValue更新为当时的累计值即可 currentSteps = totalSinceReboot - stepCounterBaseValue Log.d("StepData", "统计周期内累计步数:$currentSteps") } Sensor.TYPE_HEART_RATE -> { val bpm = event.values[0].toInt() Log.d("HeartRateData", "实时心率:$bpm 次/分") } } }
注意事项
- 部分中低端设备、无心率模块的设备没有对应硬件传感器,这种情况无法通过SensorManager获取数据,只能读取其他应用同步到系统/Health Connect的数据
- 如果需要后台持续采集传感器数据,需要配合前台服务实现,应用退到后台被杀死后传感器监听会自动断开
- 旧版Google Fit的
getHistoryClient、getSensorClient废弃后,官方推荐使用Health Connect作为健康数据统一存储、读取的入口,SensorManager无法替代其跨应用数据读取、历史数据聚合的能力。
内容的提问来源于stack exchange,提问作者Darotudeen
相关产品推荐
相关产品推荐

