Google様から古いOpenSSL使ってるアプリは2016/07/11以降、Playに公開/更新させないよというお達しもあり、Realmでは0.91.0未満では古いOpenSSLを使っているので、これを期に最新(1.0.0)にUpgradeしたときの備忘録です。
(古いOpenSSLでは脆弱性がありましたが、Realm内では脆弱性を含む機能を使用していないため、最近まで更新していなかったらしい)
本家のGetting Startedを参考に、0.87.4 => 1.0.0にUpgradeする際の手順です。(部分的にしか使ってなかったのでたぶん変更箇所は少ない方だと思います)
Change Logをみると結構たくさんBreaking changesがあるけど、頑張ろう!
手順
- gradleで参照しているRealmのバージョンを更新
- ビルドエラーを潰す
- 実際に動かして、想定外の動きをする箇所を潰す
※基本的にはエラーや想定外の動作が出た箇所の実装をChange Logと本家ドキュメントを見ながら変更/修正していくことの繰り返しです。
build.gradleの変更
projectレベルのbuild.gradleにdependenciesを追加(0.88.0/Breaking change)
buildscript {
repositories {
jcenter()
}
dependencies {
classpath "io.realm:realm-gradle-plugin:1.0.0"
}
}
appレベルのbuild.gradleから0.87.4の記述を削除して1.0.0の記述を追記
apply plugin: 'realm-android'
dependencies {
// compile 'io.realm:realm-android:0.87.4'
}
ビルドエラーの解消
リストAPI削除:RealmResults.removeLast()
- メソッドがなくなったので
RealmResults.deleteLastFromRealm()
に変更(0.91.0/Breaking change)
メソッドのthrow追加:Realm.migrateRealm(RealmConfiguration configuration, RealmMigration migration)
-
FileNotFoundException
をthrowするようになった(0.88.0/Breaking change)- そもそも
RealmConfiguration
生成時にmigrationを設定する方法に変更してベストプラクティスに従ってRealm.getDefaultInstance()
を使うよう変更
- そもそも
【変更前】
public static Realm getInstance(Context context) {
Realm realm;
RealmConfiguration config = new RealmConfiguration.Builder(context)
.schemaVersion(JmtyMigration.REALM_SCHEMA_VERSION)
.build();
try {
realm = Realm.getInstance(config);
} catch (RealmMigrationNeededException ex) {
Realm.migrateRealm(config, new JmtyMigration());
realm = Realm.getInstance(config);
}
return realm;
}
【変更後】
@Override
public void onCreate() {
super.onCreate();
sContext = getApplicationContext();
// Realmセットアップ
Realm.setDefaultConfiguration(RealmUtil.createRealmConfiguration(sContext));
}
/**
* RealmのConfigurationを生成する
*
* @param context
* @return RealmConfiguration
*/
public static RealmConfiguration createRealmConfiguration(Context context){
return new RealmConfiguration.Builder(context)
.schemaVersion(JmtyMigration.REALM_SCHEMA_VERSION)
.migration(new JmtyMigration())
.build();
}
実際に動かして、想定外の動きをする箇所を潰す
ソート変更:RealmResults.sort()
- エラーは出ず、ソートが効かなくなる
-
RealmResults
そのものへの操作ではなく、ソートしたオブジェクトを返却するようになった(0.89.0/Breaking changes)
【変更前】
Realm realm = Realm.getDefaultInstance();
RealmQuery<Article> query = realm.where(Article.class);
results = query.findAll();
results.sort("updatedAt", Sort.DESCENDING);
【変更後】
Realm realm = Realm.getDefaultInstance();
RealmQuery<Article> query = realm.where(Article);
results = query.findAll().sort("updatedAt", Sort.DESCENDING);
String型のprimary keyを持ったRealmファイルが開けない
- 以前のversionで作られたRealmファイルを参照しようとしたときにエラー
- Primary Keyのフィールドがnullを許容する型(String, Byte, Short, Integer, and Long)だと
RealmObjectSchema.setNullable()
か@Required
のアノテーションを使わないとエラーになるようになった。- Schema versionを上げて
RealmObjectSchema.isRequired(String)
を実施(0.89.0/Breaking changes)- nullを許容するなら
RealmObjectSchema.isNullable(String)
を実施する(praimary keyでnull許容なんてケースあるのか?)
- nullを許容するなら
- Schema versionを上げて
FATAL EXCEPTION: main
Process: com.snowmonkey.sample, PID: 8761
io.realm.exceptions.RealmMigrationNeededException: @PrimaryKey field '{フィールド名}' does not support null values in the existing Realm file. Migrate using RealmObjectSchema.setNullable(), or mark the field as @Required.
以下略
【変更前】
public class Article extends RealmObject {
@PrimaryKey
private String key;
// 以下略
}
【変更後】
public class Article extends RealmObject {
@PrimaryKey @Required
private String key;
// 以下略
}
public class MyMigration implements RealmMigration {
/** Current Schema Version. */
public static final long REALM_SCHEMA_VERSION = 1;
@Override
public void migrate(DynamicRealm realm, long oldVersion, long newVersion) {
Log.d(getClass().getSimpleName(), "Migrate Realm Schema old[" + oldVersion + "] to new[" + newVersion + "]");
if (oldVersion == 0) {
// Migrate from v0 to v1
migrate0To1(realm);
oldVersion++;
}
if (oldVersion < newVersion) {
throw new IllegalStateException(String.format("Migration missing from v%d to v%d", oldVersion, newVersion));
}
}
/**
* Migrate from version 0 to version 1.
* At version 1, add @Required annotation for Primary Key(historyForShow) at SearchHistory Table.
*
* @param realm
*/
private void migrate0To1(DynamicRealm realm) {
RealmObjectSchema searchHistorySchema = realm.getSchema().get(SearchHistory.class.getSimpleName());
searchHistorySchema.isRequired("key");
}
}
所感的な何か
うちはまだそれほどがっつりRealm使っていなかったのでさくっと半人日もかからずUpgrade出来てよかったよかった。
というかちゃんと本家の更新を追ってないと差分が多くなって大変そうなので今後はチラチラ追っていこう。。。
(とはいえ「安定版の1.0.0になったから今後はBreaking changeは控える」って中の人が言ってたから大丈夫かな…?)
早くRealmConfiguration.Builder.assetFile()
使ってアプリ初回起動時にやってたマスタデータ取得の時間を短縮したいぞおおおおおおお!!!