Usage: Sync health data automatically
Schedule automatic syncs in background.
Background sync
Background Sync allows to schedule an automatic syncs every hour in the background.
You can call its functions by creating an instance with a context:
val rookBackgroundSyncManager = RookBackgroundSyncManager(context)
rookBackgroundSyncManager.doSomething()
Or using the Companion object and providing a context with each call:
RookBackgroundSyncManager.doSomething(context)
Each time background sync is triggered the following operations will happen:
- Sync today events:
- Activity
- Steps
- Calories
- Body Metrics
- Heart Rate
- Oxygenation
- Temperature
- Hydration
- Nutrition
- Blood Pressure
- Blood Glucose
- Sync today summaries
- Sleep
- If at least 4 hours have passed since the last successful sync
- If the "new" data is equal to the previous sync it won't be synced again.
- Sleep
- Sync yesterday summaries
- Sleep
- If at least 4 hours have passed since the last successful sync
- If the "new" data is equal to the previous sync it won't be synced again.
- Physical
- If at least 4 hours have passed since the last successful sync
- If the "new" data is equal to the previous sync it won't be synced again.
- Body
- If at least 4 hours have passed since the last successful sync
- If the "new" data is equal to the previous sync it won't be synced again.
- Sleep
- Sync historic data
- Activity events
- If not synced yet 29 days, starting from yesterday
- Sleep summary
- If not synced yet 29 days, starting from yesterday
- Physical summary
- If not synced yet 29 days, starting from yesterday
- Body summary
- If not synced yet 29 days, starting from yesterday
- Activity events
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.
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 schedule:
- enableLogs - Enable logcat logging.
- cancelAndReschedule - If true, cancels any previously scheduled or currently running background sync and schedules a new one.
rookBackgroundSyncManager.schedule(enableLogs = isDebug)
We recommend adding an extra call to schedule in the onCreate callback of your Application class:
class MyAplication : Application() {
override fun onCreate() {
super.onCreate()
// It's a good practice to ask your users if they want to enable this behaviour
// and wrap this line inside an if which checks a preferences-stored flag
if (userAllowedBackgroundSync) {
RookBackgroundSyncManager.schedule(this, enableLogs = isDebug)
}
}
}
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 schedule conditionally.
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 cancel:
rookBackgroundSyncManager.cancel()
If you want to check the current state of Background Sync call isScheduled or isScheduledFlow (Experimental):
fun howToCheckBackgroundSyncState() {
// Get latest state
coroutineScope.launch {
val isScheduled: Boolean = rookBackgroundSyncManager.isScheduled().getOrDefault(defaultValue = false)
// Update UI
}
// Receive real-time updates
@OptIn(ExperimentalRookApi::class)
viewModelScope.launch {
rookBackgroundSyncManager.isScheduledFlow().collectLatest { isScheduled: Boolean ->
// Update UI
}
}
}
Don't use isScheduled or isScheduledFlow to decide if you should call schedule, 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.
Progress updates
Register a BroadcastReceiver with the ACTION_BACKGROUND_SYNC action to get progress updates:
This action will always contain the EXTRA_BACKGROUND_SYNC_PROGRESS extra which can be converted to a
HCBackgroundSyncProgress enum. If HCBackgroundSyncProgress.FAILED is received you can also check for the
EXTRA_BACKGROUND_SYNC_FAILURE_REASON extra to get the error message.
// 1.- Create broadcast receiver
private val broadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(intentContext: Context?, intent: Intent?) {
val progressId = intent?.getIntExtra(
/* name = */ RookBackgroundSyncManager.EXTRA_BACKGROUND_SYNC_PROGRESS,
/* defaultValue = */ -1,
) ?: -1
val progress = HCBackgroundSyncProgress.fromId(progressId)
if (progress == HCBackgroundSyncProgress.FAILED) {
val message = intent?.getStringExtra(
/* name = */ RookBackgroundSyncManager.EXTRA_BACKGROUND_SYNC_FAILURE_REASON,
)
}
// Update your UI
}
}
// 2.- Register broadcast receiver (onCreate)
ContextCompat.registerReceiver(
context,
broadcastReceiver,
IntentFilter(RookBackgroundSyncManager.ACTION_BACKGROUND_SYNC),
ContextCompat.RECEIVER_EXPORTED,
)
// 3.- Unregister broadcast receiver (onDestroy)
context.unregisterReceiver(broadcastReceiver)
A typical updates flow will look like below:
- Sync started,
STARTEDwill be broadcasted. - Check requirements
- If Background Read or No data types permissions are granted
INSUFFICIENT_PERMISSIONSwill be broadcasted.- Sync failed,
FAILEDwill be broadcasted.
- Sync failed,
- If Background Read or No data types permissions are granted
- Data Sync consist of 4 stages;
SYNCING_TODAY_EVENTS,SYNCING_TODAY_SUMMARIES,SYNCING_YESTERDAY_SUMMARIESandSYNCING_HISTORIC_SUMMARIES_AND_ACTIVITYwill be broadcasted.- If in any of the previously mentioned stages the request quota of Health Connect is reached
BLOCKEDwill be broadcasted.- Sync failed,
FAILEDwill be broadcasted.
- Sync failed,
- If in any of the previously mentioned stages has an unrecoverable error
FAILEDwill be broadcasted.
- If in any of the previously mentioned stages the request quota of Health Connect is reached
- Sync completed,
FINISHEDwill be broadcasted.
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.