Docs Menu
Docs Home
/ /
Atlas Device SDKs

Quick Start with Sync - Java SDK

On this page

  • Initialize Realm
  • Initialize the App
  • Define Your Object Model
  • Authenticate a User
  • Open a Realm
  • Create, Read, Update, and Delete Objects
  • Watch for Changes
  • Log Out
  • Complete Example
  • Output

Tip

This Guide uses Device Sync

This guide helps you get started with an Android application that communicates with an App backend. The App provides features like Sync, Realm Functions, and user management. If your application requires only local database functionality, check out the Quick Start (Local-only) guide.

This page contains information to quickly get Atlas App Services integrated into your app. Before you begin, ensure you have:

Before you can use Realm in your app, you must initialize the Realm library. Your application should initialize Realm just once each time the application runs.

To initialize the Realm library, provide an Android context to the Realm.init() static function. You can provide an Activity, Fragment, or Application context for initialization with no difference in behavior. You can initialize the Realm library in the onCreate() method of an application subclass to ensure that you only initialize Realm once each time the application runs.

Realm.init(this); // context, usually an Activity or Application
Realm.init(this) // context, usually an Activity or Application

Tip

Register Your Application Subclass in the Android Manifest

If you create your own Application subclass, you must add it to your application's AndroidManifest.xml to execute your custom application logic. Set the android.name property of your manifest's application definition to ensure that Android instantiates your Application subclass before any other class when a user launches your application.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.mongodb.example">
<application
android:name=".MyApplicationSubclass"
...
/>
</manifest>

To use App Services features such as authentication and sync, access your App Services App using your App ID. You can find your App ID in the App Services UI.

app = new App(new AppConfiguration.Builder(appID)
.build());
val appID : String = YOUR_APP_ID;
app = App(AppConfiguration.Builder(appID)
.build())

Note

Android Studio Errors?

If Android Studio does not recognize the Realm, App, or AppConfiguration types, there could be a problem with the your Gradle build configuration. To fix the issue:

  • Clean your project with Build > Clean Project

  • Rebuild your project based on your updated build.gradle file with Build > Rebuild Project

  • Revisit the Install the Java SDK guide to make sure that you installed the dependencies correctly.

Your application's data model defines the structure of data stored within Realm and synchronized to and from App Services. You can define your application's data model in two ways:

This quick start uses the latter approach, which defines your schema using classes in your mobile application code. To define your App's object model in this way, you need to enable Development Mode.

Once you've enabled Development Mode, add the following class definitions to your application code:

