如何在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
相关产品推荐
相关产品推荐

