You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过系统运动状态回调启停传感器数据采集的前台服务

需求:手机非静止状态下采集加速度计、陀螺仪传感器数据

已实现功能

  • 使用 Sensor Listener 监听传感器数据
sensorManager = getSystemService(SENSOR_SERVICE) as SensorManager

val accelerometerSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)

sensorManager.registerListener(
        accSensor,
        accelerometerSensor,
        SensorManager.SENSOR_DELAY_NORMAL
    )
  • 运行前台服务在后台持续跟踪传感器数据,应用从最近任务列表划走也可正常运行
serviceIntent = Intent(context, SensorService::class.java)
context.startForegroundService(serviceIntent)
  • 通过监听开机完成事件的广播接收器,实现设备重启后自动启动服务

未解决问题

  • 无法在设备停止移动时停止采集传感器数据的服务
  • 无法在用户设备开始移动时启动未运行的传感器完成数据采集

实现方案

Android 系统本身提供了低功耗的显著运动检测能力,配合自定义的静止判断逻辑,即可实现根据设备运动状态自动启停采集服务:

1. 运动开始检测

使用系统内置的 *Sensor.TYPE_SIGNIFICANT_MOTION* 传感器,该传感器由硬件层实现,功耗极低,仅在检测到设备发生显著位移(如用户拿起手机、步行移动)时触发回调,非常适合作为运动启动的触发信号。
注册代码示例:

// 检查设备是否支持显著运动检测
val significantMotionSensor = sensorManager.getDefaultSensor(Sensor.TYPE_SIGNIFICANT_MOTION)
if (significantMotionSensor != null) {
    val motionTriggerListener = object : TriggerEventListener() {
        override fun onTrigger(event: TriggerEvent?) {
            // 检测到运动启动,启动前台采集服务
            if (!isServiceRunning(SensorService::class.java)) {
                val serviceIntent = Intent(context, SensorService::class.java)
                context.startForegroundService(serviceIntent)
            }
            // 单次触发后需重新注册才能检测下一次运动
            sensorManager.requestTriggerSensor(this, significantMotionSensor)
        }
    }
    // 注册触发器
    sensorManager.requestTriggerSensor(motionTriggerListener, significantMotionSensor)
} else {
    // 设备不支持硬件显著运动检测,降级使用低采样率加速度计轮询判断运动
}

注意:Android 10及以上系统需要申请 ACTIVITY_RECOGNITION 权限才能正常使用该传感器。

2. 运动结束检测

系统没有提供标准的运动结束回调,可在采集服务运行期间,通过加速度计数值判断设备是否持续静止,达到阈值后自动停止服务:
判断逻辑:计算三轴加速度的合值,减去重力加速度(9.81m/s²)得到运动产生的加速度,如果该值持续3~5秒低于设定的静止阈值,即可判定设备停止运动,停止采集服务。
代码示例:

private var lastMovingTime = System.currentTimeMillis()
// 静止阈值,可根据业务需求调整,避免微小晃动误判
private val STATIONARY_THRESHOLD = 0.2f
// 持续静止3秒触发服务停止
private val STOP_DELAY = 3000L

val accSensor = object : SensorEventListener {
    override fun onSensorChanged(event: SensorEvent?) {
        event ?: return
        val x = event.values[0]
        val y = event.values[1]
        val z = event.values[2]
        // 计算合加速度
        val totalAcc = sqrt(x*x + y*y + z*z)
        // 扣除重力影响,得到仅由运动产生的加速度
        val motionAcc = abs(totalAcc - 9.81f)
        
        if (motionAcc > STATIONARY_THRESHOLD) {
            lastMovingTime = System.currentTimeMillis()
            // 原有传感器数据采集逻辑
            saveSensorData(event.values)
        } else {
            // 静止时长达到阈值,停止服务
            if (System.currentTimeMillis() - lastMovingTime > STOP_DELAY) {
                stopForeground(STOP_FOREGROUND_REMOVE)
                stopSelf()
            }
        }
    }

    override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) = Unit
}

内容的提问来源于stack exchange,提问作者erluxman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 02:48:04