読者です 読者をやめる 読者になる 読者になる

techium

このブログは何かに追われないと頑張れない人たちが週一更新をノルマに技術情報を発信するブログです。もし何か調査して欲しい内容がありましたら、@kobashinG or @muchiki0226 までいただけますと気が向いたら調査するかもしれません。

Realm.writeCopyTo(File f)で.realmファイルの確認を簡略化する

Android Realm

前回の記事ではRealm BrowserでRealmのデータをGUIで確認する方法を紹介しました。

今回はRealm Browserでデータを確認する際の手順を簡略化する方法を紹介します。

正攻法で.realmファイルを取得する

Realmで作成したデータはデフォルトでは/data/data/アプリパッケージ名/files/default.realmに保存されます。ここで作成されたdefault.realmをRealm Browserで開くと保存したデータが確認できますが、このファイルパスはアプリ領域下のセキュアな領域のため、通常はadb pullなどで直接参照することができません。

そこで、前回の記事で記載したようにadb shell run-as パッケージ名を実行後、cpなどでアプリ領域から公開領域にコピーしてからadb pullで.realmファイルを取得するという手順が必要でした。

上記のように正攻法で.realmファイルを取得しようとすると、「データ保存→アプリ権限で端末のシェルを実行→公開領域にファイルコピー→adb pullでファイル取得」という面倒な手順を実行する必要があります。この手順を簡略化するのが今回のテーマです。

writeCopyTo(File f)で公開領域にコピーを作成する

先ほどの正攻法の手順の中でネックになっているのが「アプリ領域から公開領域にファイルをコピーする」という部分です。これを実行するためにrun-asコマンドでアプリ権限になる必要がありましたが、そのせいで実行しなければならないコマンドが3つほど増えます*1

逆に言えば最初から公開領域に.realmファイルを作成すればコマンド一発で取得することができます。バージョン1.1.0時点ではデータの保存場所を指定するAPIは見当たりませんが、データ保存後にRealm.writeCopyTo(File f)を実行することで.realmファイルのコピーを任意の場所に保存することができます。そうやって作成したファイルをadb pullで取得すると、adb shellでの操作がかなり簡略化されます。

writeCopyTo(File f)で.realmファイルのコピーを作成するには以下のようにします。

private void createBookShelf() {
    Realm r = Realm.getDefaultInstance();

    // トランザクション開始
    r.beginTransaction();

    // データ作成処理

    r.commitTransaction();
    // トランザクション終了

    String fileName = "realm_copy.realm";
    File dir = Environment.getExternalStorageDirectory();

    // 外部ストレージ直下にrealm_copy.realmファイルを作成する
    File f = new File(Environment.getExternalStorageDirectory() + "/" + fileName);
    if (f.exists()) {
        // 同一ファイル名のファイルが存在する場合エラーが発生するため、ファイルがすでに存在すれば削除する
        f.delete();
    }

    try {
        // 現時点での.realmファイルを指定のパスの位置にコピーする
        r.writeCopyTo(f);
    } catch (IOException e) {
        e.printStackTrace();
    }

    r.close();
}

上記のコードをNexus6で実行すると/sdcard/0/realm_copy.realmファイルが作成されます。後はターミナルからadb pull /sdcard/realm_copy.realmを実行するだけで.realmファイルが取得できます。お手軽ですね。

なおこの方法は外部ストレージへの書き込みが必要なのでWRITE_EXTERNAL_STORAGEのパーミッションを追加する必要があります。Android6.0以降で上記のコードを実行するとRuntime Permissionの制限によりSecurityExceptionが発生するため注意してください。

完全なサンプルが必要な場合は記事末尾のサンプルコードより取得してみてください。

所感

本来writeCopyTo(File f)は.realmファイルのバックアップを作成するためのAPIだと思いますが、今回のように動作確認のために使うと非常に便利なんじゃないかなーというお話でした。

サンプルコード

前回の記事のサンプルコードと同じものです。Runtime Permissionの対応も一応入っていますのでご参考まで。

github.com

*1:run-asでアプリ権限になる→ファイルを公開領域にコピー→exitで端末のシェルを抜ける