前回の記事では、アプリにバックアップと復元の機能を追加したことを紹介しました。

その中でバックアップ機能の実現方法についての実装部分を書いていきたいと思います。

1.はじめに

Roomライブラリを利用してデータベースを扱う場合、デフォルトの設定ではSQLiteはWALモードの設定となっているため、以下の3つのファイルを扱うことになります。
・todolog_database
・todolog_database-shm
・todolog_database-wal
※「todolog」はパッケージ名になります。
 
今回の記事では、上記の3つのファイルを「[Java]Storage Access Frameworkを利用して好きな場所にファイルを保存」の記事で書いたSAFを利用して保存場所を指定した後からの処理を書いていきます。
以下が記事からの引用部分。この赤字の部分の処理の続きになります。

    Uri uri = resultData.getData();

    OutputExternalFile externalFile = new OutputExternalFile(this);
    externalFile.outputSelectFolder(uri);

2.ZipOutputStreamを利用してZIP形式のファイル出力

OutputExternalFileクラスのoutputSelectFolderメソッドの処理は以下の通り。

public class OutputExternalFile {
    private Context context;

    public OutputExternalFile(Context context) {
        this.context = context;
    }

    public void outputSelectFolder(final Uri uri) {
        InputStream inputStream = null;
        OutputStream outputStream = null;
        try {
            String pathList[] = new String[3];
            pathList[0] = context.getDatabasePath("todolog_database").getPath();
            pathList[1] = context.getDatabasePath("todolog_database-shm").getPath();
            pathList[2] = context.getDatabasePath("todolog_database-wal").getPath();
            String fileList[] = new String[3];
            fileList[0] = "todolog_database";
            fileList[1] = "todolog_database-shm";
            fileList[2] = "todolog_database-wal";

            outputStream = context.getContentResolver().openOutputStream(uri);
            ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream);

            for (int i = 0; i < pathList.length; i++) {
                inputStream = new FileInputStream(pathList[i]);
                ZipEntry zipEntry = new ZipEntry(fileList[i]);
                zipOutputStream.putNextEntry(zipEntry);

                byte[] buf = new byte[1024];
                int len;
                while ((len = inputStream.read(buf)) > 0) {
                    zipOutputStream.write(buf, 0, len);
                }

                inputStream.close();
                zipOutputStream.closeEntry();
            }

            zipOutputStream.close();
            outputStream.close();
        } catch (Exception exc) {
			exc.printStackTrace();
        } finally {
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

この処理で注目するポイントは以下の通り。
・context.getDatabasePath("ファイル名").getPath()
指定されたファイル名でデータベースが保存されている絶対パス名を作成してくれます。

・ZipEntry zipEntry = new ZipEntry(fileList[i]);

この処理で渡しているのは絶対パス名ではなくファイル名のみを渡しています。エントリー情報をファイル名だけにすることによって、ZIP形式のフォルダ直下にファイルを格納する事ができます。
・zipEntry.putNextEntry(zipEntry);
生成したエントリーをこの処理によって複数回登録する事で複数のファイルを1つのZIP形式のファイルにまとめる事ができます。
 
説明は以上となります。
このような実装によってデータのバックアップと復元の機能が追加された履歴が残るToDoリストのアプリぜひ使ってみて下さい。