Skip to content

Commit

Permalink
Merge pull request #311 from weichenc/backgroun-read
Browse files Browse the repository at this point in the history
Add background read example code
  • Loading branch information
weichenc authored Nov 8, 2024
2 parents 8a3813f + efaaf31 commit 2fa129e
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
<uses-permission android:name="android.permission.health.WRITE_TOTAL_CALORIES_BURNED"/>
<uses-permission android:name="android.permission.health.READ_WEIGHT"/>
<uses-permission android:name="android.permission.health.WRITE_WEIGHT"/>
<uses-permission android:name="android.permission.health.READ_HEALTH_DATA_IN_BACKGROUND" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,10 @@ import androidx.activity.result.contract.ActivityResultContract
import androidx.compose.runtime.mutableStateOf
import androidx.health.connect.client.HealthConnectClient
import androidx.health.connect.client.HealthConnectClient.Companion.SDK_UNAVAILABLE
import androidx.health.connect.client.HealthConnectFeatures
import androidx.health.connect.client.PermissionController
import androidx.health.connect.client.changes.Change
import androidx.health.connect.client.feature.ExperimentalFeatureAvailabilityApi
import androidx.health.connect.client.records.DistanceRecord
import androidx.health.connect.client.records.ExerciseSessionRecord
import androidx.health.connect.client.records.HeartRateRecord
Expand Down Expand Up @@ -484,6 +486,13 @@ class HealthConnectManager(private val context: Context) {
samples = samples)
}

@OptIn(ExperimentalFeatureAvailabilityApi::class)
fun isFeatureAvailable(feature: Int): Boolean{
return healthConnectClient
.features
.getFeatureStatus(feature) == HealthConnectFeatures.FEATURE_STATUS_AVAILABLE
}

// Represents the two types of messages that can be sent in a Changes flow.
sealed class ChangesMessage {
data class NoMoreChanges(val nextChangesToken: String) : ChangesMessage()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,13 +94,17 @@ fun HealthConnectNavigation(
val permissionsGranted by viewModel.permissionsGranted
val sessionsList by viewModel.sessionsList
val permissions = viewModel.permissions
val backgroundReadAvailable by viewModel.backgroundReadAvailable
val backgroundReadGranted by viewModel.backgroundReadGranted
val onPermissionsResult = {viewModel.initialLoad()}
val permissionsLauncher =
rememberLauncherForActivityResult(viewModel.permissionsLauncher) {
onPermissionsResult()}
ExerciseSessionScreen(
permissionsGranted = permissionsGranted,
permissions = permissions,
backgroundReadAvailable = backgroundReadAvailable,
backgroundReadGranted = backgroundReadGranted,
sessionsList = sessionsList,
uiState = viewModel.uiState,
onInsertClick = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.health.connect.client.permission.HealthPermission.Companion.PERMISSION_READ_HEALTH_DATA_IN_BACKGROUND
import androidx.health.connect.client.records.ExerciseSessionRecord
import com.example.healthconnectsample.R
import com.example.healthconnectsample.data.ExerciseSession
Expand All @@ -50,6 +51,8 @@ import java.util.UUID
fun ExerciseSessionScreen(
permissions: Set<String>,
permissionsGranted: Boolean,
backgroundReadAvailable: Boolean,
backgroundReadGranted: Boolean,
sessionsList: List<ExerciseSession>,
uiState: ExerciseSessionViewModel.UiState,
onInsertClick: () -> Unit = {},
Expand Down Expand Up @@ -110,6 +113,26 @@ fun ExerciseSessionScreen(
Text(stringResource(id = R.string.insert_exercise_session))
}
}
if (!backgroundReadGranted) {
item {
Button(
modifier = Modifier
.fillMaxWidth()
.height(48.dp)
.padding(4.dp),
onClick = {
onPermissionsLaunch(setOf(PERMISSION_READ_HEALTH_DATA_IN_BACKGROUND))
},
enabled = backgroundReadAvailable,
) {
if (backgroundReadAvailable){
Text("Request Background Read")
} else {
Text("Background Read Is Not Available")
}
}
}
}

items(sessionsList) { session ->
val appInfo = session.sourceAppInfo
Expand Down Expand Up @@ -152,6 +175,8 @@ fun ExerciseSessionScreenPreview() {
ExerciseSessionScreen(
permissions = setOf(),
permissionsGranted = true,
backgroundReadAvailable = false,
backgroundReadGranted = false,
sessionsList = listOf(
ExerciseSession(
title = "Running",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@ import androidx.compose.runtime.MutableState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.health.connect.client.HealthConnectFeatures
import androidx.health.connect.client.feature.ExperimentalFeatureAvailabilityApi
import androidx.health.connect.client.permission.HealthPermission
import androidx.health.connect.client.permission.HealthPermission.Companion.PERMISSION_READ_HEALTH_DATA_IN_BACKGROUND
import androidx.health.connect.client.records.DistanceRecord
import androidx.health.connect.client.records.ExerciseSessionRecord
import androidx.health.connect.client.records.HeartRateRecord
Expand Down Expand Up @@ -59,6 +62,12 @@ class ExerciseSessionViewModel(private val healthConnectManager: HealthConnectMa
var permissionsGranted = mutableStateOf(false)
private set

var backgroundReadAvailable = mutableStateOf(false)
private set

var backgroundReadGranted = mutableStateOf(false)
private set

var sessionsList: MutableState<List<ExerciseSession>> = mutableStateOf(listOf())
private set

Expand Down Expand Up @@ -131,8 +140,15 @@ class ExerciseSessionViewModel(private val healthConnectManager: HealthConnectMa
* Where an error is caught, of the type Health Connect is known to throw, [uiState] is set to
* [UiState.Error], which results in the snackbar being used to show the error message.
*/
@OptIn(ExperimentalFeatureAvailabilityApi::class)
private suspend fun tryWithPermissionsCheck(block: suspend () -> Unit) {
permissionsGranted.value = healthConnectManager.hasAllPermissions(permissions)
backgroundReadAvailable.value = healthConnectManager.isFeatureAvailable(
HealthConnectFeatures.FEATURE_READ_HEALTH_DATA_IN_BACKGROUND
)
backgroundReadGranted.value = healthConnectManager.hasAllPermissions(
setOf(PERMISSION_READ_HEALTH_DATA_IN_BACKGROUND)
)
uiState = try {
if (permissionsGranted.value) {
block()
Expand Down

0 comments on commit 2fa129e

Please sign in to comment.