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

Android Kotlin实现每分钟向REST API发送传感器与心率数据

解决方案

一、解决屏幕熄灭后传感器数据停止的问题

Android屏幕熄灭后会进入低功耗模式,后台服务易被系统限制,需做以下调整:

  • 使用前台服务(Foreground Service):前台服务会在通知栏保留持续通知,系统不会轻易终止它。在服务启动时调用startForeground():
// 先创建通知渠道(Android 8.0+必填)
private fun createNotificationChannel() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        val channel = NotificationChannel(CHANNEL_ID, "数据采集通道", NotificationManager.IMPORTANCE_LOW)
        val manager = getSystemService(NotificationManager::class.java)
        manager.createNotificationChannel(channel)
    }
}

// 在服务onCreate/onStartCommand中启动前台服务
override fun onCreate() {
    super.onCreate()
    createNotificationChannel()
    val notification = NotificationCompat.Builder(this, CHANNEL_ID)
        .setContentTitle("数据采集服务")
        .setContentText("正在采集运动与心率数据")
        .setSmallIcon(R.drawable.ic_notification)
        .build()
    startForeground(NOTIFICATION_ID, notification)
}
  • 申请唤醒锁(Wake Lock):保证屏幕熄灭后CPU仍能运行,记得在不需要时释放避免耗电:
private lateinit var wakeLock: PowerManager.WakeLock

override fun onCreate() {
    super.onCreate()
    val powerManager = getSystemService(POWER_SERVICE) as PowerManager
    wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MyApp::DataLock")
    wakeLock.acquire(60*1000L /* 可设置超时时间,按需调整 */)
}

override fun onDestroy() {
    super.onDestroy()
    if (wakeLock.isHeld) wakeLock.release()
}

同时在Manifest中添加权限:<uses-permission android:name="android.permission.WAKE_LOCK" />

  • Android 12+需额外申请POST_NOTIFICATIONS权限,否则前台服务无法启动。

二、将MeasureClient整合到服务中

直接在服务内初始化MeasureClient并管理其生命周期,同步两类数据后定时上报:

  1. 服务内初始化MeasureClient:
private lateinit var measureClient: MeasureClient
private var latestHeartRate: Int? = null

override fun onCreate() {
    super.onCreate()
    measureClient = MeasureClient(this)
    // 请求健康数据权限并启动监听
    measureClient.requestPermissions { granted ->
        if (granted) startHeartRateListen()
    }
}

private fun startHeartRateListen() {
    measureClient.registerHeartRateCallback { rate ->
        latestHeartRate = rate
    }
}
  1. 同步加速度与心率数据,定时上报:
    在服务中维护最新的加速度数据,用定时器每分钟触发一次API请求:
private var latestAccelData: FloatArray? = null
private val uploadHandler = Handler(Looper.getMainLooper())
private val uploadTask = object : Runnable {
    override fun run() {
        // 两类数据都存在时才上报
        latestAccelData?.let { accel ->
            latestHeartRate?.let { rate ->
                sendCombinedDataToApi(accel, rate)
            }
        }
        uploadHandler.postDelayed(this, 60 * 1000)
    }
}

override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
    uploadHandler.post(uploadTask)
    // 初始化加速度传感器监听
    initAccelerometer()
    return START_STICKY
}

private fun initAccelerometer() {
    val sensorManager = getSystemService(SENSOR_SERVICE) as SensorManager
    val accelSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
    sensorManager.registerListener(this, accelSensor, SensorManager.SENSOR_DELAY_NORMAL)
}

// 实现SensorEventListener的onSensorChanged更新加速度数据
override fun onSensorChanged(event: SensorEvent?) {
    event?.takeIf { it.sensor.type == Sensor.TYPE_ACCELEROMETER }?.let {
        latestAccelData = it.values.clone()
    }
}
  1. 销毁服务时清理资源:
override fun onDestroy() {
    super.onDestroy()
    uploadHandler.removeCallbacks(uploadTask)
    val sensorManager = getSystemService(SENSOR_SERVICE) as SensorManager
    sensorManager.unregisterListener(this)
    measureClient.unregisterHeartRateCallback()
}

三、额外注意事项

  • 确保已申请传感器权限(Android 10+需android.permission.ACTIVITY_RECOGNITION)和对应健康数据权限。
  • 前台服务+唤醒锁会增加耗电,建议提供用户开关控制后台采集,或在长时间无操作时自动停止服务。
  • 网络不稳定时可将数据缓存到本地(如Room数据库),待网络恢复后批量上传。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 11:45:58