Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Right way of doing Realm Migration Android

We use Realm for our app. Our app has been beta released. Now I want to add a field to one of our realm objects. So I got to write RealmMigration and I wrote one too. The Question here is how to apply this Realm migration to my app. I use Realm.getInstance() get the realm instance whenever I want to something. Remember, Realm.getInstance() is being used in the entire app everytime, I want to access Realm database.

So, I am bit Queried on how to apply this migration? Any leads can be helpful. Thanks.

My RealmMigration is as follows.

public class RealmMigrationClass implements RealmMigration {
    @Override
    public void migrate(DynamicRealm realm, long oldVersion, long newVersion) {
        if(oldVersion == 0) {
            RealmSchema sessionSchema = realm.getSchema();

            if(oldVersion == 0) {
                RealmObjectSchema sessionObjSchema = sessionSchema.get("Session");
                sessionObjSchema.addField("isSessionRecordingUploading", boolean.class, FieldAttribute.REQUIRED)
                        .transform(new RealmObjectSchema.Function() {
                            @Override
                            public void apply(DynamicRealmObject obj) {
                                obj.set("isSessionRecordingUploading", false);
                            }
                        });


                sessionObjSchema.setNullable("isSessionRecordingUploading",false);
                oldVersion++;
            }

        }
    }

}

public class Session extends RealmObject {

    @PrimaryKey
    private String id;
    @Required
    private Date date;
    private double latitude;
    private double longitude;
    private String location;
    private String note;
    private String appVersion;
    private String appType;
    private String deviceModel;
    private HeartRecording heart;
    private TemperatureRecording temperature;
    private LungsRecording lungs;
    @NotNull
    private boolean isSessionRecordingUploading;
    private boolean sessionInfoUploaded;
    private boolean lungsRecordingUploaded;
    private boolean heartRecordingUploaded;

}

Removed Getter and Setters from RealmObject to cut short the Question. The exception occurred when I try to reinstall the app without uninstalling the previous one. Please advice.

like image 687
User Avatar asked Mar 07 '16 05:03

User


People also ask

What is realm migration?

public interface RealmMigration. The RealmMigration class is used to perform the migration of one Realm schema to another. The schema for a Realm is defined by all classes in a project that extend RealmObject or implement RealmModel , so any changes to these classes will require a migration.

Where is realm database stored android?

A new finder window will open, where you find your Realm inside in the following path (e.g.): AppData/Documents/default. realm (The path is /private/var/mobile , which is used by iOS on the device filesystem.


2 Answers

It is described here: https://realm.io/docs/java/latest/#migrations

But in essence, you just bump the schema version and set the configuration like this:

RealmConfiguration config = new RealmConfiguration.Builder(context)     .schemaVersion(2) // Must be bumped when the schema changes     .migration(new MyMigration()) // Migration to run     .build();  Realm.setDefaultConfiguration(config);  // This will automatically trigger the migration if needed Realm realm = Realm.getDefaultInstance(); 
like image 86
Christian Melchior Avatar answered Sep 21 '22 11:09

Christian Melchior


This is a helper class i have made to import a .realm database to my application. In my case i just need to read the db created from an iOS application in an Android application

public class RealmImporter {
private Activity activity;
private String dbaFullName = "db.realm";
private int rawRealmResource = R.raw.dbRealmResource;


public RealmImporter (Activity activity) {
    this.activity = activity;
    importData();
}


private RealmConfiguration getConfiguration() {
    RealmConfiguration config = new RealmConfiguration.Builder()
            .name(dbaFullName)
            .modules(new MyRealmModule())
            .migration(new RealmMigration() {
                @Override
                public void migrate(DynamicRealm realm, long oldVersion, long newVersion) {

                }
            })
            .build();

    return config;
}

public Realm getInstance() {
    Realm realm = Realm.getInstance(getConfiguration());

    return realm;
}

private void importData() {
    copyBundledRealmFile(activity.getResources().openRawResource(rawRealmResource), dbaFullName);

    Realm.init(activity);
}

private String copyBundledRealmFile(InputStream inputStream, String outFileName) {
    try {
        File file = new File(activity.getFilesDir(), outFileName);
        if (file.exists()) {
            return file.getAbsolutePath();
        }
        FileOutputStream outputStream = new FileOutputStream(file);
        byte[] buf = new byte[1024];
        int bytesRead;

        while ((bytesRead = inputStream.read(buf)) > 0) {
            outputStream.write(buf, 0, bytesRead);
        }

        outputStream.close();
        return file.getAbsolutePath();
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}


// Create the module
@RealmModule(classes = { Artigo.class, Comparativo.class, Indice.class, ItemDeArtigo.class})
public static class MyRealmModule{
}
}

If you have more than one realm configuration (if you need to import more than one .realm file) you need to create a RealmModule class and use the .modules() option on the RealmConfiguration.Builder .

This is needed because by default realm try to check if your .realm has tables for all your models that extend RealmObject, and if you have multiple .realm, each one of them will have some of your classes (but not all of them).

Another usefull information is that for swift to android migrations. All String properties must be declared with @Required anototation (if they have a default value).

If realm is giving you a strange Exception like "this class was not found in this schema", try to re run you app, usually it gives a different error which can hint to the real problem although sometimes it just gives a random error.

like image 26
Renato Probst Avatar answered Sep 19 '22 11:09

Renato Probst