Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Step Detector Sensor Implementation #16

Merged
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ Magnetic Field (Uncalibrated) | ⚠️ | WIP
GameRotation Vector | ⚠️ | WIP
Gyroscope (Uncalibrated) | ⚠️ | WIP
Significant Motion | ⚠️ | WIP
Step Detector | ️ | WIP
Step Detector | ️ | rememberStepDetectorSensorState
swap-musale marked this conversation as resolved.
Show resolved Hide resolved
Step Counter | ✅️ | rememberStepCounterSensorState()
Geomagnetic Rotation Vector | ⚠️ | WIP
Heart Rate | ⚠️ | WIP
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package com.mutualmobile.composesensors

import androidx.compose.runtime.Composable
import androidx.compose.runtime.Immutable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember

/**
* The step detector sensor triggers an event each time the user takes a step.
* The latency is expected to be below 2 seconds.
* @param steps Number of steps taken by the user.
* @param isAvailable Whether the current device has an step detector sensor. Defaults to false.
* @param accuracy Accuracy factor of the accelerometer sensor. Defaults to 0.
*/
@Immutable
class StepDetectorSensorState internal constructor(
val steps: Float = 0f,
swap-musale marked this conversation as resolved.
Show resolved Hide resolved
val isAvailable: Boolean = false,
val accuracy: Int = 0,
) {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is StepDetectorSensorState) return false

if (steps != other.steps) return false
if (isAvailable != other.isAvailable) return false
if (accuracy != other.accuracy) return false

return true
}

override fun hashCode(): Int {
var result = steps.hashCode()
result = 31 * result + isAvailable.hashCode()
result = 31 * result + accuracy.hashCode()
return result
}

override fun toString(): String {
return "StepDetectorSensorState(stepCount=$steps isAvailable=$isAvailable, accuracy=$accuracy)"
}
}

/**
* Creates and [remember]s an instance of [StepDetectorSensorState].
* @param sensorDelay The rate at which the raw sensor data should be received.
* Defaults to [SensorDelay.Normal].
* @param onError Callback invoked on every error state.
*/
@Composable
fun rememberStepDetectorSensorState(
sensorDelay: SensorDelay = SensorDelay.Normal,
onError: (throwable: Throwable) -> Unit = {},
): StepDetectorSensorState {
val sensorState = rememberSensorState(
sensorType = SensorType.StepDetector,
sensorDelay = sensorDelay,
onError = onError,
)
val stepDetectorSensorState = remember { mutableStateOf(StepDetectorSensorState()) }

LaunchedEffect(
key1 = sensorState,
block = {
val sensorStateValues = sensorState.data
if (sensorStateValues.isNotEmpty()) {
stepDetectorSensorState.value = StepDetectorSensorState(
steps = sensorStateValues[0],
isAvailable = sensorState.isAvailable,
accuracy = sensorState.accuracy,
)
}
},
)

return stepDetectorSensorState.value
}