You are reading the documentation for an older version of Realm. You can view the latest documentation instead.

Getting started

Please note that we do not support Java outside of Android at the moment.

Prerequisites

  • Android Studio (>= 0.8.6)
  • A recent version of the Android SDK
  • JDK version 7 or 8.

We support all Android versions since API Level 9 (Android 2.3 Gingerbread & above).

Installation

  1. Download the release package and unzip.
  2. Create a new project with Android Studio
  3. Copy the realm folder into the root folder of the new project (beside app, not inside it)
  4. Copy the realm-annotations-processor-VERSION.jar file to into app/libs (VERSION is the current version number)
  5. Add the following line to the settings.gradle file:

    include ':realm'
  6. Add the following buildscript dependency to the build.gradle file in the root folder of the project

    classpath 'com.neenbedankt.gradle.plugins:android-apt:1.3'
  7. Add the following plugin inclusion in the top of the app/build.gradle file

    apply plugin: 'android-apt'
  8. Replace the dependencies section of the app/build.gradle file with:

    dependencies {
         apt fileTree(dir: 'libs', include: ['*.jar'])
         compile project(':realm')
     }
  9. In the Android Studio menu: Tools->Android->Sync Project with Gradle Files

Realm Browser

Only available on Mac OS X at the moment! We are working on Windows & Linux versions.

We also provide a standalone app to read and edit .realm databases.

You can find it in our Cocoa release zip under browser/.

You can generate a test database with dummy data using the menu item Tools > Generate demo database.

Examples

The RealmIntroExample in the root folder contains simple examples of how you use the current API. You just Import Project in Android Studio and run. There will only be a little output in the Log, so checkout the code to see examples of simple use of the API.

The RealmGridViewExample is a trivial app that shows how to use Realm as the backing store for a GridView. It also shows how you could populate the database with json. You just Import Project in Android Studio and run. You should then see a simple gridview on the screen.

Getting Help

  • Sign up for our community newsletter to get regular tips, learn about other use-cases and get alerted of blogposts and tutorials about Realm.
  • We rely on you to send your questions, as well as your candid feedback to help shape Realm for Android! Please direct all questions and feature requests to realm-java@googlegroups.com.
  • While we discourage using it for help/debugging of your app (which is better done on the Google Group), we highly encourage all bug reports to be filed directly as issues on our GitHub repo!

Models

Realm data models are defined by implementing a traditional Java Bean. Simply extend our RealmObject and let the Realm annotations processor generate proxy classes.

public class User extends RealmObject {

    private String          name;
    private int             age;
    private String          email;
    private User            boss;
    private RealmList<User> friends;
    @Ignore
    private int             dontPersist;

    // Standard getters & setters generated by your IDE…
    public String getName() { return name; }
    public void   setName(String name) { this.name = name; }
    public int    getAge() { return age; }
    public void   setAge(int age) { this.age = age; }
    public String getEmail() { return email; }
    public void   setEmail(String email) { this.email = email; }
    public User   getBoss() { return boss; }
    public void   setBoss(User boss) { this.boss = boss; }
    public RealmList<User> getFriends() { return friends; }
    public void   setFriends(RealmList<User> friends) { this.friends = friends; }
    public int    getDontPersist() { return dontPersist; }
    public void   setDontPersist(int dontPersist) { this.dontPersist = dontPersist; }
}

Be aware that the getters and setters will be overriden by the generated proxy class used in the back by RealmObjects, so any custom logic you add to the getters & setters will not actually be executed.

RealmObjects are strongly tied to one Realm so they must be instantiated from the Realm using the realm.createObject() instance method.

Field types