import io.realm.RealmObject;
import io.realm.annotations.PrimaryKey;
import io.realm.annotations.RealmClass;
import io.realm.annotations.Required;
import org.bson.types.ObjectId;
public class Task extends RealmObject {
@PrimaryKey
private ObjectId _id = new ObjectId();
private String name = "Task";
@Required
private String status = TaskStatus.Open.name();
public void setStatus(TaskStatus status) {
this.status = status.name();
}
public String getStatus() {
return this.status;
}
public ObjectId get_id() {
return _id;
}
public void set_id(ObjectId _id) {
this._id = _id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Task(String _name) {
this.name = _name;
}
public Task() {}
}
public enum TaskStatus {
Open("Open"),
InProgress("In Progress"),
Complete("Complete");
String displayName;
TaskStatus(String displayName) {
this.displayName = displayName;
}
}
enum class TaskStatus(val displayName: String) {
Open("Open"),
InProgress("In Progress"),
Complete("Complete"),
}
open class Task(_name: String = "Task", project: String = "My Project") : RealmObject() {
@PrimaryKey
var _id: ObjectId = ObjectId()
var name: String = _name
@Required
var status: String = TaskStatus.Open.name
var statusEnum: TaskStatus
get() {
// because status is actually a String and another client could assign an invalid value,
// default the status to "Open" if the status is unreadable
return try {
TaskStatus.valueOf(status)
} catch (e: IllegalArgumentException) {
TaskStatus.Open
}
}
set(value) { status = value.name }
}

When you have enabled anonymous authentication in the App Services UI, users can immediately log into your app without providing any identifying information:

Credentials credentials = Credentials.anonymous();
app.loginAsync(credentials, result -> {
if (result.isSuccess()) {
Log.v("QUICKSTART", "Successfully authenticated anonymously.");
User user = app.currentUser();
String partitionValue = "My Project";
SyncConfiguration config = new SyncConfiguration.Builder(
user,
partitionValue)
.build();
uiThreadRealm = Realm.getInstance(config);
addChangeListenerToRealm(uiThreadRealm);
FutureTask<String> task = new FutureTask(new BackgroundQuickStart(app.currentUser()), "test");
ExecutorService executorService = Executors.newFixedThreadPool(2);
executorService.execute(task);
} else {
Log.e("QUICKSTART", "Failed to log in. Error: " + result.getError());
}
});
val credentials: Credentials = Credentials.anonymous()
app.loginAsync(credentials) {
if (it.isSuccess) {
Log.v("QUICKSTART", "Successfully authenticated anonymously.")
val user: User? = app.currentUser()
val partitionValue: String = "My Project"
val config = SyncConfiguration.Builder(user, partitionValue)
.build()
uiThreadRealm = Realm.getInstance(config)
addChangeListenerToRealm(uiThreadRealm)
val task : FutureTask<String> = FutureTask(BackgroundQuickStart(app.currentUser()!!), "test")
val executorService: ExecutorService = Executors.newFixedThreadPool(2)
executorService.execute(task)
} else {
Log.e("QUICKSTART", "Failed to log in. Error: ${it.error}")
}
}

Realm provides many additional ways to authenticate, register, and link users.

Once you have enabled Sync and authenticated a user, you can open a synced realm. Use SyncConfiguration to control the specifics of how your application synchronizes data with App Services, including timeouts, synchronous reads and writes on the UI thread, and more.

String partitionValue = "My Project";
SyncConfiguration config = new SyncConfiguration.Builder(
user,
partitionValue)
.build();
Realm backgroundThreadRealm = Realm.getInstance(config);
val partitionValue: String = "My Project"
val config = SyncConfiguration.Builder(user, partitionValue)
.build()
val backgroundThreadRealm : Realm = Realm.getInstance(config)

Once you have opened a realm, you can modify the objects within that realm in a write transaction block.

Important

Synchronous Reads and Writes on the UI Thread

By default, you can only read or write to a realm in your application's UI thread using asynchronous transactions. That is, you can only use Realm methods whose name ends with the word Async in the main thread of your Android application unless you explicitly allow the use of synchronous methods.

This restriction exists for the benefit of your application users: performing read and write operations on the UI thread can lead to unresponsive or slow UI interactions, so it's usually best to handle these operations either asynchronously or in a background thread. However, if your application requires the use of synchronous realm reads or writes on the UI thread, you can explicitly allow the use of synchronous methods with the following SyncConfiguration options:

SyncConfiguration config = new SyncConfiguration.Builder(app.currentUser(), PARTITION)
.allowQueriesOnUiThread(true)
.allowWritesOnUiThread(true)
.build();
Realm.getInstanceAsync(config, new Realm.Callback() {
@Override
public void onSuccess(Realm realm) {
Log.v(
"EXAMPLE",
"Successfully opened a realm with reads and writes allowed on the UI thread."
);
}
});
val config = SyncConfiguration.Builder(app.currentUser(), PARTITION)
.allowQueriesOnUiThread(true)
.allowWritesOnUiThread(true)
.build()
Realm.getInstanceAsync(config, object : Realm.Callback() {
override fun onSuccess(realm: Realm) {
Log.v("EXAMPLE", "Successfully opened a realm with reads and writes allowed on the UI thread.")
}
})

To create a new Task, instantiate an instance of the Task class and add it to the realm in a write block:

Task task = new Task("New Task");
backgroundThreadRealm.executeTransaction (transactionRealm -> {
transactionRealm.insert(task);
});
val task : Task = Task("New Task", partitionValue)
backgroundThreadRealm.executeTransaction { transactionRealm ->
transactionRealm.insert(task)
}

You can retrieve a live collection of all items in the realm:

// all tasks in the realm
RealmResults<Task> tasks = backgroundThreadRealm.where(Task.class).findAll();
// all tasks in the realm
val tasks : RealmResults<Task> = backgroundThreadRealm.where<Task>().findAll()

You can also filter that collection using a filter:

// you can also filter a collection
RealmResults<Task> tasksThatBeginWithN = tasks.where().beginsWith("name", "N").findAll();
RealmResults<Task> openTasks = tasks.where().equalTo("status", TaskStatus.Open.name()).findAll();
// you can also filter a collection
val tasksThatBeginWithN : List<Task> = tasks.where().beginsWith("name", "N").findAll()
val openTasks : List<Task> = tasks.where().equalTo("status", TaskStatus.Open.name).findAll()

To modify a task, update its properties in a write transaction block:

Task otherTask = tasks.get(0);
// all modifications to a realm must happen inside of a write block
backgroundThreadRealm.executeTransaction( transactionRealm -> {
Task innerOtherTask = transactionRealm.where(Task.class).equalTo("_id", otherTask.get_id()).findFirst();
innerOtherTask.setStatus(TaskStatus.Complete);
});
val otherTask: Task = tasks[0]!!
// all modifications to a realm must happen inside of a write block
backgroundThreadRealm.executeTransaction { transactionRealm ->
val innerOtherTask : Task = transactionRealm.where<Task>().equalTo("_id", otherTask._id).findFirst()!!
innerOtherTask.status = TaskStatus.Complete.name
}

Finally, you can delete a task by calling the deleteFromRealm() method in a write transaction block:

Task yetAnotherTask = tasks.get(0);
ObjectId yetAnotherTaskId = yetAnotherTask.get_id();
// all modifications to a realm must happen inside of a write block
backgroundThreadRealm.executeTransaction( transactionRealm -> {
Task innerYetAnotherTask = transactionRealm.where(Task.class).equalTo("_id", yetAnotherTaskId).findFirst();
innerYetAnotherTask.deleteFromRealm();
});
val yetAnotherTask: Task = tasks.get(0)!!
val yetAnotherTaskId: ObjectId = yetAnotherTask._id
// all modifications to a realm must happen inside of a write block
backgroundThreadRealm.executeTransaction { transactionRealm ->
val innerYetAnotherTask : Task = transactionRealm.where<Task>().equalTo("_id", yetAnotherTaskId).findFirst()!!
innerYetAnotherTask.deleteFromRealm()
}

You can watch a realm, collection, or object for changes by attaching a custom OrderedRealmCollectionChangeListener with the addChangeListener() method:

// all tasks in the realm
RealmResults<Task> tasks = uiThreadRealm.where(Task.class).findAllAsync();
tasks.addChangeListener(new OrderedRealmCollectionChangeListener<RealmResults<Task>>() {
@Override
public void onChange(RealmResults<Task> collection, OrderedCollectionChangeSet changeSet) {
// process deletions in reverse order if maintaining parallel data structures so indices don't change as you iterate
OrderedCollectionChangeSet.Range[] deletions = changeSet.getDeletionRanges();
for (OrderedCollectionChangeSet.Range range : deletions) {
Log.v("QUICKSTART", "Deleted range: " + range.startIndex + " to " + (range.startIndex + range.length - 1));
}
OrderedCollectionChangeSet.Range[] insertions = changeSet.getInsertionRanges();
for (OrderedCollectionChangeSet.Range range : insertions) {
Log.v("QUICKSTART", "Inserted range: " + range.startIndex + " to " + (range.startIndex + range.length - 1)); }
OrderedCollectionChangeSet.Range[] modifications = changeSet.getChangeRanges();
for (OrderedCollectionChangeSet.Range range : modifications) {
Log.v("QUICKSTART", "Updated range: " + range.startIndex + " to " + (range.startIndex + range.length - 1)); }
}
});
// all tasks in the realm
val tasks : RealmResults<Task> = realm.where<Task>().findAllAsync()
tasks.addChangeListener(OrderedRealmCollectionChangeListener<RealmResults<Task>> { collection, changeSet ->
// process deletions in reverse order if maintaining parallel data structures so indices don't change as you iterate
val deletions = changeSet.deletionRanges
for (i in deletions.indices.reversed()) {
val range = deletions[i]
Log.v("QUICKSTART", "Deleted range: ${range.startIndex} to ${range.startIndex + range.length - 1}")
}
val insertions = changeSet.insertionRanges
for (range in insertions) {
Log.v("QUICKSTART", "Inserted range: ${range.startIndex} to ${range.startIndex + range.length - 1}")
}
val modifications = changeSet.changeRanges
for (range in modifications) {
Log.v("QUICKSTART", "Updated range: ${range.startIndex} to ${range.startIndex + range.length - 1}")
}
})

Once logged in, you can log out:

app.currentUser().logOutAsync(result -> {
if (result.isSuccess()) {
Log.v("QUICKSTART", "Successfully logged out.");
} else {
Log.e("QUICKSTART", "Failed to log out, error: " + result.getError());
}
});
app.currentUser()?.logOutAsync() {
if (it.isSuccess) {
Log.v("QUICKSTART", "Successfully logged out.")
} else {
Log.e("QUICKSTART", "Failed to log out, error: ${it.error}")
}
}

Run the complete example by replacing the appId with your realm app ID. If you're running this project in a fresh Android Studio project, you can copy and paste this file into your application's MainActivity -- just remember to:

