Skip to main content

Usage: Sync health data automatically

Schedule automatic syncs with every app launch or in background.

Background sync

note

Background Sync is only available in 2.0.0-alpha01+ version.

Background Sync is a preconfigured component to execute an automatic syncs every hour in the background.

RookBackgroundSyncManager

You can create an instance of RookBackgroundSyncManager:

  • context - Application context
val rookBackgroundSyncManager = RookBackgroundSyncManager(context)

Usage

To schedule a background sync for every hour call schedule:

rookBackgroundSyncManager.schedule(enableLogs = isDebug)

We recommend calling 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
RookBackgroundSyncManager.schedule(this, enableLogs = isDebug)
}
}
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 schedule 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 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
}
}
}
danger

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.

info

There are alternative versions of schedule, cancel, isScheduled and isScheduledFlow which accept a Context available in the companion object of RookBackgroundSyncManager.

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.

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 device has previously exceeded the Health Connect request quota and the recovery timestamp hasn't been reached.
  • The user hasn't granted Health Connect Permissions.
  • The most recent request exceeded the Health Connect request quota.
  • The userID hasn't been configured.
  • There is an error initializing the SDK.

Yesterday sync

RookYesterdaySync is a preconfigured component to execute an automatic sync for the past 29-day summaries and activities. To create a RookYesterdaySync instance use the rookYesterdaySync delegate providing:

  • enableLogs: See the logs generated by this SDK.
  • clientUUID
  • secretKey
  • environment
  • state: Lifecycle state to trigger the sync process at. Supported values: CREATED (Default), STARTED, RESUMED.
class HomeActivity : AppCompatActivity() {

private val rookYesterdaySync by rookYesterdaySync(
enableLogs = true,
clientUUID = CLIENT_UUID,
secretKey = SECRET_KEY,
environment = environment,
state = Lifecycle.State.CREATED,
)

override fun onCreate(savedInstanceState: Bundle?) {
// Must be before super.onCreate(savedInstanceState)
// Using userAcceptedYesterdaySync we ensure to enable the YesterdaySync feature only if the user accepted it
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && homeViewModel.userAcceptedYesterdaySync) {
rookYesterdaySync.enable(this)
}

super.onCreate(savedInstanceState)
}
}
tip

We recommend you to ask your users if they want to enable this behaviour, then save their preference in local storage and call enable 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

rookYesterdaySync is intended to be used once in your app, if your app has multiple activities, try to configure rookYesterdaySync in the Home/Main activity that you display when your app's users are logged in.

Permissions

To use rookYesterdaySync you will need:

info

rookYesterdaySync 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.

The notification has the next default values:

  • Icon
  • Title: Sync service
  • Content: Syncing your health data…

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

rookYesterdaySync 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 user hasn't granted Android Permissions (POST_NOTIFICATIONS, FOREGROUND_SERVICE, FOREGROUND_SERVICE_HEALTH).
  • The device has previously exceeded. the Health Connect request quota and the recovery timestamp hasn't been reached.
  • The user hasn't granted Health Connect Permissions.
  • The most recent request exceeded the Health Connect request quota.
  • The userID hasn't been configured.
  • There is an error initializing the SDK.