Realm supports the following field types: boolean, short, int, long, float, double, String, Date and byte[]. Moreover, subclasses of RealmObject and RealmList` are supported to model relationships.

Ignoring properties

The annotation @Ignore implies that a field should not be persisted to disk.

Writes

Read operations are implicit, but all write operations (adding, modifying, and removing objects) must be wrapped in write transactions to ensure thread safety:

// Obtain a Realm instance
Realm realm = Realm.getInstance(this);

realm.beginTransaction();

//... add or update objects here ...

realm.commitTransaction();

Because objects are strongly tied to a Realm, they should be instantiated through the Realm directly:

realm.beginTransaction();
User user = realm.createObject(User.class); // Create a new object
user.setName("John");
user.setEmail("john@corporation.com");
realm.commitTransaction();

Please note that writes block each other, and will block the thread they are made on if other writes are in progress. Thanks to Realm’s MVCC architecture, reads are not blocked while a write transaction is open! This means that unless you need to make simultaneous writes from many threads at once, you should favor larger write transactions that do more work over many fine-grained write transactions. When you commit a write transaction to a Realm, all other instances of that Realm will be notified, and the read implicit transactions will refresh your Realm objects automatically.

Queries

All fetches (including queries) are lazy in Realm, and the data is never copied.

Realm’s query engine uses a Fluent interface to construct multi-clause queries.

To find all users named John you would write:

// Build the query looking at all users:
RealmQuery<User> query = realm.where(User.class);

// Add query conditions:
query.equalTo("name", "John");
query.or().equalTo("name", "Peter");

// Execute the query:
RealmResults<User> result1 = query.findAll();

// Or alternatively do the same all at once (the "Fluent interface"):
RealmResults<User> result2 = realm.where(User.class)
                                  .equalTo("name", "John")
                                  .or()
                                  .equalTo("name", "Peter")
                                  .findAll();

This gives you a new RealmResults, of users with the name John. Objects are not copied - you get a list of references to the matching objects, and you work directly with the original objects that matches your query.

Conditions

The following hopefully self explanatory conditions are supported:

  • greaterThan(), lessThan(), greaterThanOrEqualTo() & lessThanOrEqualTo()
  • equalTo() & notEqualTo()
  • contains(), beginsWith() & endsWith()

Not all conditions are applicable for all data types. Please consult the API reference for RealmQuery for details.

Logical Operators

Each condition is implicitly logical-and together. Logical-or must be applied explicitly with or().

You can also also group conditions with “parentheses” to specify order of evaluation: beginGroup() is your “left parenthesis” and endGroup() your “right parenthesis”:

RealmResults<User> r = realm.where(User.class)
                            .greaterThan("age", 10)  //implicit AND
                            .beginGroup()
                                .equalTo("name", "Peter")
                                .or()
                                .contains("name", "Jo")
                            .endGroup()
                            .findAll();

Sorting

Once you have done your query, you can sort the results like this:

RealmResults<User> result = realm.where(User.class).findAll();
RealmResults<User> sortedAscending  = result.sort("age");
RealmResults<User> sortedDescending = result.sort("age", RealmResults.SORT_ORDER_DECENDING);

Chaining Queries

Since results are never copied and computed on request, you can very efficiently chain queries to gradually filter your data:

RealmResults<Person> teenagers = realm.where(Person.class).between("age", 13, 20).findAll();
Person firstJohn = teenagers.where().equalTo("name", "John").findFirst();

Aggregation

A RealmResults also has various aggregation methods:

RealmResults<User> results = realm.where(User.class).findAll();
long   sum     = results.sum("age").longValue();
long   min     = results.min("age").longValue();
long   max     = results.max("age").longValue();
double average = results.average("age");

long   matches = results.size();

Iterations

To iterate through all objects in a RealmResults you can take advantage of Iterable:

RealmResults<User> results = realm.where(User.class).findAll();
for (User u : results) {
    // ... do something with the object ...
}

or use a traditional for loop:

RealmResults<User> results = realm.where(User.class).findAll();
for (int i = 0; i < results.size(); i++) {
    User u = results.get(i);
    // ... do something with the object ...
}

Deletion

You can delete the results of a query from the Realm:

// All changes to data must happen in a transaction
realm.beginTransaction();

// remove single match
result.remove(0);
result.removeLast();

// Delete all matches
result.clear();

realm.commitTransaction()

Realms

Realms are our equivalent of a database: they contain different kinds of objects, and map to one file on disk.

The Default Realm

You may have noticed so far that we have always initialized access to our realm variable by calling Realm.getInstance(this). This singleton method will return an instance variable for your thread, that maps to a file called default.realm, located at the root of the File directory for your application.

Other Realms

It’s sometimes useful to have multiple realms, persisted at different locations, for example if you have different data groupings, different databases per feature, or you need to package some read-only files with your app, separate from the database your users will be editing.

Realm realm = Realm.getInstance(this, "allmymovies.realm");

Using a Realm across Threads

The only rule to using Realm across threads is to remember that Realm, RealmObject or RealmResults instances can be passed across threads. When you want to access the same data from different threads, you should simply obtain a separate Realm instance for each thread (i.e. Realm.getInstance(this) or its cousins) and get your objects through a RealmQuery. The objects will map to the same data on disk, and will be readable & writeable from any thread!

Relationships

Any two RealmObjects can be linked together.

public class Email extends RealmObject {
    private String address;
    // ... setters and getters left out
}

public class Contact extends RealmObject {
    private String name;
    private Email email;
    // ... setters and getters left out
}

Please note that queries on links are not supported at the moment. For now, you can work around this current limitation by iterating over your results to filter them. We’ll be support built-in queries on links in our next release.

Many-to-One

Simply declare a property with the type of one of you RealmObject subclasses:

public class Email extends RealmObject {
    private Contact contact;
    // Other fields…
}

Many-to-Many

You can establish a relationship to 0, 1 or more objects from a single object via an RealmList<T> field declaration

public class Contact extends RealmObject {
    private RealmList<Email> emails;
    // Other fields…
}

RealmLists are basically containers of RealmObjects, that behave very much like a regular Java List

You can add standard getters & setters to access the data in the link.

realm.beginTransaction();
Contact contact = realm.createObject(Contact.class);
contact.setName("John Doe");

Email email1 = realm.createObject(Email.class);
email1.setAddress("john@example.com");
contact.getEmails().add(email1);

Email email2 = realm.createObject(Email.class);
email2.setNumber("jd@example.com");
contact.getEmails().add(email2);

realm.commitTransaction();

Notifications

If you have a backgroud thread adding data to a Realm, your UI or other threads can get notified of changes in a realm by adding a listener, which is executed when the Realm is changed (by another thread or process):

realm.addChangeListener(new RealmChangeListener() {
    @Override
    public void onChange() {
        // ... do something with the updates (UI, etc.) ...
    }
});

You can easily close all listeners when needed:

realm.removeAllChangeListeners();

Migrations

When working with any database, it is likely your data model will change over time. Since data models in Realm are defined as standard Objects, changing them is as easy as changing the interface of the corresponding RealmObject subclass.

Just changing your code to the new definition will work fine, if you have no data stored on disk under the old schema. But if you do, there will be a mismatch between what Realm sees defined in code, and the data Realm sees on disk, and an exception will be thrown.

We provide built-in methods so you can upgrade your schema on disk, and the data you stored for previous versions of the schema. See our migrationSample app for details.

Encryption

Please take note of the Export Compliance section of our LICENSE, as it places restrictions against the usage of Realm if you are located in countries with an export restriction or embargo from the United States.

The Realm file can be stored encrypted on disk by passing a 256-bit encryption key to Realm.create():

byte[] key = new byte[32];
new SecureRandom().nextBytes(key);
Realm realm = Realm.create(this, key);

// ... use the Realm as normal ...

This ensures that all data persisted to disk is transparently encrypted and decrypted with standard AES-256 encryption. The same encryption key must be supplied each time a Realm instance for the file is created.

See examples/encryptionExample for a complete example of how to securely store keys between runs in the Android KeyStore so that other applications cannot read them.

Using Encryption requires building Realm from source.

  1. Follow the normal build instuctions, but before running ./gradlew assemble, add the line encryption=true to local.properties.
  2. After building Realm, replace the copy of realm-<VERSION>.aar in your project with the one found at realm/build/outputs/aar/realm-<VERSION>.aar.

Next Steps

You can look at our examples to see Realm used in practice in an app. (We’re getting more samples ready!)

Happy hacking! You can always talk to a live human developer on realm-java.