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

Improve Health Connect error handling #105

Merged
merged 3 commits into from
Mar 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .idea/compiler.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions .idea/deploymentTargetDropDown.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions .idea/gradle.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/kotlinc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions .idea/migrations.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 1 addition & 2 deletions .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,9 @@ class MainActivity : AppCompatActivity() {
val granted = healthViewModel
.healthConnectManager
.healthConnectClient
.permissionController
.getGrantedPermissions()
if (!granted.containsAll(permissions)) {
?.permissionController
?.getGrantedPermissions()
if (granted != null && !granted.containsAll(permissions)) {
requestPermissions.launch(permissions)
} else {
healthViewModel.updatePermissionsStatus(true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@ import javax.inject.Inject
class HealthViewModel @Inject constructor(
var healthConnectManager: HealthConnectManager
) : ViewModel() {
var totalStepsToday = mutableStateOf<Long>(0)
var totalStepsToday = mutableStateOf<Long?>(null)
private set

var weeklyAverageWeight = mutableStateOf<Mass?>(null)
private set

private var permissionsGranted = mutableStateOf<Boolean>(false)
private var permissionsGranted = mutableStateOf<Boolean?>(false)

val permissions = setOf(
HealthPermission.getReadPermission(StepsRecord::class),
Expand All @@ -41,7 +41,7 @@ class HealthViewModel @Inject constructor(
}

fun getTotalStepsToday() = viewModelScope.launch {
if (permissionsGranted.value) {
if (permissionsGranted.value == true) {
totalStepsToday.value = healthConnectManager.aggregateSteps(
startTime = LocalDate.now().atStartOfDay(ZoneId.systemDefault()).toInstant(),
endTime = Instant.now()
Expand All @@ -56,7 +56,7 @@ class HealthViewModel @Inject constructor(
val endOfWeek = Instant.now()
val startOfWeek = endOfWeek.minus(7, ChronoUnit.DAYS)

if (permissionsGranted.value) {
if (permissionsGranted.value == true) {
weeklyAverageWeight.value = healthConnectManager.getAverageWeight(
startTime = startOfWeek,
endTime = endOfWeek
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ fun StepsCard(
viewModel: HealthViewModel = hiltViewModel()
) {
viewModel.getTotalStepsToday()
val totalStepsString = viewModel.totalStepsToday.value?.toString() ?: "-"

Card(
modifier = Modifier
.width(165.dp)
Expand All @@ -48,7 +50,7 @@ fun StepsCard(
color = MaterialTheme.colorScheme.onSecondary
)
Text(
text = viewModel.totalStepsToday.value.toString(),
text = totalStepsString,
fontSize = 40.sp,
color = MaterialTheme.colorScheme.onSecondary
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,16 @@ fun WeightCard(
var avgWeightString = "-"
val avgWeight = viewModel.weeklyAverageWeight.value

if (useMetricUnits) {
avgWeight?.inKilograms?.roundToInt().let {
avgWeightString = "$it kg"
}
val weightInSelectedUnit = if (useMetricUnits) {
avgWeight?.inKilograms?.roundToInt()
} else {
avgWeight?.inPounds?.roundToInt().let {
avgWeightString = "$it lbs"
}
avgWeight?.inPounds?.roundToInt()
}

avgWeightString = weightInSelectedUnit?.let {
"$it ${if (useMetricUnits) "kg" else "lbs"}"
} ?: "-"

Card(
modifier = Modifier
.width(165.dp)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,9 @@ fun StepGoalProgress(
// Fetch total step count and calculate metrics
healthViewModel.getTotalStepsToday()
val goal = task.context.integerGoal
val totalStepsToday = healthViewModel.totalStepsToday.value
var progress = healthViewModel.totalStepsToday.value.toFloat() / goal
val totalStepsToday = healthViewModel.totalStepsToday.value ?: 0

var progress = totalStepsToday.toFloat() / goal
if (progress > 1.0F) {
progress = 1.0F
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,25 +17,27 @@ import javax.inject.Inject
class HealthConnectManager @Inject constructor(
private val context: Context
) {
val healthConnectClient by lazy { HealthConnectClient.getOrCreate(context) }
var healthConnectClient: HealthConnectClient? = null

var isAvailable = mutableStateOf(false)
private set
private var isAvailable = mutableStateOf(false)

init {
isAvailable.value = checkAvailabilityStatus()
if (isAvailable.value) {
healthConnectClient = HealthConnectClient.getOrCreate(context)
}
}

fun checkAvailabilityStatus(): Boolean {
private fun checkAvailabilityStatus(): Boolean {
val availabilityStatus = HealthConnectClient.sdkStatus(context, "com.google.android.apps.healthdata")
return availabilityStatus == HealthConnectClient.SDK_AVAILABLE
}

/**
* Determines if all requested permissions are granted.
*/
suspend fun hasAllPermissions(permissions: Set<String>): Boolean {
return healthConnectClient.permissionController.getGrantedPermissions().containsAll(permissions)
suspend fun hasAllPermissions(permissions: Set<String>): Boolean? {
return healthConnectClient?.permissionController?.getGrantedPermissions()?.containsAll(permissions)
}

/**
Expand All @@ -44,15 +46,15 @@ class HealthConnectManager @Inject constructor(
suspend fun readStepsByTimeRange(
startTime: Instant,
endTime: Instant
): List<StepsRecord> {
): List<StepsRecord>? {
val response =
healthConnectClient.readRecords(
healthConnectClient?.readRecords(
ReadRecordsRequest(
StepsRecord::class,
timeRangeFilter = TimeRangeFilter.between(startTime, endTime)
)
)
return response.records
return response?.records
}

/**
Expand All @@ -63,13 +65,13 @@ class HealthConnectManager @Inject constructor(
endTime: Instant
): Long {
val response =
healthConnectClient.aggregate(
healthConnectClient?.aggregate(
AggregateRequest(
metrics = setOf(StepsRecord.COUNT_TOTAL),
timeRangeFilter = TimeRangeFilter.between(startTime, endTime)
)
)
return response[StepsRecord.COUNT_TOTAL] ?: 0
return response?.get(StepsRecord.COUNT_TOTAL) ?: 0
}

/**
Expand All @@ -78,9 +80,9 @@ class HealthConnectManager @Inject constructor(
suspend fun aggregateHeartRate(
startTime: Instant,
endTime: Instant
): AggregationResult {
): AggregationResult? {
val response =
healthConnectClient.aggregate(
healthConnectClient?.aggregate(
AggregateRequest(
setOf(HeartRateRecord.BPM_MAX, HeartRateRecord.BPM_MIN),
timeRangeFilter = TimeRangeFilter.between(startTime, endTime)
Expand All @@ -94,26 +96,26 @@ class HealthConnectManager @Inject constructor(
*/
suspend fun getAverageWeight(startTime: Instant, endTime: Instant): Mass? {
val response =
healthConnectClient.aggregate(
healthConnectClient?.aggregate(
AggregateRequest(
metrics = setOf(WeightRecord.WEIGHT_AVG),
timeRangeFilter = TimeRangeFilter.between(startTime, endTime)
)
)
return response[WeightRecord.WEIGHT_AVG]
return response?.get(WeightRecord.WEIGHT_AVG)
}

/**
* Get all weight records for a certain time period
*/
suspend fun getWeightRecords(startTime: Instant, endTime: Instant): List<WeightRecord> {
suspend fun getWeightRecords(startTime: Instant, endTime: Instant): List<WeightRecord>? {
val response =
healthConnectClient.readRecords(
healthConnectClient?.readRecords(
ReadRecordsRequest(
recordType = WeightRecord::class,
timeRangeFilter = TimeRangeFilter.between(startTime, endTime)
)
)
return response.records
return response?.records
}
}
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ buildscript {
compose_version = "1.4.1"
compose_bom_version = "2023.03.00"
hilt_navigation_compose_version = "1.0.0"
firebase_bom_version = "30.1.0"
firebase_bom_version = "32.7.0"
play_services_version = "1.6.2"
play_services_auth_version = "20.3.0"
accompanist_version = "0.24.10-beta"
Expand Down