Usage: Availability and permissions
Get availability status, check and ask for permissions.
Check availability
Before proceeding further, you need to ensure the user's device is compatible with Health Connect and check if the APK is installed.
Call checkHealthConnectAvailability and take the corresponding actions:
| Status | Description | What to do |
|---|---|---|
| installed | APK is installed | Proceed to check permissions |
| notInstalled | APK is not installed | Prompt the user to install Health Connect. |
| notSupported | This device does not support Health Connect | Take the user out of the Health Connect section |
void checkAvailability() {
HCRookHealthPermissionsManager.checkHealthConnectAvailability().then((availability) {
// Success
}).catchError((exception) {
// Handle error
});
}
Health Connect permissions
These are permissions used to extract data, each Health Connect data type is subject to a different permission, below you can see the list of permissions ROOK needs:
- READ_SLEEP
- READ_STEPS
- READ_DISTANCE
- READ_FLOORS_CLIMBED
- READ_ELEVATION_GAINED
- READ_OXYGEN_SATURATION
- READ_VO2_MAX
- READ_TOTAL_CALORIES_BURNED
- READ_ACTIVE_CALORIES_BURNED
- READ_HEART_RATE
- READ_RESTING_HEART_RATE
- READ_HEART_RATE_VARIABILITY
- READ_EXERCISE
- READ_SPEED
- READ_WEIGHT
- READ_HEIGHT
- READ_BLOOD_GLUCOSE
- READ_BLOOD_PRESSURE
- READ_HYDRATION
- READ_BODY_TEMPERATURE
- READ_RESPIRATORY_RATE
- READ_NUTRITION
- READ_MENSTRUATION
- READ_POWER
- READ_BASAL_BODY_TEMPERATURE
- READ_BODY_FAT
- READ_LEAN_BODY_MASS
- READ_BODY_WATER_MASS
- READ_BONE_MASS
Check permissions
To check permissions call checkHealthConnectPermissions:
void checkHealthConnectPermissions() {
HCRookHealthPermissionsManager.checkHealthConnectPermissions().then((permissionsGranted) {
// Update your UI
}).catchError((exception) {
// Handle error
});
}
The previous function will check for all permissions, to check if at least one permission is granted, call
checkHealthConnectPermissionsPartially:
void checkHealthConnectPermissionsPartially() {
HCRookHealthPermissionsManager.checkHealthConnectPermissionsPartially().then((permissionsPartiallyGranted) {
// Update your UI
}).catchError((error) {
// Handle error
});
}
Request permissions
To request permissions call requestHealthConnectPermissions:
void requestHealthConnectPermissions() {
HCRookHealthPermissionsManager.requestHealthConnectPermissions().then((requestPermissionsStatus) {
if (requestPermissionsStatus == RequestPermissionsStatus.alreadyGranted) {
// Permissions already granted, update your UI
} else {
// Wait for result in stream
}
}).catchError((error) {
// Handle error
});
}
This function will return a RequestPermissionsStatus with 2 possible values:
- alreadyGranted: The permissions are already granted thus no request was sent.
- requestSent: The permissions request was sent, and you can get notified if the permissions were granted or denied
using the
requestHealthConnectPermissionsUpdatesstream.
// 1.- Create a stream subscription
StreamSubscription<HealthConnectPermissionsSummary>? streamSubscription;
// 2.- Listen to stream
streamSubscription = HCRookHealthPermissionsManager.requestHealthConnectPermissionsUpdates.listen((permissionsSummary) {
// Updated your UI
});
// 3.- Request permissions
HCRookHealthPermissionsManager.requestHealthConnectPermissions().then((requestPermissionsStatus) {
if (requestPermissionsStatus == RequestPermissionsStatus.alreadyGranted) {
// Permissions already granted, update your UI
} else {
// Wait for result in stream
}
}).catchError((error) {
// Handle error
});
// 4.- Stop listening to the stream
streamSubscription?.cancel();
Health Connect permissions denied
If the user clicks cancel or navigates away from the permissions screen, Health Connect will consider it as a denial of permissions. If the user denies the permissions twice, your app will be blocked by Health Connect and your only option will be to open the Health Connect app and ask your users to grant permissions manually.
When your app is blocked, any permissions request will be ignored.
To solve this problem, we recommend including an Open Health Connect button in your permissions UI. This button will
use HCRookHealthPermissionsManager.openHealthConnectSettings() to open the Health Connect application.
void openHealthConnect() {
HCRookHealthPermissionsManager.openHealthConnectSettings().then((_) {
// Success
}).catchError((exception) {
// Handle error
});
}
Background read permissions
Health Connect now supports full background data reads, but it has a few requirements, first is that the user MUST grant
a new permission (READ_HEALTH_DATA_IN_BACKGROUND) and the second is that the user's device MUST have a Health Connect
application version that supports background reads.
You can use the function checkBackgroundReadStatus available on HCRookBackgroundSync to check both scenarios:
void checkBackgroundReadStatus() async {
try {
final backgroundReadStatus = await HCRookHealthPermissionsManager.checkBackgroundReadStatus();
// Update your UI
} catch (error) {
// Handle error
}
}
To request background read permission call requestHealthConnectPermissions, this function, in addition of requesting
for "normal" data types permissions will also ask for background reads permissions (if the device supports it, otherwise
this permission won't be included in the request). You will receive an update of the permission acceptation status in
the requestHealthConnectPermissionsUpdates stream, see the complete example here.
Customizing permissions
If you want to reduce the Health Connect permissions used by this SDK you can do it following the manifest merge documentation and the SDK will change the behavior of request/check permissions functions based on the declared permissions:
For example if you remove the READ_MENSTRUATION permission...
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission
android:name="android.permission.health.READ_MENSTRUATION"
tools:node="remove"/>
</manifest>
the functions checkHealthConnectPermissions and requestHealthConnectPermissions will check/request all permissions
excluding READ_MENSTRUATION
Note that this process only works for removing Health Connect permissions, adding a permission that is not included in the default list will do nothing.
Health Connect permissions are declared with the syntax: android.permission.health.READ.., to see the current Health Connect permissions go to you AndroidManifest and select the merged manifest tab.
If you are also implementing Apple Health on the IOS side the process is the opposite: you specify the permissions that you need, at the moment of requesting permissions, more information in the Apple Health Permissions section.
Revoke permissions
You can reset all granted Health Connect permissions back to their original state with revokeHealthConnectPermissions:
void revokeHealthConnectPermissions() {
HCRookHealthPermissionsManager.revokeHealthConnectPermissions().then((_) {
// Health Connect permissions revoked, restart the app to apply the changes
}).catchError((error) {
// Error revoking Health Connect permissions
});
}
You may notice that after calling this function the permissions are still granted, however they will be revoked the next time the app is closed (process stops).
Android permissions
Android permissions are the normal permission every non-health app may need, in this case we use the following permissions to track steps and/or automatically sync health data:
- POST_NOTIFICATIONS
- ACTIVITY_RECOGNITION
- FOREGROUND_SERVICE
- FOREGROUND_SERVICE_HEALTH
To check permissions call checkAndroidPermissions:
void checkAndroidPermissions() {
HCRookHealthPermissionsManager.checkAndroidPermissions().then((permissionsGranted) {
// Update your UI
}).catchError((exception) {
// Handle error
});
}
To request permissions call requestAndroidPermissions:
void requestAndroidPermissions() async {
try {
final requestPermissionsStatus = await HCRookHealthPermissionsManager.requestAndroidPermissions();
if (requestPermissionsStatus == RequestPermissionsStatus.alreadyGranted) {
// Permissions already granted, update your UI
} else {
// Wait for result in stream
}
} catch (error) {
// Handle error
}
}
You can use HCRookHealthPermissionsManager.shouldRequestAndroidPermissions(activity) to know if the
permissions dialog WILL BE displayed before calling requestAndroidPermissions and
manage this scenario with more anticipation.
This function will return a RequestPermissionsStatus with 2 possible values:
- alreadyGranted: The permissions are already granted thus no request was sent.
- requestSent: The permissions request was sent, and you can get notified if the permissions were granted or denied
using the
requestAndroidPermissionsUpdatesstream.
// 1.- Create a stream subscription
StreamSubscription<AndroidPermissionsSummary>? streamSubscription;
// 2.- Listen to stream
streamSubscription = HCRookHealthPermissionsManager.requestAndroidPermissionsUpdates.listen((permissionsSummary) {
// Updated your UI
});
// 3.- Request permissions
try {
final requestPermissionsStatus = await HCRookHealthPermissionsManager.requestAndroidPermissions();
if (requestPermissionsStatus == RequestPermissionsStatus.alreadyGranted) {
// Permissions already granted, update your UI
} else {
// Wait for result in stream
}
} catch (error) {
// Handle error
}
// 4.- Stop listening to the stream
streamSubscription?.cancel();
Android permissions denied
If a user denies a permission Android will not show a dialog the next time you ask for permissions,
use HCRookHealthPermissionsManager.shouldRequestAndroidPermissions() to check if the user has
previously denied the permissions and based on the result request permissions or navigate the user to your app's
settings.
void requestAndroidPermissions() async {
try {
final shouldRequestPermissions = await HCRookHealthPermissionsManager.shouldRequestAndroidPermissions();
if (shouldRequestPermissions) {
// Request permissions
} else {
// Open your application's settings
// Show a toast indicating your users that they must enable permissions manually
}
} catch (error) {
// Handle error
}
}
Optimization permissions
Some users want to have as much battery life as possible, so they have power saving mode always active, also some phone manufactures add their own energy restriction on top of Android's, these restrictions are mostly enabled by default and depending on the device will add a delay to our background services; Steps Counter and Background Sync or even stop them completely.
We have added mutiple optimization paths you can follow:
The following are optional permissions, you can use the Steps Counter and Background Sync components without these permission, however we recommend to add a button to ask this permission in a support page of your application so users can grant it if they are experiencing interruptions with the service.
Alarm permissions
The SDK uses the android.permission.SCHEDULE_EXACT_ALARM (pre-included in SDK's manifest) to improve the lifetime of
Background Services in battery constrained scenarios.
To check permissions call checkExactAlarmPermissions:
HCRookHealthPermissionsManager.checkExactAlarmPermissions().then((hasAlarmPermissions) {
// Success
}).catchError((error) {
// Handle error
});
To request permissions call requestExactAlarmPermissions:
HCRookHealthPermissionsManager.requestExactAlarmPermissions().then((requestPermissionsStatus) {
switch (requestPermissionsStatus) {
case RequestPermissionsStatus.alreadyGranted:
// Permissions already granted.
case RequestPermissionsStatus.requestSent:
// Because this is a special app access permission,
// there is no callback the recommended pattern is to call checkExactAlarmPermissions again.
}
}).catchError((error) {
// Handle error
});
On API 26–30 exact alarms are unrestricted so checkExactAlarmPermissions/requestExactAlarmPermissions will always
return true/RequestPermissionsStatus.requestSent.
Battery optimizations
To check if battery optimizations are disabled call checkBatteryOptimizationsDisabled:
HCRookHealthPermissionsManager.checkBatteryOptimizationsDisabled().then((batteryOptimizationsDisabled) {
// Success
}).catchError((error) {
// Handle error
});
To request disabling battery optimizations call requestDisableBatteryOptimizations:
HCRookHealthPermissionsManager.requestDisableBatteryOptimizations().then((requestPermissionsStatus) {
switch (requestPermissionsStatus) {
case RequestPermissionsStatus.alreadyGranted:
// Battery optimizations are already disabled
case RequestPermissionsStatus.requestSent:
// Because this is a special app access permission,
// there is no callback the recommended pattern is to call checkBatteryOptimizationsDisabled again.
}
}).catchError((error) {
// Handle error
});
Auto start
Brands like OPPO, One Plus and Xiaomi implement a custom Auto Start restriction that limits app's background execution.
You can check if the current device belongs to an OEM that enforces this restriction with requiresOemAutoStartSetup:
HCRookHealthPermissionsManager.requiresOemAutoStartSetup().then((hasAutoStartRestriction) {
// Success
}).catchError((error) {
// Handle error
});
Detection works by probing whether any known OEM settings screen resolves on the device. A true result means the OEM
management system exists it does not mean auto start is currently blocked for this specific app. Use this to decide
whether to prompt the user to open the OEM setup screen.
To open the brand-specific settings screen call openOemAutoStartSetup:
HCRookHealthPermissionsManager.openOemAutoStartSetup().then((requestPermissionsStatus) {
switch (requestPermissionsStatus) {
case RequestPermissionsStatus.alreadyGranted:
// The device has no OEM screen
case RequestPermissionsStatus.requestSent:
// Because this is a brand specific there is no way to know the user's choice.
}
}).catchError((error) {
// Handle error
});