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

基于Android运动传感器实现后台服务启停的技术方案咨询

实现Android运动检测启停后台服务

1. 申请必要权限

在AndroidManifest.xml中添加权限声明:

<!-- 运动检测所需权限 -->
<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" />
<!-- Android 8+ 前台服务必备权限 -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<!-- Android 13+ 前台服务通知权限 -->
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />

在Activity中动态申请权限:

private val requiredPermissions = arrayOf(
    Manifest.permission.ACTIVITY_RECOGNITION,
    Manifest.permission.POST_NOTIFICATIONS
)

private fun checkPermissions() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        requestPermissions(requiredPermissions, PERMISSION_REQUEST_CODE)
    }
}

2. 实现运动检测逻辑

通过SensorManager监听加速度传感器,计算加速度变化判断运动状态:

class MotionDetectionManager(private val context: Context, private val listener: MotionListener) {
    private val sensorManager = context.getSystemService(Context.SENSOR_SERVICE) as SensorManager
    private val accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
    private val sensorListener = object : SensorEventListener {
        private var lastAcceleration = 0f
        private var isMoving = false
        private var stationaryStartTime = 0L
        // 运动判定阈值(可根据需求调整)
        private val MOTION_THRESHOLD = 2.0f
        // 静止判定时长(5秒无运动则判定为静止)
        private val STATIONARY_DURATION = 5000L

        override fun onSensorChanged(event: SensorEvent?) {
            event ?: return
            val x = event.values[0]
            val y = event.values[1]
            val z = event.values[2]
            // 计算去除重力后的合加速度
            val currentAcceleration = sqrt((x*x + y*y + z*z).toDouble()).toFloat() - SensorManager.GRAVITY_EARTH
            val accelerationChange = abs(currentAcceleration - lastAcceleration)

            if (accelerationChange > MOTION_THRESHOLD) {
                if (!isMoving) {
                    isMoving = true
                    listener.onMotionDetected()
                }
                stationaryStartTime = System.currentTimeMillis()
            } else {
                if (isMoving && System.currentTimeMillis() - stationaryStartTime > STATIONARY_DURATION) {
                    isMoving = false
                    listener.onStationaryDetected()
                }
            }
            lastAcceleration = currentAcceleration
        }

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

    fun startDetection() {
        sensorManager.registerListener(sensorListener, accelerometer, SensorManager.SENSOR_DELAY_NORMAL)
    }

    fun stopDetection() {
        sensorManager.unregisterListener(sensorListener)
    }

    interface MotionListener {
        fun onMotionDetected()
        fun onStationaryDetected()
    }
}

3. 实现前台服务

Android 8+限制后台服务,必须使用前台服务并显示通知:

class MotionBackgroundService : Service() {
    override fun onBind(intent: Intent?): IBinder? = null

    override fun onCreate() {
        super.onCreate()
        startForeground(NOTIFICATION_ID, createNotification())
    }

    private fun createNotification(): Notification {
        val channelId = "motion_service_channel"
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val channel = NotificationChannel(
                channelId,
                "运动检测服务",
                NotificationManager.IMPORTANCE_LOW
            )
            getSystemService(NotificationManager::class.java).createNotificationChannel(channel)
        }
        return NotificationCompat.Builder(this, channelId)
            .setContentTitle("运动检测中")
            .setContentText("后台服务运行中")
            .setSmallIcon(R.drawable.ic_notification)
            .build()
    }

    override fun onDestroy() {
        super.onDestroy()
        stopForeground(STOP_FOREGROUND_REMOVE)
    }

    companion object {
        const val NOTIFICATION_ID = 1001
        fun startService(context: Context) {
            val intent = Intent(context, MotionBackgroundService::class.java)
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                context.startForegroundService(intent)
            } else {
                context.startService(intent)
            }
        }

        fun stopService(context: Context) {
            val intent = Intent(context, MotionBackgroundService::class.java)
            context.stopService(intent)
        }
    }
}

在AndroidManifest.xml注册服务:

<service
    android:name=".MotionBackgroundService"
    android:foregroundServiceType="dataSync" />

4. 联动检测逻辑与服务

在Activity中初始化检测管理器,绑定回调启停服务:

class MainActivity : AppCompatActivity(), MotionDetectionManager.MotionListener {
    private lateinit var motionDetectionManager: MotionDetectionManager

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        checkPermissions()
        motionDetectionManager = MotionDetectionManager(this, this)
    }

    override fun onResume() {
        super.onResume()
        motionDetectionManager.startDetection()
    }

    override fun onPause() {
        super.onPause()
        // 若需后台持续检测,请勿注销传感器,可将检测逻辑移至前台服务中
        // motionDetectionManager.stopDetection()
    }

    override fun onMotionDetected() {
        MotionBackgroundService.startService(this)
    }

    override fun onStationaryDetected() {
        MotionBackgroundService.stopService(this)
    }

    companion object {
        const val PERMISSION_REQUEST_CODE = 100
    }
}

关键注意事项

  • 后台持续检测:若需App退至后台仍能检测运动,建议将传感器监听逻辑放入前台服务,避免Activity销毁后检测中断。
  • 电量优化:可调整SensorManager.SENSOR_DELAY降低采样率(如SENSOR_DELAY_UI),或结合JobScheduler限定检测时段。
  • 系统限制适配:Android 12+需正确声明前台服务类型,避免被系统强制停止。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 00:35:24