Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import androidx.health.connect.client.HealthConnectFeatures
import androidx.health.connect.client.PermissionController
import androidx.health.connect.client.permission.HealthPermission
import androidx.health.connect.client.permission.HealthPermission.Companion.PERMISSION_READ_HEALTH_DATA_HISTORY
import androidx.health.connect.client.permission.HealthPermission.Companion.PERMISSION_READ_HEALTH_DATA_IN_BACKGROUND
import androidx.health.connect.client.records.*
import androidx.health.connect.client.records.MealType.MEAL_TYPE_BREAKFAST
import androidx.health.connect.client.records.MealType.MEAL_TYPE_DINNER
Expand Down Expand Up @@ -153,6 +154,9 @@ class HealthPlugin(private var channel: MethodChannel? = null) :
"isHealthDataHistoryAvailable" -> isHealthDataHistoryAvailable(call, result)
"isHealthDataHistoryAuthorized" -> isHealthDataHistoryAuthorized(call, result)
"requestHealthDataHistoryAuthorization" -> requestHealthDataHistoryAuthorization(call, result)
"isHealthDataInBackgroundAvailable" -> isHealthDataInBackgroundAvailable(call, result)
"isHealthDataInBackgroundAuthorized" -> isHealthDataInBackgroundAuthorized(call, result)
"requestHealthDataInBackgroundAuthorization" -> requestHealthDataInBackgroundAuthorization(call, result)
"hasPermissions" -> hasPermissions(call, result)
"requestAuthorization" -> requestAuthorization(call, result)
"revokePermissions" -> revokePermissions(call, result)
Expand Down Expand Up @@ -568,6 +572,55 @@ class HealthPlugin(private var channel: MethodChannel? = null) :
healthConnectRequestPermissionsLauncher!!.launch(setOf(PERMISSION_READ_HEALTH_DATA_HISTORY))
}

/**
* Checks if the health data in background feature is available on this device
*/
@OptIn(ExperimentalFeatureAvailabilityApi::class)
private fun isHealthDataInBackgroundAvailable(call: MethodCall, result: Result) {
scope.launch {
result.success(
healthConnectClient
.features
.getFeatureStatus(HealthConnectFeatures.FEATURE_READ_HEALTH_DATA_IN_BACKGROUND) ==
HealthConnectFeatures.FEATURE_STATUS_AVAILABLE)
}
}

/**
* Checks if PERMISSION_READ_HEALTH_DATA_IN_BACKGROUND has been granted
*/
private fun isHealthDataInBackgroundAuthorized(call: MethodCall, result: Result) {
scope.launch {
result.success(
healthConnectClient
.permissionController
.getGrantedPermissions()
.containsAll(listOf(PERMISSION_READ_HEALTH_DATA_IN_BACKGROUND)),
)
}
}

/**
* Requests authorization for PERMISSION_READ_HEALTH_DATA_IN_BACKGROUND
*/
private fun requestHealthDataInBackgroundAuthorization(call: MethodCall, result: Result) {
if (context == null) {
result.success(false)
return
}

if (healthConnectRequestPermissionsLauncher == null) {
result.success(false)
Log.i("FLUTTER_HEALTH", "Permission launcher not found")
return
}

// Store the result to be called in [onHealthConnectPermissionCallback]
mResult = result
isReplySubmitted = false
healthConnectRequestPermissionsLauncher!!.launch(setOf(PERMISSION_READ_HEALTH_DATA_IN_BACKGROUND))
}

private fun hasPermissions(call: MethodCall, result: Result) {
val args = call.arguments as HashMap<*, *>
val types = (args["types"] as? ArrayList<*>)?.filterIsInstance<String>()!!
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@
<!-- For reading historical data - more than 30 days ago since permission given -->
<uses-permission android:name="android.permission.health.READ_HEALTH_DATA_HISTORY"/>

<!-- For reading data in background -->
<uses-permission android:name="android.permission.health.READ_HEALTH_DATA_IN_BACKGROUND"/>

<application
android:label="health_example"
android:name="${applicationName}"
Expand Down
3 changes: 3 additions & 0 deletions packages/health/example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,9 @@ class HealthAppState extends State<HealthApp> {
// request access to read historic data
await health.requestHealthDataHistoryAuthorization();

// request access in background
await health.requestHealthDataInBackgroundAuthorization();

} catch (error) {
debugPrint("Exception in authorize: $error");
}
Expand Down
64 changes: 64 additions & 0 deletions packages/health/lib/src/health_plugin.dart
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,70 @@ class Health {
}
}

/// Checks if the Health Data in Background feature is available.
///
/// See this for more info: https://developer.android.com/reference/androidx/health/connect/client/permission/HealthPermission#PERMISSION_READ_HEALTH_DATA_IN_BACKGROUND()
///
///
/// Android only. Returns false on iOS or if an error occurs.
Future<bool> isHealthDataInBackgroundAvailable() async {
if (Platform.isIOS) return false;

try {
final status =
await _channel.invokeMethod<bool>('isHealthDataInBackgroundAvailable');
return status ?? false;
} catch (e) {
debugPrint(
'$runtimeType - Exception in isHealthDataInBackgroundAvailable(): $e');
return false;
}
}

/// Checks the current status of the Health Data in Background permission.
/// Make sure to check [isHealthConnectAvailable] before calling this method.
///
/// See this for more info: https://developer.android.com/reference/androidx/health/connect/client/permission/HealthPermission#PERMISSION_READ_HEALTH_DATA_IN_BACKGROUND()
///
///
/// Android only. Returns true on iOS or false if an error occurs.
Future<bool> isHealthDataInBackgroundAuthorized() async {
if (Platform.isIOS) return true;

try {
final status =
await _channel.invokeMethod<bool>('isHealthDataInBackgroundAuthorized');
return status ?? false;
} catch (e) {
debugPrint(
'$runtimeType - Exception in isHealthDataInBackgroundAuthorized(): $e');
return false;
}
}

/// Requests the Health Data in Background permission.
///
/// Returns true if successful, false otherwise.
///
/// See this for more info: https://developer.android.com/reference/androidx/health/connect/client/permission/HealthPermission#PERMISSION_READ_HEALTH_DATA_IN_BACKGROUND()
///
///
/// Android only. Returns true on iOS or false if an error occurs.
Future<bool> requestHealthDataInBackgroundAuthorization() async {
if (Platform.isIOS) return true;

await _checkIfHealthConnectAvailableOnAndroid();
try {
final bool? isAuthorized =
await _channel.invokeMethod('requestHealthDataInBackgroundAuthorization');
return isAuthorized ?? false;
} catch (e) {
debugPrint(
'$runtimeType - Exception in requestHealthDataInBackgroundAuthorization(): $e');
return false;
}
}

/// Requests permissions to access health data [types].
///
/// Returns true if successful, false otherwise.
Expand Down