From 47dbe1c581a621358a32f75fe1eb96b0c6fd79ab Mon Sep 17 00:00:00 2001 From: Swapnil Musale Date: Thu, 30 Mar 2023 13:02:54 +0530 Subject: [PATCH 01/17] Hear Rate Sensor Implementation --- build.gradle.kts | 6 +- .../composesensors/HeartRateSensorState.kt | 77 ++++++++++++++++++ settings.gradle.kts | 1 + wearsample/.gitignore | 1 + wearsample/build.gradle.kts | 66 +++++++++++++++ wearsample/proguard-rules.pro | 21 +++++ wearsample/src/main/AndroidManifest.xml | 39 +++++++++ .../wearsample/presentation/MainActivity.kt | 40 +++++++++ .../wearsample/presentation/theme/Color.kt | 21 +++++ .../wearsample/presentation/theme/Theme.kt | 17 ++++ .../wearsample/presentation/theme/Type.kt | 28 +++++++ .../src/main/res/mipmap-hdpi/ic_launcher.webp | Bin 0 -> 1404 bytes .../src/main/res/mipmap-mdpi/ic_launcher.webp | Bin 0 -> 982 bytes .../main/res/mipmap-xhdpi/ic_launcher.webp | Bin 0 -> 1900 bytes .../main/res/mipmap-xxhdpi/ic_launcher.webp | Bin 0 -> 2884 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.webp | Bin 0 -> 3844 bytes .../src/main/res/values-round/strings.xml | 3 + wearsample/src/main/res/values/strings.xml | 8 ++ 18 files changed, 327 insertions(+), 1 deletion(-) create mode 100644 composesensors/src/main/java/com/mutualmobile/composesensors/HeartRateSensorState.kt create mode 100644 wearsample/.gitignore create mode 100644 wearsample/build.gradle.kts create mode 100644 wearsample/proguard-rules.pro create mode 100644 wearsample/src/main/AndroidManifest.xml create mode 100644 wearsample/src/main/java/com/compose/wearsample/presentation/MainActivity.kt create mode 100644 wearsample/src/main/java/com/compose/wearsample/presentation/theme/Color.kt create mode 100644 wearsample/src/main/java/com/compose/wearsample/presentation/theme/Theme.kt create mode 100644 wearsample/src/main/java/com/compose/wearsample/presentation/theme/Type.kt create mode 100644 wearsample/src/main/res/mipmap-hdpi/ic_launcher.webp create mode 100644 wearsample/src/main/res/mipmap-mdpi/ic_launcher.webp create mode 100644 wearsample/src/main/res/mipmap-xhdpi/ic_launcher.webp create mode 100644 wearsample/src/main/res/mipmap-xxhdpi/ic_launcher.webp create mode 100644 wearsample/src/main/res/mipmap-xxxhdpi/ic_launcher.webp create mode 100644 wearsample/src/main/res/values-round/strings.xml create mode 100644 wearsample/src/main/res/values/strings.xml diff --git a/build.gradle.kts b/build.gradle.kts index 8b52e54..b31dc84 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -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 -} \ No newline at end of file +} diff --git a/composesensors/src/main/java/com/mutualmobile/composesensors/HeartRateSensorState.kt b/composesensors/src/main/java/com/mutualmobile/composesensors/HeartRateSensorState.kt new file mode 100644 index 0000000..08ce33a --- /dev/null +++ b/composesensors/src/main/java/com/mutualmobile/composesensors/HeartRateSensorState.kt @@ -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 provided value is heart rate in beats per minute + * @param heartRate This value is indicate current heart rate. + * @param isAvailable Whether the current device has an accelerometer sensor. Defaults to false. + * @param accuracy Accuracy factor of the heart rate sensor. Defaults to 0. + */ +@Immutable +class HeartRateSensorState internal constructor( + val heartRate: Int = 0, + 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].toInt(), + isAvailable = sensorState.isAvailable, + accuracy = sensorState.accuracy, + ) + } + }, + ) + + return heartRateSensorState.value +} diff --git a/settings.gradle.kts b/settings.gradle.kts index 6205a95..06e7d8d 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -17,3 +17,4 @@ dependencyResolutionManagement { rootProject.name = "ComposeSensors" include(":sample") include(":composesensors") +include(":wearsample") diff --git a/wearsample/.gitignore b/wearsample/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/wearsample/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/wearsample/build.gradle.kts b/wearsample/build.gradle.kts new file mode 100644 index 0000000..2317312 --- /dev/null +++ b/wearsample/build.gradle.kts @@ -0,0 +1,66 @@ +plugins { + id("com.android.application") + id("org.jetbrains.kotlin.android") +} + +android { + namespace = "com.compose.wearsample" + compileSdk = 33 + + defaultConfig { + applicationId = "com.compose.wearsample" + minSdk = 26 + targetSdk = 33 + versionCode = 1 + versionName = "1.0" + vectorDrawables { + useSupportLibrary = true + } + } + + buildTypes { + release { + isMinifyEnabled = false + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro", + ) + } + } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + } + kotlinOptions { + jvmTarget = "1.8" + } + buildFeatures { + compose = true + } + composeOptions { + kotlinCompilerExtensionVersion = "1.4.4" + } + packagingOptions { + resources { + excludes += "/META-INF/{AL2.0,LGPL2.1}" + } + } +} + +dependencies { + + implementation(project(mapOf("path" to ":composesensors"))) + implementation("androidx.core:core-ktx:1.9.0") + implementation("com.google.android.gms:play-services-wearable:18.0.0") + implementation("androidx.percentlayout:percentlayout:1.0.0") + implementation("androidx.legacy:legacy-support-v4:1.0.0") + implementation("androidx.compose.ui:ui:${rootProject.extra["compose_version"]}") + implementation("androidx.wear.compose:compose-material:${rootProject.extra["wear_compose_version"]}") + implementation("androidx.wear.compose:compose-foundation:${rootProject.extra["wear_compose_version"]}") + implementation("androidx.compose.ui:ui-tooling-preview:${rootProject.extra["compose_version"]}") + implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.6.1") + implementation("androidx.activity:activity-compose:1.7.0") + androidTestImplementation("androidx.compose.ui:ui-test-junit4:${rootProject.extra["compose_version"]}") + debugImplementation("androidx.compose.ui:ui-tooling:${rootProject.extra["compose_version"]}") + debugImplementation("androidx.compose.ui:ui-test-manifest:${rootProject.extra["compose_version"]}") +} diff --git a/wearsample/proguard-rules.pro b/wearsample/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/wearsample/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/wearsample/src/main/AndroidManifest.xml b/wearsample/src/main/AndroidManifest.xml new file mode 100644 index 0000000..57d790e --- /dev/null +++ b/wearsample/src/main/AndroidManifest.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/wearsample/src/main/java/com/compose/wearsample/presentation/MainActivity.kt b/wearsample/src/main/java/com/compose/wearsample/presentation/MainActivity.kt new file mode 100644 index 0000000..0d8974e --- /dev/null +++ b/wearsample/src/main/java/com/compose/wearsample/presentation/MainActivity.kt @@ -0,0 +1,40 @@ +/* While this template provides a good starting point for using Wear Compose, you can always + * take a look at https://github.com/android/wear-os-samples/tree/main/ComposeStarter and + * https://github.com/android/wear-os-samples/tree/main/ComposeAdvanced to find the most up to date + * changes to the libraries and their usages. + */ + +package com.compose.wearsample.presentation + +import android.os.Bundle +import androidx.activity.ComponentActivity +import androidx.activity.compose.setContent +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.wear.compose.material.MaterialTheme +import androidx.wear.compose.material.Text +import com.compose.wearsample.presentation.theme.ComposeSensorsTheme +import com.mutualmobile.composesensors.rememberHeartRateSensorState + +class MainActivity : ComponentActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContent { + ComposeSensorsTheme { + Box( + modifier = Modifier + .fillMaxSize() + .background(MaterialTheme.colors.background), + contentAlignment = Alignment.Center, + ) { + // BODY_SENSORS permission must be granted before accessing sensor + val heartRateSensorState = rememberHeartRateSensorState() + Text(text = "Heart Rate : ${heartRateSensorState.heartRate}") + } + } + } + } +} diff --git a/wearsample/src/main/java/com/compose/wearsample/presentation/theme/Color.kt b/wearsample/src/main/java/com/compose/wearsample/presentation/theme/Color.kt new file mode 100644 index 0000000..d6b144a --- /dev/null +++ b/wearsample/src/main/java/com/compose/wearsample/presentation/theme/Color.kt @@ -0,0 +1,21 @@ +package com.compose.wearsample.presentation.theme + +import androidx.compose.ui.graphics.Color +import androidx.wear.compose.material.Colors + +val Purple200 = Color(0xFFBB86FC) +val Purple500 = Color(0xFF6200EE) +val Purple700 = Color(0xFF3700B3) +val Teal200 = Color(0xFF03DAC5) +val Red400 = Color(0xFFCF6679) + +internal val wearColorPalette: Colors = Colors( + primary = Purple200, + primaryVariant = Purple700, + secondary = Teal200, + secondaryVariant = Teal200, + error = Red400, + onPrimary = Color.Black, + onSecondary = Color.Black, + onError = Color.Black, +) diff --git a/wearsample/src/main/java/com/compose/wearsample/presentation/theme/Theme.kt b/wearsample/src/main/java/com/compose/wearsample/presentation/theme/Theme.kt new file mode 100644 index 0000000..0811f6a --- /dev/null +++ b/wearsample/src/main/java/com/compose/wearsample/presentation/theme/Theme.kt @@ -0,0 +1,17 @@ +package com.compose.wearsample.presentation.theme + +import androidx.compose.runtime.Composable +import androidx.wear.compose.material.MaterialTheme + +@Composable +fun ComposeSensorsTheme( + content: @Composable () -> Unit, +) { + MaterialTheme( + colors = wearColorPalette, + typography = Typography, + // For shapes, we generally recommend using the default Material Wear shapes which are + // optimized for round and non-round devices. + content = content, + ) +} diff --git a/wearsample/src/main/java/com/compose/wearsample/presentation/theme/Type.kt b/wearsample/src/main/java/com/compose/wearsample/presentation/theme/Type.kt new file mode 100644 index 0000000..d31b989 --- /dev/null +++ b/wearsample/src/main/java/com/compose/wearsample/presentation/theme/Type.kt @@ -0,0 +1,28 @@ +package com.compose.wearsample.presentation.theme + +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.sp +import androidx.wear.compose.material.Typography + +// Set of Material typography styles to start with +val Typography = Typography( + body1 = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Normal, + fontSize = 16.sp, + ), + /* Other default text styles to override + button = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.W500, + fontSize = 14.sp + ), + caption = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Normal, + fontSize = 12.sp + ) + */ +) diff --git a/wearsample/src/main/res/mipmap-hdpi/ic_launcher.webp b/wearsample/src/main/res/mipmap-hdpi/ic_launcher.webp new file mode 100644 index 0000000000000000000000000000000000000000..c209e78ecd372343283f4157dcfd918ec5165bb3 GIT binary patch literal 1404 zcmV-?1%vuhNk&F=1pok7MM6+kP&il$0000G0000-002h-06|PpNX!5L00Dqw+t%{r zzW2vH!KF=w&cMnnN@{whkTw+#mAh0SV?YL=)3MimFYCWp#fpdtz~8$hD5VPuQgtcN zXl<@<#Cme5f5yr2h%@8TWh?)bSK`O z^Z@d={gn7J{iyxL_y_%J|L>ep{dUxUP8a{byupH&!UNR*OutO~0{*T4q5R6@ApLF! z5{w?Z150gC7#>(VHFJZ-^6O@PYp{t!jH(_Z*nzTK4 zkc{fLE4Q3|mA2`CWQ3{8;gxGizgM!zccbdQoOLZc8hThi-IhN90RFT|zlxh3Ty&VG z?Fe{#9RrRnxzsu|Lg2ddugg7k%>0JeD+{XZ7>Z~{=|M+sh1MF7~ zz>To~`~LVQe1nNoR-gEzkpe{Ak^7{{ZBk2i_<+`Bq<^GB!RYG+z)h;Y3+<{zlMUYd zrd*W4w&jZ0%kBuDZ1EW&KLpyR7r2=}fF2%0VwHM4pUs}ZI2egi#DRMYZPek*^H9YK zay4Iy3WXFG(F14xYsoDA|KXgGc5%2DhmQ1gFCkrgHBm!lXG8I5h*uf{rn48Z!_@ z4Bk6TJAB2CKYqPjiX&mWoW>OPFGd$wqroa($ne7EUK;#3VYkXaew%Kh^3OrMhtjYN?XEoY`tRPQsAkH-DSL^QqyN0>^ zmC>{#F14jz4GeW{pJoRpLFa_*GI{?T93^rX7SPQgT@LbLqpNA}<@2wH;q493)G=1Y z#-sCiRNX~qf3KgiFzB3I>4Z%AfS(3$`-aMIBU+6?gbgDb!)L~A)je+;fR0jWLL-Fu z4)P{c7{B4Hp91&%??2$v9iRSFnuckHUm}or9seH6 z>%NbT+5*@L5(I9j@06@(!{ZI?U0=pKn8uwIg&L{JV14+8s2hnvbRrU|hZCd}IJu7*;;ECgO%8_*W Kmw_-CKmY()leWbG literal 0 HcmV?d00001 diff --git a/wearsample/src/main/res/mipmap-mdpi/ic_launcher.webp b/wearsample/src/main/res/mipmap-mdpi/ic_launcher.webp new file mode 100644 index 0000000000000000000000000000000000000000..4f0f1d64e58ba64d180ce43ee13bf9a17835fbca GIT binary patch literal 982 zcmV;{11bDcNk&G_0{{S5MM6+kP&il$0000G0000l001ul06|PpNU8t;00Dqo+t#w^ z^1csucXz7-Qrhzl9HuHB%l>&>1tG2^vb*E&k^T3$FG1eQZ51g$uv4V+kI`0<^1Z@N zk?Jjh$olyC%l>)Xq;7!>{iBj&BjJ`P&$fsCfpve_epJOBkTF?nu-B7D!hO=2ZR}

C%4 zc_9eOXvPbC4kzU8YowIA8cW~Uv|eB&yYwAObSwL2vY~UYI7NXPvf3b+c^?wcs~_t{ ze_m66-0)^{JdOMKPwjpQ@Sna!*?$wTZ~su*tNv7o!gXT!GRgivP}ec?5>l1!7<(rT zds|8x(qGc673zrvYIz;J23FG{9nHMnAuP}NpAED^laz3mAN1sy+NXK)!6v1FxQ;lh zOBLA>$~P3r4b*NcqR;y6pwyhZ3_PiDb|%n1gGjl3ZU}ujInlP{eks-#oA6>rh&g+!f`hv#_%JrgYPu z(U^&XLW^QX7F9Z*SRPpQl{B%x)_AMp^}_v~?j7 zapvHMKxSf*Mtyx8I}-<*UGn3)oHd(nn=)BZ`d$lDBwq_GL($_TPaS{UeevT(AJ`p0 z9%+hQb6z)U9qjbuXjg|dExCLjpS8$VKQ55VsIC%@{N5t{NsW)=hNGI`J=x97_kbz@ E0Of=7!To6o6Gy zRq6Ap5(_{XLdXcL-MzlN`ugSdZY_`jXhcENAu)N_0?GhF))9R;E`!bo9p?g?SRgw_ zEXHhFG$0{qYOqhdX<(wE4N@es3VIo$%il%6xP9gjiBri+2pI6aY4 zJbgh-Ud|V%3O!IcHKQx1FQH(_*TK;1>FQWbt^$K1zNn^cczkBs=QHCYZ8b&l!UV{K z{L0$KCf_&KR^}&2Fe|L&?1I7~pBENnCtCuH3sjcx6$c zwqkNkru);ie``q+_QI;IYLD9OV0ZxkuyBz|5<$1BH|vtey$> z5oto4=l-R-Aaq`Dk0}o9N0VrkqW_#;!u{!bJLDq%0092{Ghe=F;(kn} z+sQ@1=UlX30+2nWjkL$B^b!H2^QYO@iFc0{(-~yXj2TWz?VG{v`Jg zg}WyYnwGgn>{HFaG7E~pt=)sOO}*yd(UU-D(E&x{xKEl6OcU?pl)K%#U$dn1mDF19 zSw@l8G!GNFB3c3VVK0?uyqN&utT-D5%NM4g-3@Sii9tSXKtwce~uF zS&Jn746EW^wV~8zdQ1XC28~kXu8+Yo9p!<8h&(Q({J*4DBglPdpe4M_mD8AguZFn~ ztiuO~{6Bx?SfO~_ZV(GIboeR9~hAym{{fV|VM=77MxDrbW6`ujX z<3HF(>Zr;#*uCvC*bpoSr~C$h?_%nXps@A)=l_;({Fo#6Y1+Zv`!T5HB+)#^-Ud_; zBwftPN=d8Vx)*O1Mj+0oO=mZ+NVH*ptNDC-&zZ7Hwho6UQ#l-yNvc0Cm+2$$6YUk2D2t#vdZX-u3>-Be1u9gtTBiMB^xwWQ_rgvGpZ6(C@e23c!^K=>ai-Rqu zhqT`ZQof;9Bu!AD(i^PCbYV%yha9zuoKMp`U^z;3!+&d@Hud&_iy!O-$b9ZLcSRh? z)R|826w}TU!J#X6P%@Zh=La$I6zXa#h!B;{qfug}O%z@K{EZECu6zl)7CiNi%xti0 zB{OKfAj83~iJvmpTU|&q1^?^cIMn2RQ?jeSB95l}{DrEPTW{_gmU_pqTc)h@4T>~& zluq3)GM=xa(#^VU5}@FNqpc$?#SbVsX!~RH*5p0p@w z;~v{QMX0^bFT1!cXGM8K9FP+=9~-d~#TK#ZE{4umGT=;dfvWi?rYj;^l_Zxywze`W z^Cr{55U@*BalS}K%Czii_80e0#0#Zkhlij4-~I@}`-JFJ7$5{>LnoJSs??J8kWVl6|8A}RCGAu9^rAsfCE=2}tHwl93t0C?#+jMpvr7O3`2=tr{Hg$=HlnjVG^ewm|Js0J*kfPa6*GhtB>`fN!m#9J(sU!?(OSfzY*zS(FJ<-Vb zfAIg+`U)YaXv#sY(c--|X zEB+TVyZ%Ie4L$gi#Fc++`h6%vzsS$pjz9aLt+ZL(g;n$Dzy5=m=_TV(3H8^C{r0xd zp#a%}ht55dOq?yhwYPrtp-m1xXp;4X;)NhxxUpgP%XTLmO zcjaFva^}dP3$&sfFTIR_jC=2pHh9kpI@2(6V*GQo7Ws)`j)hd+tr@P~gR*2gO@+1? zG<`_tB+LJuF|SZ9tIec;h%}}6WClT`L>HSW?E{Hp1h^+mlbf_$9zA>!ug>NALJsO{ mU%z=YwVD?}XMya)Bp;vlyE5&E_6!fzx9pwrdz474!~g(M6R?N? literal 0 HcmV?d00001 diff --git a/wearsample/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/wearsample/src/main/res/mipmap-xxhdpi/ic_launcher.webp new file mode 100644 index 0000000000000000000000000000000000000000..28d4b77f9f036a47549d47db79c16788749dca10 GIT binary patch literal 2884 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 + From the Round world,\nHello, %1$s! + \ No newline at end of file diff --git a/wearsample/src/main/res/values/strings.xml b/wearsample/src/main/res/values/strings.xml new file mode 100644 index 0000000..a09c157 --- /dev/null +++ b/wearsample/src/main/res/values/strings.xml @@ -0,0 +1,8 @@ + + Wear Sample + + From the Square world,\nHello, %1$s! + \ No newline at end of file From 1a5bb338bcab97d8da4171802933bae44fe665f8 Mon Sep 17 00:00:00 2001 From: Swapnil Musale Date: Thu, 30 Mar 2023 16:01:57 +0530 Subject: [PATCH 02/17] Hear Rate Sensor Implementation --- README.md | 2 +- .../composesensors/HeartRateSensorState.kt | 6 +++--- settings.gradle.kts | 2 +- {wearsample => wearablesample}/.gitignore | 0 {wearsample => wearablesample}/build.gradle.kts | 4 ++-- {wearsample => wearablesample}/proguard-rules.pro | 0 .../src/main/AndroidManifest.xml | 0 .../wearablesample}/presentation/MainActivity.kt | 4 ++-- .../wearablesample}/presentation/theme/Color.kt | 2 +- .../wearablesample}/presentation/theme/Theme.kt | 2 +- .../wearablesample}/presentation/theme/Type.kt | 2 +- .../src/main/res/mipmap-hdpi/ic_launcher.webp | Bin .../src/main/res/mipmap-mdpi/ic_launcher.webp | Bin .../src/main/res/mipmap-xhdpi/ic_launcher.webp | Bin .../src/main/res/mipmap-xxhdpi/ic_launcher.webp | Bin .../src/main/res/mipmap-xxxhdpi/ic_launcher.webp | Bin .../src/main/res/values-round/strings.xml | 0 .../src/main/res/values/strings.xml | 0 18 files changed, 12 insertions(+), 12 deletions(-) rename {wearsample => wearablesample}/.gitignore (100%) rename {wearsample => wearablesample}/build.gradle.kts (95%) rename {wearsample => wearablesample}/proguard-rules.pro (100%) rename {wearsample => wearablesample}/src/main/AndroidManifest.xml (100%) rename {wearsample/src/main/java/com/compose/wearsample => wearablesample/src/main/java/com/mutualmobile/wearablesample}/presentation/MainActivity.kt (92%) rename {wearsample/src/main/java/com/compose/wearsample => wearablesample/src/main/java/com/mutualmobile/wearablesample}/presentation/theme/Color.kt (89%) rename {wearsample/src/main/java/com/compose/wearsample => wearablesample/src/main/java/com/mutualmobile/wearablesample}/presentation/theme/Theme.kt (88%) rename {wearsample/src/main/java/com/compose/wearsample => wearablesample/src/main/java/com/mutualmobile/wearablesample}/presentation/theme/Type.kt (92%) rename {wearsample => wearablesample}/src/main/res/mipmap-hdpi/ic_launcher.webp (100%) rename {wearsample => wearablesample}/src/main/res/mipmap-mdpi/ic_launcher.webp (100%) rename {wearsample => wearablesample}/src/main/res/mipmap-xhdpi/ic_launcher.webp (100%) rename {wearsample => wearablesample}/src/main/res/mipmap-xxhdpi/ic_launcher.webp (100%) rename {wearsample => wearablesample}/src/main/res/mipmap-xxxhdpi/ic_launcher.webp (100%) rename {wearsample => wearablesample}/src/main/res/values-round/strings.xml (100%) rename {wearsample => wearablesample}/src/main/res/values/strings.xml (100%) diff --git a/README.md b/README.md index 002df52..433ea56 100644 --- a/README.md +++ b/README.md @@ -91,7 +91,7 @@ Significant Motion | ⚠️ | WIP Step Detector | ⚠️ | WIP Step Counter | ✅️ | rememberStepCounterSensorState() Geomagnetic Rotation Vector | ⚠️ | WIP -Heart Rate | ⚠️ | WIP +Heart Rate | ✅️ | rememberHeartRateSensorState Pose6DOF | ⚠️ | WIP Stationary Detect | ⚠️ | WIP Motion Detect | ⚠️ | WIP diff --git a/composesensors/src/main/java/com/mutualmobile/composesensors/HeartRateSensorState.kt b/composesensors/src/main/java/com/mutualmobile/composesensors/HeartRateSensorState.kt index 08ce33a..feff307 100644 --- a/composesensors/src/main/java/com/mutualmobile/composesensors/HeartRateSensorState.kt +++ b/composesensors/src/main/java/com/mutualmobile/composesensors/HeartRateSensorState.kt @@ -7,9 +7,9 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember /** - * The HeartRate sensor provided value is heart rate in beats per minute - * @param heartRate This value is indicate current heart rate. - * @param isAvailable Whether the current device has an accelerometer sensor. Defaults to false. + * 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 diff --git a/settings.gradle.kts b/settings.gradle.kts index 06e7d8d..5db7e5b 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -17,4 +17,4 @@ dependencyResolutionManagement { rootProject.name = "ComposeSensors" include(":sample") include(":composesensors") -include(":wearsample") +include(":wearablesample") diff --git a/wearsample/.gitignore b/wearablesample/.gitignore similarity index 100% rename from wearsample/.gitignore rename to wearablesample/.gitignore diff --git a/wearsample/build.gradle.kts b/wearablesample/build.gradle.kts similarity index 95% rename from wearsample/build.gradle.kts rename to wearablesample/build.gradle.kts index 2317312..233abbc 100644 --- a/wearsample/build.gradle.kts +++ b/wearablesample/build.gradle.kts @@ -4,11 +4,11 @@ plugins { } android { - namespace = "com.compose.wearsample" + namespace = "com.mutualmobile.wearablesample" compileSdk = 33 defaultConfig { - applicationId = "com.compose.wearsample" + applicationId = "com.mutualmobile.wearablesample" minSdk = 26 targetSdk = 33 versionCode = 1 diff --git a/wearsample/proguard-rules.pro b/wearablesample/proguard-rules.pro similarity index 100% rename from wearsample/proguard-rules.pro rename to wearablesample/proguard-rules.pro diff --git a/wearsample/src/main/AndroidManifest.xml b/wearablesample/src/main/AndroidManifest.xml similarity index 100% rename from wearsample/src/main/AndroidManifest.xml rename to wearablesample/src/main/AndroidManifest.xml diff --git a/wearsample/src/main/java/com/compose/wearsample/presentation/MainActivity.kt b/wearablesample/src/main/java/com/mutualmobile/wearablesample/presentation/MainActivity.kt similarity index 92% rename from wearsample/src/main/java/com/compose/wearsample/presentation/MainActivity.kt rename to wearablesample/src/main/java/com/mutualmobile/wearablesample/presentation/MainActivity.kt index 0d8974e..35cdea3 100644 --- a/wearsample/src/main/java/com/compose/wearsample/presentation/MainActivity.kt +++ b/wearablesample/src/main/java/com/mutualmobile/wearablesample/presentation/MainActivity.kt @@ -4,7 +4,7 @@ * changes to the libraries and their usages. */ -package com.compose.wearsample.presentation +package com.mutualmobile.wearablesample.presentation import android.os.Bundle import androidx.activity.ComponentActivity @@ -16,8 +16,8 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.wear.compose.material.MaterialTheme import androidx.wear.compose.material.Text -import com.compose.wearsample.presentation.theme.ComposeSensorsTheme import com.mutualmobile.composesensors.rememberHeartRateSensorState +import com.mutualmobile.wearablesample.presentation.theme.ComposeSensorsTheme class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { diff --git a/wearsample/src/main/java/com/compose/wearsample/presentation/theme/Color.kt b/wearablesample/src/main/java/com/mutualmobile/wearablesample/presentation/theme/Color.kt similarity index 89% rename from wearsample/src/main/java/com/compose/wearsample/presentation/theme/Color.kt rename to wearablesample/src/main/java/com/mutualmobile/wearablesample/presentation/theme/Color.kt index d6b144a..cd5d94e 100644 --- a/wearsample/src/main/java/com/compose/wearsample/presentation/theme/Color.kt +++ b/wearablesample/src/main/java/com/mutualmobile/wearablesample/presentation/theme/Color.kt @@ -1,4 +1,4 @@ -package com.compose.wearsample.presentation.theme +package com.mutualmobile.wearablesample.presentation.theme import androidx.compose.ui.graphics.Color import androidx.wear.compose.material.Colors diff --git a/wearsample/src/main/java/com/compose/wearsample/presentation/theme/Theme.kt b/wearablesample/src/main/java/com/mutualmobile/wearablesample/presentation/theme/Theme.kt similarity index 88% rename from wearsample/src/main/java/com/compose/wearsample/presentation/theme/Theme.kt rename to wearablesample/src/main/java/com/mutualmobile/wearablesample/presentation/theme/Theme.kt index 0811f6a..2e364a9 100644 --- a/wearsample/src/main/java/com/compose/wearsample/presentation/theme/Theme.kt +++ b/wearablesample/src/main/java/com/mutualmobile/wearablesample/presentation/theme/Theme.kt @@ -1,4 +1,4 @@ -package com.compose.wearsample.presentation.theme +package com.mutualmobile.wearablesample.presentation.theme import androidx.compose.runtime.Composable import androidx.wear.compose.material.MaterialTheme diff --git a/wearsample/src/main/java/com/compose/wearsample/presentation/theme/Type.kt b/wearablesample/src/main/java/com/mutualmobile/wearablesample/presentation/theme/Type.kt similarity index 92% rename from wearsample/src/main/java/com/compose/wearsample/presentation/theme/Type.kt rename to wearablesample/src/main/java/com/mutualmobile/wearablesample/presentation/theme/Type.kt index d31b989..b3fb98a 100644 --- a/wearsample/src/main/java/com/compose/wearsample/presentation/theme/Type.kt +++ b/wearablesample/src/main/java/com/mutualmobile/wearablesample/presentation/theme/Type.kt @@ -1,4 +1,4 @@ -package com.compose.wearsample.presentation.theme +package com.mutualmobile.wearablesample.presentation.theme import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.font.FontFamily diff --git a/wearsample/src/main/res/mipmap-hdpi/ic_launcher.webp b/wearablesample/src/main/res/mipmap-hdpi/ic_launcher.webp similarity index 100% rename from wearsample/src/main/res/mipmap-hdpi/ic_launcher.webp rename to wearablesample/src/main/res/mipmap-hdpi/ic_launcher.webp diff --git a/wearsample/src/main/res/mipmap-mdpi/ic_launcher.webp b/wearablesample/src/main/res/mipmap-mdpi/ic_launcher.webp similarity index 100% rename from wearsample/src/main/res/mipmap-mdpi/ic_launcher.webp rename to wearablesample/src/main/res/mipmap-mdpi/ic_launcher.webp diff --git a/wearsample/src/main/res/mipmap-xhdpi/ic_launcher.webp b/wearablesample/src/main/res/mipmap-xhdpi/ic_launcher.webp similarity index 100% rename from wearsample/src/main/res/mipmap-xhdpi/ic_launcher.webp rename to wearablesample/src/main/res/mipmap-xhdpi/ic_launcher.webp diff --git a/wearsample/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/wearablesample/src/main/res/mipmap-xxhdpi/ic_launcher.webp similarity index 100% rename from wearsample/src/main/res/mipmap-xxhdpi/ic_launcher.webp rename to wearablesample/src/main/res/mipmap-xxhdpi/ic_launcher.webp diff --git a/wearsample/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/wearablesample/src/main/res/mipmap-xxxhdpi/ic_launcher.webp similarity index 100% rename from wearsample/src/main/res/mipmap-xxxhdpi/ic_launcher.webp rename to wearablesample/src/main/res/mipmap-xxxhdpi/ic_launcher.webp diff --git a/wearsample/src/main/res/values-round/strings.xml b/wearablesample/src/main/res/values-round/strings.xml similarity index 100% rename from wearsample/src/main/res/values-round/strings.xml rename to wearablesample/src/main/res/values-round/strings.xml diff --git a/wearsample/src/main/res/values/strings.xml b/wearablesample/src/main/res/values/strings.xml similarity index 100% rename from wearsample/src/main/res/values/strings.xml rename to wearablesample/src/main/res/values/strings.xml From c1545d75a6d2e325a977e752765f922e093da9c1 Mon Sep 17 00:00:00 2001 From: Swapnil Musale Date: Thu, 30 Mar 2023 16:21:56 +0530 Subject: [PATCH 03/17] feat: Step Detector Sensor Implementation --- README.md | 2 +- .../composesensors/StepDetectorSensorState.kt | 78 +++++++++++++++++++ 2 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 composesensors/src/main/java/com/mutualmobile/composesensors/StepDetectorSensorState.kt diff --git a/README.md b/README.md index f854a28..7ef73cf 100644 --- a/README.md +++ b/README.md @@ -88,7 +88,7 @@ Magnetic Field (Uncalibrated) | ⚠️ | WIP GameRotation Vector | ⚠️ | WIP Gyroscope (Uncalibrated) | ⚠️ | WIP Significant Motion | ⚠️ | WIP -Step Detector | ⚠️ | WIP +Step Detector | ✅️ | rememberStepDetectorSensorState Step Counter | ⚠️ | WIP Geomagnetic Rotation Vector | ⚠️ | WIP Heart Rate | ⚠️ | WIP diff --git a/composesensors/src/main/java/com/mutualmobile/composesensors/StepDetectorSensorState.kt b/composesensors/src/main/java/com/mutualmobile/composesensors/StepDetectorSensorState.kt new file mode 100644 index 0000000..8965f38 --- /dev/null +++ b/composesensors/src/main/java/com/mutualmobile/composesensors/StepDetectorSensorState.kt @@ -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, + 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 +} From 321da668a09322d557f50d69d0fd8159fa5c2056 Mon Sep 17 00:00:00 2001 From: AdityaBhawsar Date: Thu, 30 Mar 2023 19:24:54 +0530 Subject: [PATCH 04/17] Added AmbientTemperatureSensorState.kt --- .../composesensors/AmbientTemperatureSensorState.kt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 composesensors/src/main/java/com/mutualmobile/composesensors/AmbientTemperatureSensorState.kt diff --git a/composesensors/src/main/java/com/mutualmobile/composesensors/AmbientTemperatureSensorState.kt b/composesensors/src/main/java/com/mutualmobile/composesensors/AmbientTemperatureSensorState.kt new file mode 100644 index 0000000..fcae169 --- /dev/null +++ b/composesensors/src/main/java/com/mutualmobile/composesensors/AmbientTemperatureSensorState.kt @@ -0,0 +1,2 @@ +package com.mutualmobile.composesensors + From bfe6143e3399c4fb665a142b9466054f0ebf1393 Mon Sep 17 00:00:00 2001 From: Swapnil Musale Date: Thu, 30 Mar 2023 20:30:27 +0530 Subject: [PATCH 05/17] feat: Step Detector Sensor Implementation --- README.md | 2 +- .../composesensors/StepDetectorSensorState.kt | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 23da1a1..b281e58 100644 --- a/README.md +++ b/README.md @@ -88,7 +88,7 @@ Magnetic Field (Uncalibrated) | ⚠️ | WIP GameRotation Vector | ⚠️ | WIP Gyroscope (Uncalibrated) | ⚠️ | WIP Significant Motion | ⚠️ | WIP -Step Detector | ✅️ | rememberStepDetectorSensorState +Step Detector | ✅️ | rememberStepDetectorSensorState() Step Counter | ✅️ | rememberStepCounterSensorState() Geomagnetic Rotation Vector | ⚠️ | WIP Heart Rate | ⚠️ | WIP diff --git a/composesensors/src/main/java/com/mutualmobile/composesensors/StepDetectorSensorState.kt b/composesensors/src/main/java/com/mutualmobile/composesensors/StepDetectorSensorState.kt index 8965f38..085af17 100644 --- a/composesensors/src/main/java/com/mutualmobile/composesensors/StepDetectorSensorState.kt +++ b/composesensors/src/main/java/com/mutualmobile/composesensors/StepDetectorSensorState.kt @@ -9,13 +9,13 @@ 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 stepCount 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, + val stepCount: Float = 0f, val isAvailable: Boolean = false, val accuracy: Int = 0, ) { @@ -23,7 +23,7 @@ class StepDetectorSensorState internal constructor( if (this === other) return true if (other !is StepDetectorSensorState) return false - if (steps != other.steps) return false + if (stepCount != other.stepCount) return false if (isAvailable != other.isAvailable) return false if (accuracy != other.accuracy) return false @@ -31,14 +31,14 @@ class StepDetectorSensorState internal constructor( } override fun hashCode(): Int { - var result = steps.hashCode() + var result = stepCount.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)" + return "StepDetectorSensorState(stepCount=$stepCount isAvailable=$isAvailable, accuracy=$accuracy)" } } @@ -66,7 +66,7 @@ fun rememberStepDetectorSensorState( val sensorStateValues = sensorState.data if (sensorStateValues.isNotEmpty()) { stepDetectorSensorState.value = StepDetectorSensorState( - steps = sensorStateValues[0], + stepCount = sensorStateValues[0], isAvailable = sensorState.isAvailable, accuracy = sensorState.accuracy, ) From 8c8a8121ec11f35fee47ee52ca7bc4bb671a7a07 Mon Sep 17 00:00:00 2001 From: Swapnil Musale Date: Thu, 30 Mar 2023 20:32:36 +0530 Subject: [PATCH 06/17] feat: Heart Rate Sensor Implementation --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 433ea56..749cad8 100644 --- a/README.md +++ b/README.md @@ -91,7 +91,7 @@ Significant Motion | ⚠️ | WIP Step Detector | ⚠️ | WIP Step Counter | ✅️ | rememberStepCounterSensorState() Geomagnetic Rotation Vector | ⚠️ | WIP -Heart Rate | ✅️ | rememberHeartRateSensorState +Heart Rate | ✅️ | rememberHeartRateSensorState() Pose6DOF | ⚠️ | WIP Stationary Detect | ⚠️ | WIP Motion Detect | ⚠️ | WIP From 0c16166162bf46127478ee13069dbcbdf9b85714 Mon Sep 17 00:00:00 2001 From: AdityaBhawsar Date: Thu, 30 Mar 2023 22:50:54 +0530 Subject: [PATCH 07/17] Added functional implementation AmbientTemperatureSensorState.kt --- .../AmbientTemperatureSensorState.kt | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/composesensors/src/main/java/com/mutualmobile/composesensors/AmbientTemperatureSensorState.kt b/composesensors/src/main/java/com/mutualmobile/composesensors/AmbientTemperatureSensorState.kt index fcae169..0f9f63c 100644 --- a/composesensors/src/main/java/com/mutualmobile/composesensors/AmbientTemperatureSensorState.kt +++ b/composesensors/src/main/java/com/mutualmobile/composesensors/AmbientTemperatureSensorState.kt @@ -1,2 +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 +} \ No newline at end of file From 2835b222e3cef2d8105bf0a216f22a2b643b8534 Mon Sep 17 00:00:00 2001 From: AdityaBhawsar Date: Thu, 30 Mar 2023 22:53:03 +0530 Subject: [PATCH 08/17] updated README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0bf5540..55aa44b 100644 --- a/README.md +++ b/README.md @@ -83,7 +83,7 @@ Gravity | ✅️ | rememberGravitySensorState() Linear Acceleration | ✅️ | rememberLinearAccelerationSensorState() Rotation Vector | ⚠️ | WIP Relative Humidity | ⚠️ | WIP -Ambient Temperature | ⚠️ | WIP +Ambient Temperature | ✅️ | rememberAmbientTemperatureSensorState() Magnetic Field (Uncalibrated) | ⚠️ | WIP GameRotation Vector | ⚠️ | WIP Gyroscope (Uncalibrated) | ⚠️ | WIP From 7575cd1cb8d706b8aaa943e7615e02289ed9abe3 Mon Sep 17 00:00:00 2001 From: AdityaBhawsar Date: Fri, 31 Mar 2023 00:43:50 +0530 Subject: [PATCH 09/17] Added GeomagneticRotationVectorSensorState.kt --- .../composesensors/GeomagneticRotationVectorSensorState.kt | 1 + 1 file changed, 1 insertion(+) create mode 100644 composesensors/src/main/java/com/mutualmobile/composesensors/GeomagneticRotationVectorSensorState.kt diff --git a/composesensors/src/main/java/com/mutualmobile/composesensors/GeomagneticRotationVectorSensorState.kt b/composesensors/src/main/java/com/mutualmobile/composesensors/GeomagneticRotationVectorSensorState.kt new file mode 100644 index 0000000..8bf5a0d --- /dev/null +++ b/composesensors/src/main/java/com/mutualmobile/composesensors/GeomagneticRotationVectorSensorState.kt @@ -0,0 +1 @@ +package com.mutualmobile.composesensors \ No newline at end of file From 61af10846ea48e96d8cbbd66a312d53eeca8a1b9 Mon Sep 17 00:00:00 2001 From: AdityaBhawsar Date: Fri, 31 Mar 2023 00:47:55 +0530 Subject: [PATCH 10/17] Added functional implementation for GeomagneticRotationVectorSensorState.kt --- .../GeomagneticRotationVectorSensorState.kt | 89 ++++++++++++++++++- 1 file changed, 88 insertions(+), 1 deletion(-) diff --git a/composesensors/src/main/java/com/mutualmobile/composesensors/GeomagneticRotationVectorSensorState.kt b/composesensors/src/main/java/com/mutualmobile/composesensors/GeomagneticRotationVectorSensorState.kt index 8bf5a0d..49f8585 100644 --- a/composesensors/src/main/java/com/mutualmobile/composesensors/GeomagneticRotationVectorSensorState.kt +++ b/composesensors/src/main/java/com/mutualmobile/composesensors/GeomagneticRotationVectorSensorState.kt @@ -1 +1,88 @@ -package com.mutualmobile.composesensors \ No newline at end of file +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 rememberGameRotationVectorSensorState( + 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 +} \ No newline at end of file From c55f79c16e9784da79d891a186a4f437efb606d4 Mon Sep 17 00:00:00 2001 From: AdityaBhawsar Date: Fri, 31 Mar 2023 00:50:02 +0530 Subject: [PATCH 11/17] Added functional implementation for GeomagneticRotationVectorSensorState.kt --- README.md | 2 +- .../composesensors/GeomagneticRotationVectorSensorState.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 0bf5540..2b2c4c7 100644 --- a/README.md +++ b/README.md @@ -90,7 +90,7 @@ Gyroscope (Uncalibrated) | ⚠️ | WIP Significant Motion | ⚠️ | WIP Step Detector | ⚠️ | WIP Step Counter | ✅️ | rememberStepCounterSensorState() -Geomagnetic Rotation Vector | ⚠️ | WIP +Geomagnetic Rotation Vector | ✅️️ | rememberGeomagneticRotationVectorSensorState() Heart Rate | ⚠️ | WIP Pose6DOF | ⚠️ | WIP Stationary Detect | ⚠️ | WIP diff --git a/composesensors/src/main/java/com/mutualmobile/composesensors/GeomagneticRotationVectorSensorState.kt b/composesensors/src/main/java/com/mutualmobile/composesensors/GeomagneticRotationVectorSensorState.kt index 49f8585..4f6c8b8 100644 --- a/composesensors/src/main/java/com/mutualmobile/composesensors/GeomagneticRotationVectorSensorState.kt +++ b/composesensors/src/main/java/com/mutualmobile/composesensors/GeomagneticRotationVectorSensorState.kt @@ -58,7 +58,7 @@ class GeomagneticRotationVectorSensorState internal constructor( * @param onError Callback invoked on every error state. */ @Composable -fun rememberGameRotationVectorSensorState( +fun rememberGeomagneticRotationVectorSensorState( sensorDelay: SensorDelay = SensorDelay.Normal, onError: (throwable: Throwable) -> Unit = {}, ): GeomagneticRotationVectorSensorState { From 05063b8c2588bac26ebebf683853a5ba226a1288 Mon Sep 17 00:00:00 2001 From: AdityaBhawsar Date: Fri, 31 Mar 2023 01:06:11 +0530 Subject: [PATCH 12/17] Added RotationVectorSensorState.kt --- .../mutualmobile/composesensors/RotationVectorSensorState.kt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 composesensors/src/main/java/com/mutualmobile/composesensors/RotationVectorSensorState.kt diff --git a/composesensors/src/main/java/com/mutualmobile/composesensors/RotationVectorSensorState.kt b/composesensors/src/main/java/com/mutualmobile/composesensors/RotationVectorSensorState.kt new file mode 100644 index 0000000..fcae169 --- /dev/null +++ b/composesensors/src/main/java/com/mutualmobile/composesensors/RotationVectorSensorState.kt @@ -0,0 +1,2 @@ +package com.mutualmobile.composesensors + From 88d22d91d5dea8f4918a5c33801736b8f381564a Mon Sep 17 00:00:00 2001 From: AdityaBhawsar Date: Fri, 31 Mar 2023 01:25:54 +0530 Subject: [PATCH 13/17] Added functional implementation for RotationVectorSensorState.kt --- .../RotationVectorSensorState.kt | 95 +++++++++++++++++++ 1 file changed, 95 insertions(+) diff --git a/composesensors/src/main/java/com/mutualmobile/composesensors/RotationVectorSensorState.kt b/composesensors/src/main/java/com/mutualmobile/composesensors/RotationVectorSensorState.kt index fcae169..30723fe 100644 --- a/composesensors/src/main/java/com/mutualmobile/composesensors/RotationVectorSensorState.kt +++ b/composesensors/src/main/java/com/mutualmobile/composesensors/RotationVectorSensorState.kt @@ -1,2 +1,97 @@ 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 scalar Scalar component of rotation vector. + * @param estimatedHeadingAccuracy estimated heading Accuracy (in radians). + * @param isAvailable Whether the current device has a rotation vector sensor. Defaults to false. + * @param accuracy Accuracy factor of the rotation vector sensor. Defaults to 0. + */ +@Immutable +class RotationVectorSensorState internal constructor( + val vectorX: Float = 0f, + val vectorY: Float = 0f, + val vectorZ: Float = 0f, + val scalar: Float = 0f, + val estimatedHeadingAccuracy: Float = 0f, + val isAvailable: Boolean = false, + val accuracy: Int = 0 +) { + override fun toString(): String { + return "RotationVectorSensorState(vectorX=$vectorX, " + + "vectorY=$vectorY, vectorZ=$vectorZ, scalar=$scalar, " + + "estimatedHeadingAccuracy=$estimatedHeadingAccuracy, " + + "isAvailable=$isAvailable, accuracy=$accuracy)" + } + + override fun equals(other: Any?): Boolean { + if (this === other) return true + other as RotationVectorSensorState + + if (vectorX != other.vectorX) return false + if (vectorY != other.vectorY) return false + if (vectorZ != other.vectorZ) return false + if (scalar != other.scalar) return false + if (estimatedHeadingAccuracy != other.estimatedHeadingAccuracy) 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 + scalar.hashCode() + result = 31 * result + estimatedHeadingAccuracy.hashCode() + result = 31 * result + isAvailable.hashCode() + result = 31 * result + accuracy + return result + } +} + +/** + * Creates and [remember]s instance of [RotationVectorSensorState]. + * @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 rememberRotationVectorSensorState( + sensorDelay: SensorDelay = SensorDelay.Normal, + onError: (throwable: Throwable) -> Unit = {}, +): RotationVectorSensorState { + val sensorState = rememberSensorState( + sensorType = SensorType.RotationVector, + sensorDelay = sensorDelay, + onError = onError, + ) + + val rotationVectorSensorState = remember { mutableStateOf(RotationVectorSensorState()) } + + LaunchedEffect(key1 = sensorState, block = { + val sensorStateValues = sensorState.data + if (sensorStateValues.isNotEmpty()) { + rotationVectorSensorState.value = RotationVectorSensorState( + vectorX = sensorStateValues[0], + vectorY = sensorStateValues[1], + vectorZ = sensorStateValues[2], + scalar = sensorStateValues[3], + estimatedHeadingAccuracy = sensorStateValues[4], + isAvailable = sensorState.isAvailable, + accuracy = sensorState.accuracy + ) + } + }) + + return rotationVectorSensorState.value +} \ No newline at end of file From 62533840cce494981d91f8d6da1bc21dec98558d Mon Sep 17 00:00:00 2001 From: AdityaBhawsar Date: Fri, 31 Mar 2023 01:27:13 +0530 Subject: [PATCH 14/17] updated README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0bf5540..aa99405 100644 --- a/README.md +++ b/README.md @@ -81,7 +81,7 @@ 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 From 9c725512187bd99960a41f530e6257d8b21e5e19 Mon Sep 17 00:00:00 2001 From: Swapnil Musale Date: Fri, 31 Mar 2023 12:20:29 +0530 Subject: [PATCH 15/17] feat: Heart Rate Sensor Implementation --- .../com/mutualmobile/composesensors/HeartRateSensorState.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/composesensors/src/main/java/com/mutualmobile/composesensors/HeartRateSensorState.kt b/composesensors/src/main/java/com/mutualmobile/composesensors/HeartRateSensorState.kt index feff307..5f8f80d 100644 --- a/composesensors/src/main/java/com/mutualmobile/composesensors/HeartRateSensorState.kt +++ b/composesensors/src/main/java/com/mutualmobile/composesensors/HeartRateSensorState.kt @@ -14,7 +14,7 @@ import androidx.compose.runtime.remember */ @Immutable class HeartRateSensorState internal constructor( - val heartRate: Int = 0, + val heartRate: Float = 0f, val isAvailable: Boolean = false, val accuracy: Int = 0, ) { @@ -65,7 +65,7 @@ fun rememberHeartRateSensorState( val sensorStateValues = sensorState.data if (sensorStateValues.isNotEmpty()) { heartRateSensorState.value = HeartRateSensorState( - heartRate = sensorStateValues[0].toInt(), + heartRate = sensorStateValues[0], isAvailable = sensorState.isAvailable, accuracy = sensorState.accuracy, ) From 6717705555eef12cedeb550bb7d0d2ad8b0c1502 Mon Sep 17 00:00:00 2001 From: Shubham Singh <89389061+shubhamsinghmutualmobile@users.noreply.github.com> Date: Mon, 3 Apr 2023 13:06:48 +0530 Subject: [PATCH 16/17] Add demo GIF to README --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 615b151..40e9017 100644 --- a/README.md +++ b/README.md @@ -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 🌺 From d26a518ae68982572d2810ac91b9b002a9ce6bc9 Mon Sep 17 00:00:00 2001 From: Shubham Singh <89389061+shubhamsinghmutualmobile@users.noreply.github.com> Date: Mon, 3 Apr 2023 13:18:52 +0530 Subject: [PATCH 17/17] README - Remove incorrect WIP status Remove WIP status for sensors whose PRs have not been raised yet --- README.md | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 40e9017..426b6c7 100644 --- a/README.md +++ b/README.md @@ -87,28 +87,28 @@ Linear Acceleration | ✅️ | rememberLinearAccelerationSensorState() Rotation Vector | ⚠️ | WIP Relative Humidity | ⚠️ | WIP Ambient Temperature | ✅️ | rememberAmbientTemperatureSensorState() -Magnetic Field (Uncalibrated) | ⚠️ | WIP +Magnetic Field (Uncalibrated) | — | N/A GameRotation Vector | ⚠️ | WIP Gyroscope (Uncalibrated) | ⚠️ | WIP -Significant Motion | ⚠️ | WIP +Significant Motion | — | N/A Step Detector | ✅️ | rememberStepDetectorSensorState() Step Counter | ✅️ | rememberStepCounterSensorState() Geomagnetic Rotation Vector | ⚠️ | WIP Heart Rate | ✅️ | rememberHeartRateSensorState() -Pose6DOF | ⚠️ | WIP -Stationary Detect | ⚠️ | WIP -Motion Detect | ⚠️ | WIP -Heart Beat | ⚠️ | WIP -Low Latency Off-Body Detect | ⚠️ | WIP +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 🔖 ```