Skip to main content

Usage: Sync health data automatically

Schedule automatic syncs with every app launch or in background.

You can implement automatic syncs using any of the following:

  • Background Sync: Syncs every hour without opening the app, recommended if your project supports Android 15 (SDK 35).
  • Yesterday Sync: Syncs every time you call it on foreground, recommended if your project is still on Android 14 (SDK 34) or lower.

You should not use them at the same time as that could negatively affect your Health Connect request quota, however you can use them conditionally to cover edge cases like a user whose device does not support Background Sync, in that case using Yesterday Sync will ensure that data is synced when your app is in foreground.

Background sync

Background Sync allows to schedule an automatic syncs every hour in the background.

The following table describes Background Sync frequency of synchronization and historical range of each Health structure:

Health structureFrequencyHistorical range
Sleep SummaryOnce per day29 days in the past until yesterday
Body SummaryOnce per day29 days in the past until yesterday
Physical SummaryOnce per day29 days in the past until yesterday
Physical ActivityOnce per hour29 days in the past until today
StepsOnce per hourToday
CaloriesOnce per hourToday
Body metricsOnce per hourToday
Heart rateOnce per hourToday
OxygenationOnce per hourToday
TemperatureOnce per hourToday
HydrationOnce per hourToday
NutritionOnce per hourToday
Blood pressureOnce per hourToday
Blood glucoseOnce per hourToday

Permissions

To use Background Sync you will need:

  • Health Connect permissions: Go to the main Health Connect Permissions section to see the implementation.
  • Background read permissions: Go to the main Background Read permissions section to see the implementation.
info

Background Sync also requires a user id, so it's possible that the first time nothing will happen, only after a user id is configured and all necessary permissions are granted the automatic sync will happen within the next hour.

Usage

To schedule a background sync for every hour call enableBackground:

void enableBackgroundSync() async {
try {
await HCRookBackgroundSync.enableBackground(enableNativeLogs: isDebug);

// Background sync enabled
} catch (error) {
// Handle error
}
}

Is NOT harmful to call enableBackground in the main method:

void main() {
// Ensure that the plugin is ready
WidgetsFlutterBinding.ensureInitialized();

if (Platform.isAndroid) {
HCRookBackgroundSync.enableBackground(enableNativeLogs: isDebug).then((_) {
// Success
}).catchError((error) {
// Failure
});
} else {
AHRookBackgroundSync.enableBackground(
clientUUID: Secrets.clientUUID,
secretKey: Secrets.secretKey,
environment: rookEnvironment,
enableNativeLogs: isDebug,
).then((_) {
// Success
}).catchError((error) {
// Failure
});
}

runApp(App())
}
tip

It's a good practice to ask your users if they want to enable this behaviour, then save their preference in local storage and call enableBackground conditionally.

info

Once started Background Sync will attempt to sync all historic data, and will stop after it finishes or until the Health Connect request quota is exceeded.

To cancel any scheduled background sync call disableBackground:

void disableBackgroundSync() async {
try {
await HCRookBackgroundSync.disableBackground();

// Background sync disabled
} catch (error) {
// Handle error
}
}

If you want to check the current state of Background Sync call isScheduled or isScheduledUpdates (Experimental):

void checkBackgroundSyncState() async {
try {
final isScheduled = await HCRookBackgroundSync.isScheduled();

// Update your UI
} catch (error) {
// Handle error
}
}
// 1.- Create a stream subscription
StreamSubscription<bool>? streamSubscription;

// 2.- Listen to stream
streamSubscription = HCRookBackgroundSync.isScheduledUpdates.listen((isScheduled) {
// Update UI
});

// 3.- Stop listening to the stream
streamSubscription?.cancel();
danger

Don't use isScheduled or isScheduledUpdates to decide if you should call enableBackground, if you do this future improvements to the Background Sync behavior may not be applied, the "isScheduled" functions are only meant for UI related purposes.

Execution/Skip conditions

Each periodic execution of Background Sync will check for some requirements, and will skip the execution if one the following conditions is true:

  • The device battery is low.
  • The device storage is low.
  • The device is not connected to the internet.
  • The userID hasn't been configured.
  • The most recent request exceeded the Health Connect request quota.
  • The user hasn't granted Health Connect Permissions.
  • The user hasn't granted Background Read Permissions.
  • There is an error initializing the SDK.

