Register for the free MongoDB.live developer conference July 13 and 14. Click to register now.
HomeLearnHow-toIntroduction to MongoDB Realm Sync for Android

Introduction to MongoDB Realm Sync for Android

Published: Jun 10, 2021

  • Realm
  • Mobile
  • Kotlin
  • ...

By Mohit Sharma

Rate this article

Welcome back! We really appreciate you coming back and showing your interest in Realm. This is a follow-up article to Introduction to Realm for Android. If you haven't read that yet, we recommend you go through it first.

This is a beginner-level article, where we introduce you to MongoDB Realm Sync. As always, we demonstrate its usage by building an Android app using the MVVM architecture.

#Prerequisites

You have created at least one app using Android Studio.

#What Are We Trying to Solve?

In the previous article, we learned that the Realm SDK is easy to use when working with a local database. But in the world of the internet we want to share our data, so how do we do that with the Realm Database?

MongoDB Realm Sync

Realm Sync is the solution to our problem. It's one of the many features provided by MongoDB Realm. It synchronizes the data between client-side Realms and the server-side cloud, MongoDB Atlas, without worrying about conflict resolution and error handling.

The illustration below demonstrates how MongoDB Realm has simplified the complex architecture:

Realm Sync has simplified the complex architecture

To demonstrate how to use MongoDB Realm Sync, we will extend our previous application, which tracks app views, to use Realm Sync.

#Step 1: Get the Base Code

Clone the original repo and rename it "HelloRealmSync."

#Step 2: Enable Realm Sync

Update the syncEnabled state as shown below in the Gradle file (at the module level):

1android {
2// few other things
3
4 realm {
5 syncEnabled = true
6 }
7}

Also, add the buildConfigField to buildTypes in the same file:

1buildTypes {
2
3 debug {
4 buildConfigField "String", "RealmAppId", "\"App Key\""
5 }
6
7 release {
8 buildConfigField "String", "RealmAppId", "\"App Key\""
9 }
10}

You can ignore the value of App Key for now, as it will be covered in a later step.

#Step 3: Set Up Your Free MongoDB Atlas Cloud Database

MongoDB cloud setup

Once this is done, we have a cloud database where all our mobile app data can be saved, i.e., MongoDB Atlas. Now we are left with linking our cloud database (in Atlas) with the mobile app.

#Step 4: Create a Realm App

MongoDB Realm App setup

In layman's terms, Realm apps on the MongoDB cloud are just links between the data flowing between the mobile apps (Realm SDK) and Atlas.

#Step 5: Add the Realm ID to the Android Project

Copy the Realm app ID and use it to replace App Key in the build.gradle file, which we added in Step 2.

Copying the MongoDB Realm App ID from the Realm UI

With this done, MongoDB Realm and your Android App are connected.

#Step 6: Enable Realm Sync and Authentication

MongoDB Realm is a very powerful tool and has a bunch of cool features from data security to its manipulation. This is more than sufficient for one application. Let's enable authentication and sync.

#But Why Authentication?

MongoDB Realm is designed to make apps secure by default, by not allowing an unknown user to access data.

We don't have to force a user to sign up for them to become a known user. We can enable anonymous authentication, which is a win-win for everyone.

So let's enable both of them:

Enabling anonymous authentication through the MongoDB Realm UIEnabling MongoDB Realm Sync using the MongoDB Realm UI

Let's quickly recap what we have done so far.

In the Android app:

  • Added Realm ID to the Gradle file.
  • Enabled Realm Sync.

In MongoDB Realm:

  • Set up account.
  • Created a free cluster for MongoDB Atlas.
  • Created a Realm app.
  • Enabled anonymous authentication.
  • Enabled sync.

Now, the final piece is to make the necessary modifications to our Android app.

#Step 7: Update the Android App Code

The only code change is to get an instance of the Realm database from the Realm app instance.

  1. Get a Realm app instance from which the Realm instance can be derived:

    1val realmSync by lazy {
    2 App(AppConfiguration.Builder(BuildConfig.RealmAppId).build())
    3}
  2. Update the creation of the View Model:

    1private val homeViewModel: HomeViewModel by navGraphViewModels(
    2R.id.mobile_navigation,
    3factoryProducer = {
    4 object : ViewModelProvider.Factory {
    5 @Suppress("UNCHECKED_CAST")
    6 override fun <T : ViewModel?> create(modelClass: Class<T>): T {
    7 val realmApp = (requireActivity().application as HelloRealmSyncApp).realmSync
    8 return HomeViewModel(realmApp) as T
    9 }
    10 }
    11})
  3. Update the View Model constructor to accept the Realm app instance:

    1class HomeViewModel(private val realmApp: App) : ViewModel() {
    2
    3}
  4. Update the updateData method in HomeViewModel:

    1private fun updateData() {
    2 _isLoading.postValue(true)
    3
    4 fun onUserSuccess(user: User) {
    5 val config = SyncConfiguration.Builder(user, user.id).build()
    6
    7 Realm.getInstanceAsync(config, object : Realm.Callback() {
    8 override fun onSuccess(realm: Realm) {
    9 realm.executeTransactionAsync {
    10 var visitInfo = it.where(VisitInfo::class.java).findFirst()
    11 visitInfo = visitInfo?.updateCount() ?: VisitInfo().apply {
    12 partition = user.id
    13 visitCount++
    14 }
    15 _visitInfo.postValue(it.copyFromRealm(visitInfo))
    16 it.copyToRealmOrUpdate(visitInfo)
    17 _isLoading.postValue(false)
    18 }
    19 }
    20
    21 override fun onError(exception: Throwable) {
    22 super.onError(exception)
    23 //TODO: Implementation pending
    24 _isLoading.postValue(false)
    25 }
    26 })
    27 }
    28
    29 realmApp.loginAsync(Credentials.anonymous()) {
    30 if (it.isSuccess) {
    31 onUserSuccess(it.get())
    32 } else {
    33 _isLoading.postValue(false)
    34 }
    35 }
    36}

In the above snippet, we are doing two primary things:

  1. Getting a user instance by signing in anonymously.
  2. Getting a Realm instance using SyncConfiguration.Builder.
1SyncConfiguration.Builder(user, user.id).build()

Where user.id is the partition key we defined in our MongoDB Realm Sync configuration (Step 6). In simple terms, partition key is an identifier that helps you to get the exact data as per client needs. For more details, please refer to the article on Realm partitioning strategies.

#Step 8: View Your Results in MongoDB Atlas

Viewing the results in Atlas using the MongoDB Atlas UI

Thank you for reading. You can find the complete working code in our GitHub repo.

If you have questions, please head to our developer community website where the MongoDB engineers and the MongoDB community will help you build your next big idea with MongoDB.

Rate this article

More from this series

Get Started With Realm and Android
  • Introduction to the Realm SDK for Android
  • Introduction to MongoDB Realm Sync for Android
MongoDB Icon
  • Developer Hub
  • Documentation
  • University
  • Community Forums

© MongoDB, Inc.