forked from mongodb/docs-realm
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
c6d39c8
commit 509f4d2
Showing
2 changed files
with
163 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,162 @@ | ||
.. _kotlin-background-sync: | ||
|
||
======================================== | ||
Sync Data in the Background - Kotlin SDK | ||
======================================== | ||
|
||
.. contents:: On this page | ||
:local: | ||
:backlinks: none | ||
:depth: 2 | ||
:class: singlecol | ||
|
||
|
||
If you need to sync data when your app isn't running, you can sync realms | ||
in a background process. | ||
|
||
Prerequisites | ||
------------- | ||
|
||
To get started with background synchronization, you need to add the | ||
following dependencies to your Android application: | ||
|
||
- :android:`androidx.work:work-runtime <reference/androidx/work/package-summary>` | ||
to enqueue jobs | ||
- :android:`androidx.concurrent:concurrent-futures <reference/androidx/concurrent/futures/package-summary>` | ||
to return job results from a background worker | ||
|
||
Example | ||
------- | ||
|
||
Background sync requires two things: | ||
|
||
- Synchronization logic | ||
- A scheduled job that periodically performs the sync logic | ||
|
||
Synchronization Logic | ||
~~~~~~~~~~~~~~~~~~~~~ | ||
|
||
First, write the custom logic that synchronizes your realm. Treat this | ||
logic as a standalone connection to your backend. As a result, you'll | ||
need to: | ||
|
||
- initialize the Realm SDK | ||
- authenticate a user to open the realm | ||
|
||
You can use a user's cached credentials if the user recently used the app. | ||
|
||
Open the realm, then use `SyncSession.downloadAllServerChanges() <{+kotlin-sync-prefix+}io.realm.kotlin.mongodb.sync/-sync-session/download-all-server-changes.html>`__ | ||
and `SyncSession.uploadAllLocalChanges() <{+kotlin-sync-prefix+}io.realm.kotlin.mongodb.sync/-sync-session/upload-all-local-changes.html>`__ | ||
to synchronize the realm fully with the backend. For more information, see | ||
:ref:`Manage Sync Sessions <kotlin-manage-sync-session>`. | ||
|
||
You can execute this logic as a background process using a subclass of | ||
:android:`CoroutineWorker <reference/kotlin/androidx/work/CoroutineWorker>`. | ||
Put your synchronization logic in the ``doWork()`` method of your worker: | ||
|
||
.. code-block:: kotlin | ||
:caption: Example RealmBackgroundWorker.kt | ||
|
||
package com.mongodb.app.worker | ||
|
||
import android.annotation.SuppressLint | ||
import android.content.Context | ||
import androidx.concurrent.futures.ResolvableFuture | ||
import androidx.work.CoroutineWorker | ||
import androidx.work.WorkerParameters | ||
import com.mongodb.app.app | ||
import com.mongodb.app.data.RealmSyncRepository | ||
import io.realm.kotlin.Realm | ||
import io.realm.kotlin.mongodb.syncSession | ||
|
||
class RealmBackgroundWorker(context: Context, workerParams: WorkerParameters) : | ||
CoroutineWorker(context, workerParams) { | ||
|
||
private lateinit var future: ResolvableFuture<Result> | ||
@SuppressLint("RestrictedApi") | ||
override suspend fun doWork(): Result { | ||
future = ResolvableFuture.create() | ||
|
||
// Get the realm configuration | ||
val syncRepository = RealmSyncRepository { session, error -> | ||
future.setException(error) | ||
} | ||
val config = syncRepository.getRealmConfiguration() | ||
|
||
// Check if user is logged-in | ||
if (app.currentUser?.loggedIn == true) { | ||
val realm = Realm.open(config) | ||
try { | ||
realm.syncSession.downloadAllServerChanges() | ||
realm.syncSession.uploadAllLocalChanges() | ||
} catch (e: InterruptedException) { | ||
e.printStackTrace() | ||
} | ||
} | ||
return future.get() | ||
} | ||
companion object { | ||
const val UNIQUE_WORK_NAME = "RealmBackgroundWorker" | ||
} | ||
} | ||
|
||
|
||
Worker | ||
~~~~~~ | ||
|
||
To create a worker that periodically performs background sync: | ||
|
||
1. Create a set of :android:`Constraints <reference/androidx/work/Constraints.Builder>` | ||
that specify the conditions required for your worker. Because synchronizing | ||
a realm uses data, you should consider only downloading changes in the | ||
background when the device is *not*: | ||
|
||
- low on battery | ||
- using a metered data source | ||
|
||
2. Specify how frequently your worker should execute. Your repeat interval | ||
depends on how frequently data updates in the realm and how often users | ||
open your application. | ||
|
||
- If the realm frequently updates throughout the day, consider setting a repeat | ||
interval of 1-3 hours. | ||
- If the realm only updates a small number of times each day, it's best to | ||
set a higher repeat interval and only background sync once or twice a day. | ||
|
||
3. Enqueue your worker with the Android OS. Assign it a unique identifier | ||
so that you can update the job in the future. | ||
|
||
.. tip:: | ||
|
||
You can create the background sync job inside an Application subclass in | ||
your app to guarantee that the logic only executes once every time your | ||
application runs. | ||
|
||
|
||
.. code-block:: kotlin | ||
:caption: Example worker | ||
|
||
// Create constraints that require a network connection and | ||
// that the device is not low on battery | ||
val constraints: Constraints = Constraints.Builder() | ||
.setRequiredNetworkType(NetworkType.UNMETERED) | ||
.setRequiresBatteryNotLow(true) | ||
.build() | ||
|
||
val backgroundRealmSync = | ||
PeriodicWorkRequestBuilder<RealmBackgroundWorker>( | ||
// Repeat every 12 hours | ||
12, TimeUnit.HOURS, | ||
// Execute job at any point during that 12-hour period | ||
12, TimeUnit.HOURS | ||
) | ||
.setConstraints(constraints) | ||
.build() | ||
|
||
// Enqueue the work job, replacing it with the most recent | ||
// version if we update it | ||
WorkManager.getInstance(this).enqueueUniquePeriodicWork( | ||
RealmBackgroundWorker.UNIQUE_WORK_NAME, | ||
ExistingPeriodicWorkPolicy.UPDATE, | ||
backgroundRealmSync | ||
) |