Yesterday sync

HCRookYesterdaySyncManager allows to launch 29 days historic health data synchronizations.

The following table describes Yesterday sync frequency of synchronization and historical range of each Health structure:

Health structureFrequencyHistorical range
Sleep SummaryEach time scheduleYesterdaySync is called29 days in the past until yesterday
Body SummaryEach time scheduleYesterdaySync is called29 days in the past until yesterday
Physical SummaryEach time scheduleYesterdaySync is called29 days in the past until yesterday
Physical ActivityEach time scheduleYesterdaySync is called29 days in the past until today
StepsEach time scheduleYesterdaySync is calledToday
CaloriesEach time scheduleYesterdaySync is calledToday
Body metricsEach time scheduleYesterdaySync is calledToday
Heart rateEach time scheduleYesterdaySync is calledToday
OxygenationEach time scheduleYesterdaySync is calledToday
TemperatureEach time scheduleYesterdaySync is calledToday
HydrationEach time scheduleYesterdaySync is calledToday
NutritionEach time scheduleYesterdaySync is calledToday
Blood pressureEach time scheduleYesterdaySync is calledToday
Blood glucoseEach time scheduleYesterdaySync is calledToday

To sync Health Data automatically you can use the scheduleYesterdaySync method in your app's initialization phase. The following example uses the focus_detector package:

@override
Widget build(BuildContext context) {
return FocusDetector(
onFocusGained: attemptToEnableYesterdaySync,
child: Column(
children: [
],
),
);
}

void attemptToEnableYesterdaySync() {
SharedPreferences.getInstance().then((prefs) {
final userAcceptedYesterdaySync = prefs.getBool("ACCEPTED_YESTERDAY_SYNC") ?? false;

if (userAcceptedYesterdaySync) {
HCRookYesterdaySyncManager.scheduleYesterdaySync(
enableNativeLogs: isDebug,
clientUUID: Secrets.clientUUID,
secretKey: Secrets.secretKey,
environment: rookEnvironment,
);
} else {
// The user did not accept the yesterday sync feature
}
});
}
tip

We recommend you to ask your users if they want to enable this behaviour, then save their preference in local storage and call scheduleYesterdaySync conditionally.

info

Once started rookYesterdaySync will attempt to sync all historic data, and it will shut down itself after it finishes or until the Health Connect request quota is exceeded.

danger

scheduleYesterdaySync is intended to be called once in your app, preferably once the user has opened the app as part of the application initialization phase.

Permissions

To use rookYesterdaySync you will need:

info

scheduleYesterdaySync also requires a user id, so it's possible that the first time you launch your app nothing will happen, only after a user id is configured and all necessary permissions are granted the automatic sync will happen the next time the app is launched.

Customizing the foreground service notification

To sync health data automatically a Foreground Service is used, this service requires a notification to be displayed until the synchronization finishes.

To use your own resources you need to reference them in the AndroidManifest.xml file:


<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application>
<meta-data
android:name="io.tryrook.service.notification.SYNC_ICON"
android:resource="@drawable/my_custom_icon"/>

<meta-data
android:name="io.tryrook.service.notification.SYNC_TITLE"
android:resource="@string/my_custom_title"/>

<meta-data
android:name="io.tryrook.service.notification.SYNC_CONTENT"
android:resource="@string/my_custom_content"/>
</application>
</manifest>
info

Starting on Android 13 (SDK 33) this notification can be dismissed without finishing the service associated with it, then the service will be displayed in the active apps section (This may vary depending on device brand).

Launch/Stop conditions

scheduleYesterdaySync won't start or will stop if one the following conditions is true:

  • The device battery is low.
  • The device storage is low.
  • The device is not connected to the internet.
  • The userID hasn't been configured.
  • The most recent request exceeded the Health Connect request quota.
  • The device has previously exceeded the Health Connect request quota and less than 60 minutes have passed.
  • The user hasn't granted Health Connect Permissions.
  • There is an error initializing the SDK.
  • The user hasn't granted Android Permissions.