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

如何在Jetpack Compose中实现Android设备摇一摇检测?

Android 简单可靠的摇一摇检测实现方案

核心思路

基于Android原生SensorManager监听加速度传感器,通过合理设置触发阈值与防抖间隔,平衡灵敏度与误触发问题,无需依赖第三方包。

实现步骤

1. 配置权限

在AndroidManifest.xml中添加传感器相关权限(适配Android 12+):

<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" />

2. 封装摇一摇检测工具类

创建ShakeDetector类,封装传感器监听与触发逻辑:

import android.content.Context
import android.hardware.Sensor
import android.hardware.SensorEvent
import android.hardware.SensorEventListener
import android.hardware.SensorManager
import kotlin.math.sqrt

class ShakeDetector(private val onShake: () -> Unit) : SensorEventListener {
    private var sensorManager: SensorManager? = null
    private var lastShakeTime: Long = 0
    // *触发阈值*:建议12-15之间,数值越大越不灵敏
    private val SHAKE_THRESHOLD = 13f
    // *防抖间隔*:避免短时间内重复触发,单位毫秒
    private val SHAKE_INTERVAL = 1000L

    fun start(context: Context) {
        sensorManager = context.getSystemService(Context.SENSOR_SERVICE) as SensorManager
        val accelerometer = sensorManager?.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
        accelerometer?.let {
            sensorManager?.registerListener(this, it, SensorManager.SENSOR_DELAY_NORMAL)
        }
    }

    fun stop() {
        sensorManager?.unregisterListener(this)
    }

    override fun onSensorChanged(event: SensorEvent?) {
        event ?: return
        if (event.sensor.type != Sensor.TYPE_ACCELEROMETER) return

        val x = event.values[0]
        val y = event.values[1]
        val z = event.values[2]

        // 计算排除重力后的合加速度
        val acceleration = sqrt((x*x + y*y + z*z)) - SensorManager.GRAVITY_EARTH

        val currentTime = System.currentTimeMillis()
        // 满足阈值且超过防抖间隔时触发回调
        if (acceleration > SHAKE_THRESHOLD && currentTime - lastShakeTime > SHAKE_INTERVAL) {
            lastShakeTime = currentTime
            onShake.invoke()
        }
    }

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

3. 在页面中使用

在Activity或Fragment中集成并管理生命周期:

class MainActivity : AppCompatActivity() {
    private lateinit var shakeDetector: ShakeDetector

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        shakeDetector = ShakeDetector {
            // 摇一摇触发后的业务逻辑
            Toast.makeText(this, "检测到摇一摇动作", Toast.LENGTH_SHORT).show()
        }
    }

    override fun onResume() {
        super.onResume()
        // 页面可见时启动监听
        shakeDetector.start(this)
    }

    override fun onPause() {
        super.onPause()
        // 页面不可见时停止监听,避免后台耗电
        shakeDetector.stop()
    }
}

优化建议

  • 阈值微调:根据实际测试场景调整SHAKE_THRESHOLD,比如在颠簸环境中可适当提高数值。
  • 防抖调整:如果需要支持连续摇一摇,可缩短SHAKE_INTERVAL的时间。
  • 权限处理:针对Android 12+,需动态申请ACTIVITY_RECOGNITION权限,避免权限缺失导致监听失败。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 15:41:09