Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class HealthDataReader(
private val dataConverter: HealthDataConverter
) {
private val recordingFilter = HealthRecordingFilter()
private val permissionChecker = HealthPermissionChecker(context)

/**
* Retrieves all health data points of a specified type within a given time range.
Expand Down Expand Up @@ -105,7 +106,7 @@ class HealthDataReader(
"Unable to return $dataType due to the following exception:"
)
Log.e("FLUTTER_HEALTH::ERROR", Log.getStackTraceString(e))
result.success(null)
result.error("UNAVAILABLE", "Data not available", null)
}
}
}
Expand Down Expand Up @@ -306,49 +307,73 @@ class HealthDataReader(
val record = rec as ExerciseSessionRecord

// Get distance data
val distanceRequest = healthConnectClient.readRecords(
ReadRecordsRequest(
recordType = DistanceRecord::class,
timeRangeFilter = TimeRangeFilter.between(
record.startTime,
record.endTime,
),
),
)
var totalDistance = 0.0
for (distanceRec in distanceRequest.records) {
totalDistance += distanceRec.distance.inMeters
if (permissionChecker.isLocationPermissionGranted() && permissionChecker.isHealthDistancePermissionGranted()) {
val distanceRequest = healthConnectClient.readRecords(
ReadRecordsRequest(
recordType = DistanceRecord::class,
timeRangeFilter = TimeRangeFilter.between(
record.startTime,
record.endTime,
),
),
)
for (distanceRec in distanceRequest.records) {
totalDistance += distanceRec.distance.inMeters
}
} else {
Log.i(
"FLUTTER_HEALTH",
"Skipping distance data retrieval for workout due to missing permissions (location or health distance)"
)
}

// Get energy burned data
val energyBurnedRequest = healthConnectClient.readRecords(
ReadRecordsRequest(
recordType = TotalCaloriesBurnedRecord::class,
timeRangeFilter = TimeRangeFilter.between(
record.startTime,
record.endTime,
),
),
)
var totalEnergyBurned = 0.0
for (energyBurnedRec in energyBurnedRequest.records) {
totalEnergyBurned += energyBurnedRec.energy.inKilocalories
if (permissionChecker.isHealthTotalCaloriesBurnedPermissionGranted()) {
val energyBurnedRequest = healthConnectClient.readRecords(
ReadRecordsRequest(
recordType = TotalCaloriesBurnedRecord::class,
timeRangeFilter = TimeRangeFilter.between(
record.startTime,
record.endTime,
),
),
)
for (energyBurnedRec in energyBurnedRequest.records) {
totalEnergyBurned += energyBurnedRec.energy.inKilocalories
}
} else {
Log.i(
"FLUTTER_HEALTH",
"Skipping total calories burned data retrieval for workout due to missing permissions"
)
}


// Get steps data
val stepRequest = healthConnectClient.readRecords(
ReadRecordsRequest(
recordType = StepsRecord::class,
timeRangeFilter = TimeRangeFilter.between(
record.startTime,
record.endTime
),
),
)
var totalSteps = 0.0
if (permissionChecker.isHealthStepsPermissionGranted()) {
val stepRequest = healthConnectClient.readRecords(
ReadRecordsRequest(
recordType = StepsRecord::class,
timeRangeFilter = TimeRangeFilter.between(
record.startTime,
record.endTime
),
),
)

for (stepRec in stepRequest.records) {
totalSteps += stepRec.count
}

} else {
Log.i(
"FLUTTER_HEALTH",
"Skipping steps data retrieval for workout due to missing permissions"
)
}

// Add final datapoint
healthConnectData.add(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package cachet.plugins.health

import android.Manifest
import android.content.Context
import android.content.pm.PackageManager
import androidx.core.content.ContextCompat

class HealthPermissionChecker(private val context: Context) {

fun isLocationPermissionGranted(): Boolean {
val fineLocationGranted = ContextCompat.checkSelfPermission(
context,
Manifest.permission.ACCESS_FINE_LOCATION
) == PackageManager.PERMISSION_GRANTED

val coarseLocationGranted = ContextCompat.checkSelfPermission(
context,
Manifest.permission.ACCESS_COARSE_LOCATION
) == PackageManager.PERMISSION_GRANTED

return fineLocationGranted || coarseLocationGranted
}

fun isHealthDistancePermissionGranted(): Boolean {
val healthDistancePermission = "android.permission.health.READ_DISTANCE"
return ContextCompat.checkSelfPermission(
context,
healthDistancePermission
) == PackageManager.PERMISSION_GRANTED
}

fun isHealthTotalCaloriesBurnedPermissionGranted(): Boolean {
val healthCaloriesPermission = "android.permission.health.READ_TOTAL_CALORIES_BURNED"
return ContextCompat.checkSelfPermission(
context,
healthCaloriesPermission
) == PackageManager.PERMISSION_GRANTED
}

fun isHealthStepsPermissionGranted(): Boolean {
val healthStepsPermission = "android.permission.health.READ_STEPS"
return ContextCompat.checkSelfPermission(
context,
healthStepsPermission
) == PackageManager.PERMISSION_GRANTED
}
}
Loading