Androidアプリを作っていると、
- 「いまどんな値がRealmに入ってるんだっけ?」
- 「ここの数字を2に書き変えたらうまくいくのかな?」
みたいなデバッグをしたくなることがよくあります。
adb pull / push でRealmデータベースを抜いたり入れたりするのはめんどくさすぎるので、できればリモートデバッグがしたいですよね。
「いまどんな値がRealmに入ってるんだけ?」という要求については、 @zaki50 さんによる神拡張 stetho-realm で概ね目的は果たせるのですが、「ここの数字を2に書き換えたらうまくいくのかな?」のようなデバッグはそう簡単にはできません。
Realm Mobile Platformで実現できるか・・・?
Realm Browserを使うと、Realm Object Serverに保持されている値をさらっと書き換えたり消したりすることができます。
ということは、Realm Object Serverを介して「ここの数字を2に書き換えたらうまくいくのかな?」というデバッグをすることができるのでは? と試してみたくなりました。
サンプルアプリ
メッセンジャーライクなアプリで、内部設計的には、Messageモデルをrealm-android-adaptersのRealmBaseAdapterでそのままリストビューに表示させてるだけです。
ソースをちょっと変える
build.gradle
realm {
syncEnabled = true
}
を追記します。
Applicationクラス
Realm.init(this);
のようにしていたところは、
Realm.init(this);
SyncCredentials credentials = SyncCredentials.usernamePassword(
"yusuke.iwaki@example.com", "hogehoge", false);
SyncUser.loginAsync(credentials, "http://localhost:9080/auth", new SyncUser.Callback() {
@Override
public void onSuccess(SyncUser user) {
RealmConfiguration config = new SyncConfiguration.Builder(user, "realm://localhost:9080/~/debug").build();
Realm.setDefaultConfiguration(config);
}
@Override
public void onError(ObjectServerError error) {
}
});
このように、Realm Object Serverに接続するようなコードに変えます。
Realm Object Serverを起動する
./start-object-server.command
これを実行すると、
Your admin access token is: ewoJImlkZW50aXR5IjogImFkbWluIi~~(略)~~9eCEinw==
みたいなのが出るので、こいつをメモ。
ユーザを適当につくる
SyncCredentials credentials = SyncCredentials.usernamePassword(
"yusuke.iwaki@example.com", "hogehoge", false);
でログインできるように、管理画面でユーザをつくります。
ポートフォワーディング
アプリが http://localhost:9080/auth
のソースでRealm Object Serverに接続できるようにするには
adb reverse tcp:9080 tcp:9080
で、端末の9080版ポートをMacにフォワードさせる必要があります。
アプリのソースを http://10.0.3.2:9080/auth
のように、直接Realm Object Serverを向くように変えるでもOKです。
で、アプリを実行すると・・・
見た目は何も変わりません。
「あれ、古いデータが残ってるぞ?」というときは
一旦アプリを終了させてもう一度起動すると、SyncConfigurationを反映したRealm DBが見えるようになるかと思います。
Applicationクラスで非同期でSyncConfigurationをsetDefaultしているため、初回起動時はそれより先にActivityのonCreateが呼ばれ、 Realm.getDefaultInstance()
で正しくSync DBが見えないのです。
もう一度起動し直すことによって、Applicationクラスは初期化されずそのまま、Activityだけが初期化されるので、正しくSync DBが見えるようになる、というわけです。
Realm BrowserでRealm Object Serverに接続
/debug
で終わるデータベースが作られています。
中を覗くと、それっぽいデータが見えます。
さわってみる
リモートデバッグっぽい感じで、DBをごにょごにょできました。
Realm Browser側がオートリフレッシュがかかるので、非常に便利ですね。
RealmChangeListenerとかもちゃんと発動しますね!
サンプルアプリでは、「syncstate=0のMessageが来たら、それを1に変えて、もうしばらくしたら2に変える」という動作をするバックグラウンドサービスが動いていますが、RealmBrowserで syncstate=0にデータを書き換えた場合にもリスナーがしっかり発動してくれます。
ざっくり変更差分はこんな感じです。
https://github.com/YusukeIwaki/RealmDebugSample/commit/e94b3cd1ed476be50882d82b8b3d73ad92ab0624
まとめ
Realm Object Serverの本来の使い方ではありませんが、ちょっと一工夫をすることでリモートデバッグにも使えそう、ということがわかりました。
今回試したソースは、デバッグ版でもリリース版でもSyncConfigurationを使うようになってますが、たとえば
- デバッグビルドではSyncConfigurationでリモートデバッグ可能
- リリースビルドでは従来通りRealmConfiguration
のようにしておくと、「やべー、リモートデバッグ有効にしたままリリースしちゃった!」てきな事故にはならずに済みますねw
ということで、みなさんRealm Object Server使ってみましょう!