Skip to content

Commit

Permalink
Merge branch 'development' into ab_game_rotation_vector_support
Browse files Browse the repository at this point in the history
  • Loading branch information
aditya-bhawsar-mm committed Apr 3, 2023
2 parents 879d7b8 + 26171a4 commit e974e8d
Show file tree
Hide file tree
Showing 23 changed files with 687 additions and 19 deletions.
39 changes: 21 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ Accessing sensor data of your Android devices just became quick and easy ⚡️

This library provides a convenience wrapper over the [Sensor APIs](https://developer.android.com/guide/topics/sensors/sensors_overview) for Android to be used with Jetpack Compose.

## Demo ❤️
![Screen Recording 2023-04-03 at 1 00 08 PM](https://user-images.githubusercontent.com/89389061/229441943-6339d18f-c704-4d92-9fe8-28c2fd94fdeb.gif)

## WIP 🚧
This library is a work-in-progress and is subject to major changes. Our team is working hard to get it stable as soon as possible. Thank you for your patience 🌺

Expand Down Expand Up @@ -81,31 +84,31 @@ Pressure | ✅️ | rememberPressureSensorState()
Proximity | ✅️️ | rememberProximitySensorState()
Gravity | ✅️ | rememberGravitySensorState()
Linear Acceleration | ✅️ | rememberLinearAccelerationSensorState()
Rotation Vector | ⚠️ | WIP
Rotation Vector | ✅️️ | rememberRotationVectorSensorState()
Relative Humidity | ⚠️ | WIP
Ambient Temperature | ️ | WIP
Magnetic Field (Uncalibrated) | ⚠️ | WIP
Ambient Temperature | ️ | rememberAmbientTemperatureSensorState()
Magnetic Field (Uncalibrated) | | N/A
GameRotation Vector | ✅️ | rememberGameRotationVectorSensorState()
Gyroscope (Uncalibrated) | ⚠️ | WIP
Significant Motion | ⚠️ | WIP
Step Detector | ️ | WIP
Significant Motion | | N/A
Step Detector | ️ | rememberStepDetectorSensorState()
Step Counter | ✅️ | rememberStepCounterSensorState()
Geomagnetic Rotation Vector | ⚠️ | WIP
Heart Rate | ️ | WIP
Pose6DOF | ⚠️ | WIP
Stationary Detect | ⚠️ | WIP
Motion Detect | ⚠️ | WIP
Heart Beat | ⚠️ | WIP
Low Latency Off-Body Detect | ⚠️ | WIP
Geomagnetic Rotation Vector | ✅️️ | rememberGeomagneticRotationVectorSensorState()
Heart Rate | ️ | rememberHeartRateSensorState()
Pose6DOF | | N/A
Stationary Detect | | N/A
Motion Detect | | N/A
Heart Beat | | N/A
Low Latency Off-Body Detect | | N/A
Accelerometer (Uncalibrated) | ⚠️ | WIP
Hinge Angle | ⚠️ | WIP
Head Tracker | ⚠️ | WIP
Accelerometer Limited Axes | ⚠️ | WIP
Gyroscope Limited Axes | ⚠️ | WIP
Accelerometer Limited Axes (Uncalibrated) | ⚠️ | WIP
Gyroscope Limited Axes (Uncalibrated) | ⚠️ | WIP
Head Tracker | | N/A
Accelerometer Limited Axes | | N/A
Gyroscope Limited Axes | | N/A
Accelerometer Limited Axes (Uncalibrated) | | N/A
Gyroscope Limited Axes (Uncalibrated) | | N/A
Heading | ⚠️ | WIP
All | ⚠️ | WIP
All | | N/A

## License 🔖
```
Expand Down
6 changes: 5 additions & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
buildscript {
val compose_version by extra("1.4.0")
val wear_compose_version by extra("1.0.0")
}
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
id("com.android.application") version "7.4.2" apply false
id("com.android.library") version "7.4.2" apply false
id("org.jetbrains.kotlin.android") version "1.8.10" apply false
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
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

/**
* Measures the ambient room temperature in degrees Celsius (°C)
* @param temperature Ambient temperature as determined by sensor (in °C).
* @param isAvailable Whether the current device has an ambient temperature sensor. Defaults to false.
* @param accuracy Accuracy factor of the ambient temperature sensor. Defaults to 0.
*/
@Immutable
class AmbientTemperatureSensorState internal constructor(
val temperature: Float = 0f,
val isAvailable: Boolean = false,
val accuracy: Int = 0
) {
override fun toString(): String {
return "AmbientTemperatureSensorState(temperature=$temperature, " +
"isAvailable=$isAvailable, accuracy=$accuracy)"
}

override fun equals(other: Any?): Boolean {
if (this === other) return true
other as AmbientTemperatureSensorState

if (temperature != other.temperature) return false
if (isAvailable != other.isAvailable) return false
if (accuracy != other.accuracy) return false
return true
}

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


/**
* Creates and [remember]s instance of [AmbientTemperatureSensorState].
* @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 rememberAmbientTemperatureSensorState(
sensorDelay: SensorDelay = SensorDelay.Normal,
onError: (throwable: Throwable) -> Unit = {},
): AmbientTemperatureSensorState {
val sensorState = rememberSensorState(
sensorType = SensorType.AmbientTemperature,
sensorDelay = sensorDelay,
onError = onError,
)

val ambientTemperatureSensorState = remember { mutableStateOf(AmbientTemperatureSensorState()) }

LaunchedEffect(key1 = sensorState, block = {
val sensorStateValues = sensorState.data
if (sensorStateValues.isNotEmpty()) {
ambientTemperatureSensorState.value = AmbientTemperatureSensorState(
temperature = sensorStateValues[0],
isAvailable = sensorState.isAvailable,
accuracy = sensorState.accuracy
)
}
})

return ambientTemperatureSensorState.value
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
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

/**
* Measures the orientation of a device by providing the three elements of the device's rotation vector.
* @param vectorX Rotation vector component along the x axis.
* @param vectorY Rotation vector component along the y axis.
* @param vectorZ Rotation vector component along the z axis.
* @param isAvailable Whether the current device has a geomagnetic rotation vector sensor. Defaults to false.
* @param accuracy Accuracy factor of the geomagnetic rotation vector sensor. Defaults to 0.
*/
@Immutable
class GeomagneticRotationVectorSensorState internal constructor(
val vectorX: Float = 0f,
val vectorY: Float = 0f,
val vectorZ: Float = 0f,
val isAvailable: Boolean = false,
val accuracy: Int = 0
) {
override fun toString(): String {
return "GeomagneticRotationVectorSensorState(vectorX=$vectorX, " +
"vectorY=$vectorY, vectorZ=$vectorZ, isAvailable=$isAvailable, " +
"accuracy=$accuracy)"
}

override fun equals(other: Any?): Boolean {
if (this === other) return true
other as GeomagneticRotationVectorSensorState

if (vectorX != other.vectorX) return false
if (vectorY != other.vectorY) return false
if (vectorZ != other.vectorZ) return false
if (isAvailable != other.isAvailable) return false
if (accuracy != other.accuracy) return false

return true
}

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

/**
* Creates and [remember]s instance of [GeomagneticRotationVectorSensorState].
* @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 rememberGeomagneticRotationVectorSensorState(
sensorDelay: SensorDelay = SensorDelay.Normal,
onError: (throwable: Throwable) -> Unit = {},
): GeomagneticRotationVectorSensorState {
val sensorState = rememberSensorState(
sensorType = SensorType.GeomagneticRotationVector,
sensorDelay = sensorDelay,
onError = onError,
)

val geomagneticRotationVectorSensorState =
remember { mutableStateOf(GeomagneticRotationVectorSensorState()) }

LaunchedEffect(key1 = sensorState, block = {
val sensorStateValues = sensorState.data
if (sensorStateValues.isNotEmpty()) {
geomagneticRotationVectorSensorState.value = GeomagneticRotationVectorSensorState(
vectorX = sensorStateValues[0],
vectorY = sensorStateValues[1],
vectorZ = sensorStateValues[2],
isAvailable = sensorState.isAvailable,
accuracy = sensorState.accuracy
)
}
})

return geomagneticRotationVectorSensorState.value
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
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 HeartRate sensor provides the speed at which the current user's heart beats per minute (denoted by BPM).
* @param heartRate Indicates the current heart rate (in BPM).
* @param isAvailable Whether the current device has an heart rate sensor. Defaults to false.
* @param accuracy Accuracy factor of the heart rate sensor. Defaults to 0.
*/
@Immutable
class HeartRateSensorState internal constructor(
val heartRate: Float = 0f,
val isAvailable: Boolean = false,
val accuracy: Int = 0,
) {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is HeartRateSensorState) return false

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

return true
}

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

override fun toString(): String {
return "HeartRateSensorState(heartRate=$heartRate isAvailable=$isAvailable, accuracy=$accuracy)"
}
}

/**
* Creates and [remember]s an instance of [HeartRateSensorState].
* @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 rememberHeartRateSensorState(
sensorDelay: SensorDelay = SensorDelay.Normal,
onError: (throwable: Throwable) -> Unit = {},
): HeartRateSensorState {
val sensorState = rememberSensorState(
sensorType = SensorType.HeartRate,
sensorDelay = sensorDelay,
onError = onError,
)
val heartRateSensorState = remember { mutableStateOf(HeartRateSensorState()) }

LaunchedEffect(
key1 = sensorState,
block = {
val sensorStateValues = sensorState.data
if (sensorStateValues.isNotEmpty()) {
heartRateSensorState.value = HeartRateSensorState(
heartRate = sensorStateValues[0],
isAvailable = sensorState.isAvailable,
accuracy = sensorState.accuracy,
)
}
},
)

return heartRateSensorState.value
}

0 comments on commit e974e8d

Please sign in to comment.