2.6. 編集内容のファイル保存

サンプルアプリである「メモアプリ」の、編集画面で入力された内容をファイル保存する処理について説明します。
編集画面では、入力された内容を 「メイン画面に戻るタイミング」 でファイル保存します。
メイン画面から編集画面への遷移
「メイン画面に戻るタイミング」 は、Android アプリでは 「画面がバックグラウンドに移動するタイミング」 のイベントとなります。
また、アクションバーのメニューである [削除] を選択した場合は、ファイルを削除して(もしくは保存なしで)メイン画面に遷移します。

ここで必要になる処理としては、以下の3つとなります。
・ 編集画面がバックグラウンドに移動するタイミングでのイベント処理
・ ファイル保存処理
・ アクションバーの [削除] 選択時のファイル削除、画面閉じる処理
それぞれについて説明していきます。

編集画面がバックグラウンドに移動するタイミングでのイベント処理

Android アプリの画面 (Activity) がバックグラウンドに移動するタイミングで処理するには、Activity クラスの onPause メソッドをオーバーライドします。
このイベントを処理する部分は以下のようになります。
EditActivity.java ファイルに以下のメソッドを追加します。

@Override
protected void onPause() {
    super.onPause();
    // ここでファイル保存処理を行う
}

このイベントで処理を行うと、端末の 「戻る」 ボタンが押下されたときにファイル保存をすることができます。
また、端末の 「ホーム」ボタン押下等で、この画面がバックグラウンドに移動するような場合でも内容が保存できますので、入力された内容を確実に保存することができます。
Android アプリでは、画面上で管理しているデータがある場合は、この onPause で保存します。
これについて詳しく知りたい方は、Activity のライフサイクルについて を参照してみてくだい。

それでは、ここにファイル保存の処理を追加していきます。

ファイル保存処理

編集画面で入力される 「タイトル」 と 「内容」 をファイル保存する処理を追加していきます。
Android アプリで端末に保存する場合、アプリ毎に専用のファイル保存フォルダがあります。
他のアプリとデータを共有することがない場合は、通常この専用のファイル保存フォルダにアプリのデータを保存します。
専用の保存フォルダへのファイル保存は、Activity クラスの openFileOutput メソッドを使用すれば、 ファイル名を引数として渡すだけで保存可能ですので、このメソッドを使用して保存処理を行います。
(保存フォルダは、/data/data/パッケージ名(ここでは com.example.memoapp)/files/ 以下となります。)

このメソッドを使用した onPause イベントでのファイル保存の処理は以下のようになります。
(クラスのメンバに、String mFileName と boolean mNotSave も追加してください。)

@Override
protected void onPause() {
    super.onPause();
    
    // [削除] で画面を閉じるときは、保存しない
    if (mNotSave) {
        return;
    }
    
    // タイトル、内容を取得
    EditText eTxtTitle = (EditText)findViewById(R.id.eTxtTitle);
    EditText eTxtContent = (EditText)findViewById(R.id.eTxtContent);
    String title = eTxtTitle.getText().toString();
    String content = eTxtContent.getText().toString();
    
    // タイトル、内容が空白の場合、保存しない
    if (title.isEmpty() && content.isEmpty()) {
        Toast.makeText(this, R.string.msg_destruction, Toast.LENGTH_SHORT).show();
        return;
    }
    
    // ファイル名を生成  ファイル名 : yyyyMMdd_HHmmssSSS.txt
    // (既に保存されているファイルは、そのままのファイル名とする)
    if (mFileName.isEmpty()) {
        Date date = new Date(System.currentTimeMillis());
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmssSSS", Locale.JAPAN);
        mFileName = sdf.format(date) + ".txt";
    }
    
    // 保存
    OutputStream out = null;
    PrintWriter writer = null;
    try{
        out = this.openFileOutput(mFileName, Context.MODE_PRIVATE);
        writer = new PrintWriter(new OutputStreamWriter(out,"UTF-8"));
        // タイトル書き込み
        writer.println(title);
        // 内容書き込み
        writer.print(content);
        writer.close();
        out.close();
    }catch(Exception e){
        Toast.makeText(this, "File save error!", Toast.LENGTH_LONG).show();
    }
}

また、Toastで表示する文字の定義を、strings.xml に追加します。

<string name="msg_destruction">メモを破棄しました。</string>


まず、入力されたタイトルと内容を取得するために、EditTextのテキストを取得します。
findViewById メソッドで、タイトルおよび内容の EditText を取得し、getText().toString() で設定されているテキストの文字列を取得します。

次にファイル名を生成します。
ファイル名は、重複しないように、日付と時間を使用して、20141201_211530678.txt のようにします。
Data クラスを使用してミリ秒単位の時間を取得し、SimpleDataFormat クラスを使用して上記のような文字列にフォーマットします。

最後に、ファイルを作成します。
アプリ専用の保存フォルダに保存するため、Activity クラスの openFileOutput メソッドを使用します。
引数にファイル名と、モードを渡します。このアプリからしかアクセスしないファイルですので、モードには MODE_PRIVATE を設定します。
そして、PrintWrite クラスを使用して、ファイルを書き込みます。
先頭一行をタイトル、次の行以降を内容として保存しますので、タイトルの書き込みには行書き込みの println、内容には print メソッドを使用して書き込みます。

これで、編集画面がバックグラウンドに移動するタイミングで、入力されたタイトルと内容をファイル保存することができます。

アクションバーで [削除] 選択時のファイル削除、画面閉じる処理

最後に、アクションバーで [削除] を選択したときに、ファイルを削除する処理を追加します。
アクションバーのメニューを選択したときのイベント処理については、2.5. 画面遷移の処理 で説明していますので、 ここでも同様にイベント処理を追加します。
ファイルの削除は、保存と同様に Activity クラスで用意されている deleteFile メソッドを使用します。
このメソッドを使用することで、アプリ専用の保存フォルダにあるファイルを、ファイル名を指定するだけで削除することができます。

アクションバーのメニュー選択イベントと、ファイル削除処理は以下のようになります。

// メニュー選択時の処理
@Override
public boolean onMenuItemSelected(int featureId, MenuItem item) {
    switch(item.getItemId()) {
    case R.id.action_del:
        // [削除] 選択処理
        // ファイル削除
        if (!mFileName.isEmpty()) {
            this.deleteFile(mFileName);
        }     
        // 保存せずに、画面を閉じる
        mNotSave = true;
        this.finish();
        break;
    default:
        break;
    }
    
    return super.onMenuItemSelected(featureId, item);
}

アクションバーのアイテム [削除] が選択されたときに、ファイル削除処理を行います。
ファイルが保存されていれば、mFileName は空ではないので、このときに delete ファイルメソッドを使用してファイルを削除します。
また、画面を閉じるには Activity クラスの finish メソッドを使用します。
finish メソッドで画面を閉じるときも onPause メソッドが呼び出され、ファイル保存されてしまうので、 mNotSave フラグを true に設定し、onPause メソッドでファイル保存されないようにします。

これで、削除ボタン押下したときにファイルを削除し、画面を閉じる処理は完了です。



次は・・・
メイン画面で、保存されているファイルをリストに一覧表示する処理について説明します。
2.7. メイン画面のリストデータ表示