Docs Menu

Docs HomeRealm

Android With Kotlin Tutorial

On this page

  • Overview
  • Prerequisites
  • Start with the Template
  • Set up the Template App
  • Open the App
  • Explore the App Structure
  • Run the App
  • Check the Backend
  • Modify the Application
  • Add a New Property
  • Set the Priority when Creating a New Item
  • Run and Test
  • Change the Subscription
  • Conclusion
  • What's Next?

Realm provides a Kotlin SDK that allows you to create an Android mobile application with Kotlin. This tutorial is based on the Kotlin Flexible Sync Template App, named kotlin.todo.flex, which illustrates the creation of a Todo Item List management application. This application enables users to:

  • Register their email as a new user account.

  • Sign in to their account with their email and password (and sign out later).

  • View, create, modify, and delete todo items.

This tutorial adds functionality to the Template App. You will add a new Priority field to the existing Item model and update the Flexible Sync subscription to only show items within a range of priorities.

Depending on your experience with Kotlin, this tutorial should take around 30 minutes.

Note

Check Out the Quick Start

If you prefer to get started with your own application rather than follow a guided tutorial, check out the Kotlin Quick Start. It includes copyable code examples and the essential information that you need to set up an Atlas App Services backend.

  • Android Studio Bumblebee 2021.1.1 or higher.

  • JDK 11 or higher.

  • Kotlin Plugin for Android Studio, version 1.6.10 or higher.

  • An Android Virtual Device (AVD) using a supported CPU architecture.

This tutorial is based on the Kotlin SDK Flexible Sync Template App named kotlin.todo.flex. We start with the default app and build new features on it.

From Realm CLI, you can run the realm-cli apps create command to set up the backend and create the Kotlin base app. The following command creates a new app based on the kotlin.todo.flex template. With the options flags we can pass during creation, the command below creates an app:

  • Named "MyTutorialApp"

  • Deployed in the US-VA region

  • With the environment set to "development" (instead of production or QA)

realm-cli apps create -n MyTutorialApp --template kotlin.todo.flex \
--deployment-model global --location us-va --environment development

To learn more about the Template Apps and to install the Template App that this tutorial uses in the Atlas App Services UI, see template applications.

1

Navigate to the directory where the Realm CLI created the Template App. The client code is in a frontend/kotlin.todo.flex directory. Open the build.gradle.kts in Android Studio.

2

Take a few minutes to explore how the project organization while Android Studio indexes your project. Within the app/java/com.mongodb.app directory, you can see a few files worth noting :

File
Purpose
Item.kt
Defines the Realm object we store in the database.
ItemActivity.kt
UI-based class that opens a realm, and adds functionality for writing Items to the realm, logging a user out, and closing a realm.
ItemAdapter.kt
Adapter that displays a list of Items in an Android RecyclerView, allows users to check & uncheck items updating their status, and delete items.
LoginActivity.kt
UI-based class that provides functionality for registering a user and logging a user in.
TemplateApp.kt
Class that initializes the App Services App
3

Without making any changes to the code, you should be able to run the app on an Android Emulator using Android Studio or on a physical device.

When you installed the template app, the Realm CLI also set up a new backend for you and populated the realm.xml file with the correct app ID.

Run the app, register a new user account, and then add a new Item to your todo list.

4

Log in to Atlas App Services. In the Atlas tab, click on Browse Collections. In the list of databases, find and expand the todo database and then the Item collection. You should see the document you created in this collection.

1

We can add changes now that you have confirmed everything is working as expected. In this tutorial, we have decided that we want to add a "Priority" property to each Item so that we can filter Items by their priorities. The Priority property will be mapped to a PriorityLevel enum to constrain the possible values.

To do this, follow these steps:

  1. Open the build.gradle.kts file in Android Studio.

  2. Within the app/java/com.mongodb.app folder open the Item class file.

  3. Also, add a PriorityLevel enum above the Item class:

    enum class PriorityLevel(val priority: Int) {
    Severe(0),
    High(1),
    Medium(2),
    Low(3)
    }
  4. Add the following property to your Realm Object Model, before the constructor:

    var priority: Int = PriorityLevel.Low.priority

    This sets the default priority to 3, indicating that it is a low-priority todo item.