  • change the package declaration so it matches your project

  • replace the App ID placeholder with your App's App ID

  • update the import statements for Task and TaskStatus if you're using Java

Task.java
import io.realm.RealmObject;
import io.realm.annotations.PrimaryKey;
import io.realm.annotations.RealmClass;
import io.realm.annotations.Required;
import org.bson.types.ObjectId;
public class Task extends RealmObject {
@PrimaryKey
private ObjectId _id = new ObjectId();
private String name = "Task";
@Required
private String status = TaskStatus.Open.name();
public void setStatus(TaskStatus status) {
this.status = status.name();
}
public String getStatus() {
return this.status;
}
public ObjectId get_id() {
return _id;
}
public void set_id(ObjectId _id) {
this._id = _id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Task(String _name) {
this.name = _name;
}
public Task() {}
}
TaskStatus.java
public enum TaskStatus {
Open("Open"),
InProgress("In Progress"),
Complete("Complete");
String displayName;
TaskStatus(String displayName) {
this.displayName = displayName;
}
}
MainActivity.java
import io.realm.OrderedCollectionChangeSet;
import org.bson.types.ObjectId;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import android.util.Log;
import io.realm.OrderedRealmCollectionChangeListener;
import io.realm.Realm;
import io.realm.RealmResults;
import io.realm.mongodb.App;
import io.realm.mongodb.AppConfiguration;
import io.realm.mongodb.Credentials;
import io.realm.mongodb.User;
import io.realm.mongodb.sync.SyncConfiguration;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
import com.mongodb.realm.examples.model.Task;
import com.mongodb.realm.examples.model.TaskStatus;
public class MainActivity extends AppCompatActivity {
Realm uiThreadRealm;
App app;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Realm.init(this); // context, usually an Activity or Application
app = new App(new AppConfiguration.Builder(appID)
.build());
Credentials credentials = Credentials.anonymous();
app.loginAsync(credentials, result -> {
if (result.isSuccess()) {
Log.v("QUICKSTART", "Successfully authenticated anonymously.");
User user = app.currentUser();
String partitionValue = "My Project";
SyncConfiguration config = new SyncConfiguration.Builder(
user,
partitionValue)
.build();
uiThreadRealm = Realm.getInstance(config);
addChangeListenerToRealm(uiThreadRealm);
FutureTask<String> task = new FutureTask(new BackgroundQuickStart(app.currentUser()), "test");
ExecutorService executorService = Executors.newFixedThreadPool(2);
executorService.execute(task);
} else {
Log.e("QUICKSTART", "Failed to log in. Error: " + result.getError());
}
});
}
private void addChangeListenerToRealm(Realm realm) {
// all tasks in the realm
RealmResults<Task> tasks = uiThreadRealm.where(Task.class).findAllAsync();
tasks.addChangeListener(new OrderedRealmCollectionChangeListener<RealmResults<Task>>() {
@Override
public void onChange(RealmResults<Task> collection, OrderedCollectionChangeSet changeSet) {
// process deletions in reverse order if maintaining parallel data structures so indices don't change as you iterate
OrderedCollectionChangeSet.Range[] deletions = changeSet.getDeletionRanges();
for (OrderedCollectionChangeSet.Range range : deletions) {
Log.v("QUICKSTART", "Deleted range: " + range.startIndex + " to " + (range.startIndex + range.length - 1));
}
OrderedCollectionChangeSet.Range[] insertions = changeSet.getInsertionRanges();
for (OrderedCollectionChangeSet.Range range : insertions) {
Log.v("QUICKSTART", "Inserted range: " + range.startIndex + " to " + (range.startIndex + range.length - 1)); }
OrderedCollectionChangeSet.Range[] modifications = changeSet.getChangeRanges();
for (OrderedCollectionChangeSet.Range range : modifications) {
Log.v("QUICKSTART", "Updated range: " + range.startIndex + " to " + (range.startIndex + range.length - 1)); }
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
// the ui thread realm uses asynchronous transactions, so we can only safely close the realm
// when the activity ends and we can safely assume that those transactions have completed
uiThreadRealm.close();
app.currentUser().logOutAsync(result -> {
if (result.isSuccess()) {
Log.v("QUICKSTART", "Successfully logged out.");
} else {
Log.e("QUICKSTART", "Failed to log out, error: " + result.getError());
}
});
}
public class BackgroundQuickStart implements Runnable {
User user;
public BackgroundQuickStart(User user) {
this.user = user;
}
@Override
public void run() {
String partitionValue = "My Project";
SyncConfiguration config = new SyncConfiguration.Builder(
user,
partitionValue)
.build();
Realm backgroundThreadRealm = Realm.getInstance(config);
Task task = new Task("New Task");
backgroundThreadRealm.executeTransaction (transactionRealm -> {
transactionRealm.insert(task);
});
// all tasks in the realm
RealmResults<Task> tasks = backgroundThreadRealm.where(Task.class).findAll();
// you can also filter a collection
RealmResults<Task> tasksThatBeginWithN = tasks.where().beginsWith("name", "N").findAll();
RealmResults<Task> openTasks = tasks.where().equalTo("status", TaskStatus.Open.name()).findAll();
Task otherTask = tasks.get(0);
// all modifications to a realm must happen inside of a write block
backgroundThreadRealm.executeTransaction( transactionRealm -> {
Task innerOtherTask = transactionRealm.where(Task.class).equalTo("_id", otherTask.get_id()).findFirst();
innerOtherTask.setStatus(TaskStatus.Complete);
});
Task yetAnotherTask = tasks.get(0);
ObjectId yetAnotherTaskId = yetAnotherTask.get_id();
// all modifications to a realm must happen inside of a write block
backgroundThreadRealm.executeTransaction( transactionRealm -> {
Task innerYetAnotherTask = transactionRealm.where(Task.class).equalTo("_id", yetAnotherTaskId).findFirst();
innerYetAnotherTask.deleteFromRealm();
});
// because this background thread uses synchronous realm transactions, at this point all
// transactions have completed and we can safely close the realm
backgroundThreadRealm.close();
}
}
}
MainActivity.kt
import org.bson.types.ObjectId
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import android.util.Log
import com.mongodb.realm.examples.YOUR_APP_ID
import io.realm.OrderedRealmCollectionChangeListener
import io.realm.Realm
import io.realm.RealmObject
import io.realm.RealmResults
import io.realm.annotations.PrimaryKey
import io.realm.annotations.Required
import io.realm.kotlin.where
import io.realm.mongodb.App
import io.realm.mongodb.AppConfiguration
import io.realm.mongodb.Credentials
import io.realm.mongodb.User
import io.realm.mongodb.sync.SyncConfiguration
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
import java.util.concurrent.FutureTask
class MainActivity : AppCompatActivity() {
lateinit var uiThreadRealm: Realm
lateinit var app: App
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Realm.init(this) // context, usually an Activity or Application
val appID : String = YOUR_APP_ID;
app = App(AppConfiguration.Builder(appID)
.build())
val credentials: Credentials = Credentials.anonymous()
app.loginAsync(credentials) {
if (it.isSuccess) {
Log.v("QUICKSTART", "Successfully authenticated anonymously.")
val user: User? = app.currentUser()
val partitionValue: String = "My Project"
val config = SyncConfiguration.Builder(user, partitionValue)
.build()
uiThreadRealm = Realm.getInstance(config)
addChangeListenerToRealm(uiThreadRealm)
val task : FutureTask<String> = FutureTask(BackgroundQuickStart(app.currentUser()!!), "test")
val executorService: ExecutorService = Executors.newFixedThreadPool(2)
executorService.execute(task)
} else {
Log.e("QUICKSTART", "Failed to log in. Error: ${it.error}")
}
}
}
fun addChangeListenerToRealm(realm : Realm) {
// all tasks in the realm
val tasks : RealmResults<Task> = realm.where<Task>().findAllAsync()
tasks.addChangeListener(OrderedRealmCollectionChangeListener<RealmResults<Task>> { collection, changeSet ->
// process deletions in reverse order if maintaining parallel data structures so indices don't change as you iterate
val deletions = changeSet.deletionRanges
for (i in deletions.indices.reversed()) {
val range = deletions[i]
Log.v("QUICKSTART", "Deleted range: ${range.startIndex} to ${range.startIndex + range.length - 1}")
}
val insertions = changeSet.insertionRanges
for (range in insertions) {
Log.v("QUICKSTART", "Inserted range: ${range.startIndex} to ${range.startIndex + range.length - 1}")
}
val modifications = changeSet.changeRanges
for (range in modifications) {
Log.v("QUICKSTART", "Updated range: ${range.startIndex} to ${range.startIndex + range.length - 1}")
}
})
}
override fun onDestroy() {
super.onDestroy()
// the ui thread realm uses asynchronous transactions, so we can only safely close the realm
// when the activity ends and we can safely assume that those transactions have completed
uiThreadRealm.close()
app.currentUser()?.logOutAsync() {
if (it.isSuccess) {
Log.v("QUICKSTART", "Successfully logged out.")
} else {
Log.e("QUICKSTART", "Failed to log out, error: ${it.error}")
}
}
}
class BackgroundQuickStart(val user: User) : Runnable {
override fun run() {
val partitionValue: String = "My Project"
val config = SyncConfiguration.Builder(user, partitionValue)
.build()
val backgroundThreadRealm : Realm = Realm.getInstance(config)
val task : Task = Task("New Task", partitionValue)
backgroundThreadRealm.executeTransaction { transactionRealm ->
transactionRealm.insert(task)
}
// all tasks in the realm
val tasks : RealmResults<Task> = backgroundThreadRealm.where<Task>().findAll()
// you can also filter a collection
val tasksThatBeginWithN : List<Task> = tasks.where().beginsWith("name", "N").findAll()
val openTasks : List<Task> = tasks.where().equalTo("status", TaskStatus.Open.name).findAll()
val otherTask: Task = tasks[0]!!
// all modifications to a realm must happen inside of a write block
backgroundThreadRealm.executeTransaction { transactionRealm ->
val innerOtherTask : Task = transactionRealm.where<Task>().equalTo("_id", otherTask._id).findFirst()!!
innerOtherTask.status = TaskStatus.Complete.name
}
val yetAnotherTask: Task = tasks.get(0)!!
val yetAnotherTaskId: ObjectId = yetAnotherTask._id
// all modifications to a realm must happen inside of a write block
backgroundThreadRealm.executeTransaction { transactionRealm ->
val innerYetAnotherTask : Task = transactionRealm.where<Task>().equalTo("_id", yetAnotherTaskId).findFirst()!!
innerYetAnotherTask.deleteFromRealm()
}
// because this background thread uses synchronous realm transactions, at this point all
// transactions have completed and we can safely close the realm
backgroundThreadRealm.close()
}
}
}
enum class TaskStatus(val displayName: String) {
Open("Open"),
InProgress("In Progress"),
Complete("Complete"),
}
open class Task(_name: String = "Task", project: String = "My Project") : RealmObject() {
@PrimaryKey
var _id: ObjectId = ObjectId()
var name: String = _name
@Required
var status: String = TaskStatus.Open.name
var statusEnum: TaskStatus
get() {
// because status is actually a String and another client could assign an invalid value,
// default the status to "Open" if the status is unreadable
return try {
TaskStatus.valueOf(status)
} catch (e: IllegalArgumentException) {
TaskStatus.Open
}
}
set(value) { status = value.name }
}

Running the above code should produce output resembling the following:

Successfully authenticated anonymously.
Updated range: 0 to 1
Deleted range: 0 to 1
Successfully logged out.

Next

Welcome to the Atlas Device SDK Docs