Skip to content

Sensor

  • Coordinate system used by rotation vector sensor (device front is at Z) |246|334x319 Sensor-1779168415379.webp
class ShakeDetector(private val onShake: () -> Unit) : SensorEventListener {
private var lastUpdate: Long = 0L
private val shakeThreshold = 5f
private var lastShake: Long = 0L
override fun onAccuracyChanged(p0: Sensor?, p1: Int) {}
override fun onSensorChanged(event: SensorEvent) {
if (event.sensor.type == Sensor.TYPE_ACCELEROMETER) {
val currentTime = System.currentTimeMillis()
if ((currentTime - lastUpdate) > 100) {
val x = event.values[0]
val y = event.values[1]
val z = event.values[2]
// Log.i("Accelerometer","X: $x, Y: $y, Z: $z")
val accelerometer =
abs(sqrt(x * x + y * y + z * z) - SensorManager.GRAVITY_EARTH) // 3D畢氏定理計算總重力後去掉地心引力
if (accelerometer > shakeThreshold) {
if (currentTime - lastShake > 500) {
lastShake = currentTime
onShake()
}
}
lastUpdate = currentTime
}
}
}
}

Composable:

val context = LocalContext.current
DisposableEffect(Unit) {
val sensorManager = context.getSystemService(SensorManager::class.java)
val accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
val detector = ShakeDetector {
// fun when shake
}
sensorManager.registerListener(detector, accelerometer, SensorManager.SENSOR_DELAY_UI)
onDispose {
sensorManager.unregisterListener(detector)
}
}

Roll=atan2(x,z)×180π\text{Roll} = \operatorname{atan2}(x, z) \times \frac{180}{\pi}

Pitch=atan2(y,x2+z2)×180π\text{Pitch} = \operatorname{atan2}(-y, \sqrt{x^2 + z^2}) \times \frac{180}{\pi}

  • Math.toDegrees() convert radius to degrees
val context = LocalContext.current
var rollAngle by remember { mutableFloatStateOf(0f) }
DisposableEffect(Unit) {
val manager = context.getSystemService(SensorManager::class.java)
val sensor = manager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR)
val rotationMatrix = FloatArray(9)
val orientation = FloatArray(3)
val listener = object : SensorEventListener {
override fun onAccuracyChanged(p0: Sensor, p1: Int) {}
override fun onSensorChanged(sensor: SensorEvent) {
SensorManager.getRotationMatrixFromVector(rotationMatrix, sensor.values)
SensorManager.getOrientation(rotationMatrix, orientation)
rollAngle = Math.toDegrees(orientation[2].toDouble()).toFloat()
}
}
manager.registerListener(listener, sensor, SensorManager.SENSOR_DELAY_UI)
onDispose {
manager.unregisterListener(listener)
}
}