2
  1. Open the res/layout/create_item_dialog.xml file. This file defines the UI element that displays when a user clicks the '+' button to add a new todo item. Before the closing tag of the LinearLayout, add a Spinner that will enable the user to pick a priority level from a dropdown list.

    <Spinner
    android:id="@+id/spinner"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginLeft="20dp"
    android:layout_marginRight="20dp"
    android:minHeight="48dp"
    android:paddingLeft="5px"
    android:paddingRight="5px"
    tools:ignore="SpeakableTextPresentCheck" />
  2. Next, we will populate the spinner with user choices. Since the choices for priority levels are predetermined, we will provide them through the string resources file. Open the res/values/strings.xml file, and add the following string array before the closing of the 'resource' element.

    <string-array name="priorities">
    <item>Severe</item>
    <item>High</item>
    <item>Medium</item>
    <item>Low</item>
    </string-array>
  3. Now within the app/java/com.mongodb.app folder, open the ItemActivity file. Here we will load our string array into an instance of ArrayAdapter. First, add the following imports below the package com.mongodb.app:

    import android.widget.ArrayAdapter
    import android.widget.Spinner

    Next, add the following code in the onFabClicked() function, right before we call builder.setPositiveButton().

    val spinner = view.findViewById<View>(R.id.spinner) as Spinner
    val adapter = ArrayAdapter.createFromResource(
    this,
    R.array.priorities,
    android.R.layout.simple_spinner_item
    )
    adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
    spinner.adapter = adapter
  4. In the builder.setPositiveButton() function, we create a new Item and save it to the realm. Where we set the other Item properties, add a line of code to set the new Priority property:

    val item = Item(realmApp.currentUser!!.identity)
    item.priority = PriorityLevel.valueOf(spinner.selectedItem.toString()).priority
    item.summary = itemSummaryInput.text.toString()
    CoroutineScope(Dispatchers.IO).launch {
    realm.write {
    this.copyToRealm(item)
    }
    }
  5. Finally, we will use the Toast feedback to tell the user they have successfully created a new todo item with their summary and priority. Within the Toast.makeText() method alter the existing text to the following:

    Toast.makeText(
    this,
    "Item created: ${item.summary} with priority: ${item.priority}",
    Toast.LENGTH_SHORT
    ).show()
3

At this point, you can rerun the application. Log in using the account you created earlier in this tutorial. You will see the one Item you previously created. Add a new Item, and you will see that you can now set the priority. Choose High for the priority and save the Item.

Now switch back to the Atlas data page in your browser, and refresh the Item collection. You should now see the new Item with the priority field added and set to 1. The existing Item does not have a priority field.

Two items in a collection

Note

Why Didn't This Break Sync?

Adding a property to a Realm object is not a breaking change and therefore does not require a client reset. The template app has Development Mode enabled, so changes to the client Realm object are reflected in the server-side schema. For more information, see Enable or Disable Development Mode and Update Your Schema.

1

Within the app/java/com.mongodb.app folder, open the ItemActivity where we define the Flexible Sync subscription. The subscription defines which documents we sync with the user's device & account. Find the SyncConfiguration.Builder().initialSubscriptions() function that our application calls on start. Within the add() method, you can see that we are currently subscribing to all documents where the OwnerId property matches the authenticated user. We want to maintain that, but only sync Items that are marked as High or Severe priority.

As you may recall, the Priority field is of type int, where the highest priority ("Severe") has a value of 0, and the lowest priority ("Low") has a value of 3. We can make direct comparisons between an integer and the Priority property. To do so, edit the RQL statement to include documents where the priority is equal to or less than PriorityLevel.High (or 1), as shown here:

config = SyncConfiguration.Builder(user, setOf(Item::class))
.initialSubscriptions (rerunOnOpen = true) { realm ->
add(
realm.query<Item>(
"owner_id == $0 AND priority <= ${PriorityLevel.High.priority.toString()}",
user.identity
),
"User's Items",
updateExisting = true,
)
}

Notice we've set rerunOnOpen to true so that the closure is re-run every time the Realm is opened. We've also set updateExisting to true, so the Realm Kotlin SDK updates the previous query named "User's Item", rather than subscribing to two queries.

2

Run the application again. Log in using the account you created earlier in this tutorial. Here, you'll notice an error if you check your logs using Logcat, you will see an entry that looks something like this:

io.realm.kotlin.mongodb.exceptions.BadFlexibleSyncQueryException:
Client provided query with bad syntax: unsupported query for table
"Item": key "priority" is not a queryable field

This message tells us that we have added a field to our subscription without configuring Flexible Sync to use that field.

3
  1. Switch back to the Atlas page in your browser. Select the Atlas App Services tab and open the app you are using.

  2. In the left-hand navigation, choose Device Sync, and then click OK in the dialog box about Development Mode being enabled.

  3. Scroll down to the Select Queryable Fields section. In the dropdown labeled Select or create a queryable field, choose "priority". The priority field will be added to the fields shown:

    Priority field is now queryable.
  4. Save your changes.

4

Return to your mobile app. To ensure the subscription is re-run, log out the current user and then log in again. After an initial moment when Realm resyncs the document collection, you will see the new Item of High priority that you created.

If you want to test the functionality further, you can create Items of various priorities. You will see that a new Item with a lower priority briefly appears in the list of Items and then disappears. Realm creates the Item locally, syncs it with the backend, and then filters out the Item because it doesn't meet the subscription rules.

You'll note, too, that the document you initially created is not synced, because it has a priority of null. If you want this Item to be synced, you can edit the document in the Atlas UI and add a value for the priority field.

Adding a property to an existing Realm object is a non-breaking change, and Development Mode ensures that the schema change is reflected server-side. If you add or change a subscription to use an additional field, whether newly added or previously existent, you need to modify the Flexible Sync settings to enable querying against that field.

Note

Give Feedback

How did it go? Use the Give Feedback tab at the bottom right of the page to let us know if this tutorial was helpful or if you had any issues.

←  SwiftUI iOS TutorialXamarin (Android & iOS) Tutorial →
Give Feedback
© 2022 MongoDB, Inc.

About

  • Careers
  • Investor Relations
  • Legal Notices
  • Privacy Notices
  • Security Information
  • Trust Center
© 2022 MongoDB, Inc.