Skip to content

Request permissions

How to request, check, enumerate, and revoke health permissions. For why the platforms behave differently here, read Permissions first.

Request permissions

dart
// 1. Ask for exactly what this feature needs.
final permissions = [
  HealthDataType.steps.readPermission,
  HealthDataType.steps.writePermission,
  HealthDataType.weight.readPermission,
  HealthPlatformFeature.readHealthDataInBackground.permission,
];

// 2. Request them together — one system prompt, not four.
final results = await connector.requestPermissions(permissions);

// 3. Handle each outcome.
for (final result in results) {
  switch (result.status) {
    case PermissionStatus.granted:
      print('Granted: ${result.permission}');
    case PermissionStatus.denied:
      print('Denied: ${result.permission}');
    case PermissionStatus.unknown:
      print('Unknown: ${result.permission} (iOS read permission)');
  }
}

Decide what "good enough" means

Rarely does a feature need every requested permission. Check the ones that block your UI and let the rest degrade:

dart
final canShowSteps = results.any(
  (r) =>
      r.permission == HealthDataType.steps.readPermission &&
      r.status != PermissionStatus.denied,
);

Use any, not where(...).every(...). every returns true on an empty iterable, so a permission missing from the results entirely would read as granted.

Check a single permission

dart
final status = await connector.getPermissionStatus(
  HealthDataType.steps.readPermission,
);

switch (status) {
  case PermissionStatus.granted:
    print('Steps read permission granted');
  case PermissionStatus.denied:
    print('Steps read permission denied');
  case PermissionStatus.unknown:
    print('Steps read permission unknown (iOS read)');
}

On iOS this only answers for writes

HealthKit restricts access to read-authorization status to protect user privacy, so the SDK reports unknown for every iOS read permission. That is native behavior, not an SDK limitation.

List every granted permission

Android only
dart
try {
  final grantedPermissions = await connector.getGrantedPermissions();
  for (final permission in grantedPermissions) {
    print('Granted: ${permission.dataType} (${permission.accessType})');
  }
} on UnsupportedOperationException {
  print('Listing granted permissions is not supported on iOS');
}

HealthKit does not allow apps to enumerate grants — that would let an app fingerprint what a user is hiding. This call throws UnsupportedOperationException on iOS.

Revoke all permissions

Android only
dart
try {
  await connector.revokeAllPermissions();
  print('Permissions revoked');
} on UnsupportedOperationException {
  print('Programmatic revocation is not supported on iOS');
}

There is no programmatic revocation on iOS. If your app offers a "disconnect Apple Health" control, point the user to Settings → Health → Data Access & Devices rather than trying to revoke for them.

Exercise routes need two permissions

Route access is layered on top of session access. Route permissions alone do nothing:

dart
final permissions = [
  // Foundation — required.
  HealthDataType.exerciseSession.readPermission,
  HealthDataType.exerciseSession.writePermission,

  // Route access on top.
  HealthDataType.exerciseSession.readExerciseRoutePermission,
  HealthDataType.exerciseSession.writeExerciseRoutePermission,
];

final results = await connector.requestPermissions(permissions);

See Read & write exercise routes.

Released under the Apache 2.0 License.