妄想プログラマのらくがき帳 : 1月 2013

2013年1月28日月曜日

[Android]外部ストレージのパブリックディレクトリに読み書きを行う

内部ストレージや外部ストレージのアプリPrivate領域に保存したファイルは、
アプリのアンインストール時に全て削除されます。
しかし、カメラで撮影した写真(画像ファイル)やエディタで編集したテキストファイル等は
アプリをアンインストールしても残しておきたいファイルです。
そんなファイルを保存するためのディレクトリが外部ストレージのパブリックディレクトリです。

外部ストレージのパブリックディレクトリにファイルを作成し、データを保存する

外部ストレージのパブリックディレクトリにファイルを作成し、データを書き込むコードは以下のようになります。
※コードでは前回同様http://developer.android.com/training/basics/data-storage/files.htmlにあるisExternalStorageWritable()とisExternalStorageReadable()を使ってます。
// 外部ストレージに書き込み可能かチェック
if (isExternalStorageWritable()) {
 FileOutputStream outputStream;
 
 // ※以下、例外処理は省略

 // パブリックディレクトリにファイルを作成し、書き込む。 
 File file = new File(
     Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS),
     "myfile.txt");

 outputStream = new FileOutputStream(file);

 outputStream.write("test".getBytes());
 
 // ちなみにDDMSで確認したところ、確認時の環境下では
 // "/mnt/sdcard/Download/myfile.txt"
 // に書き込まれた。
 
 outputStream.close();
}
アプリPrivate領域に保存する時との違いは、getExternalFilesDir()ではなくEnvironment.getExternalStoragePublicDirectory()を使う点です。
Environment.getExternalStoragePublicDirectory()の引数に指定するディレクトリのタイプは、getExternalFilesDir()と同じです。

外部ストレージのパブリックディレクトリに保存したファイルからデータを読み込む

ファイルからデータを読み込むコードは以下のようになります。
// 外部ストレージから読み込み可能かチェック
if (isExternalStorageReadable()) {
 FileInputStream inputStream;
 byte[] buffer = new byte[256];

 // ※以下、例外処理は省略
 
 File file = new File(
     Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS),
     "myfile.txt");

 if (file.exists()) {
  inputStream = new FileInputStream(file);
  inputStream.read(buffer);

  String data = new String(buffer, "UTF-8");

  inputStream.close();
 }
}
こちらもgetExternalFilesDir()ではなくEnvironment.getExternalStoragePublicDirectory()を使う点が異なるだけです。

2013年1月21日月曜日

[Android]外部ストレージのファイルに読み書きを行う

Androidアプリのファイル保存先には外部ストレージもあります。
外部ストレージの特徴として以下の3点が挙げられます。
  • デバイスが取り外されていて使用できない場合がある
  • ファイルは外部から読み書き可能
    (内部ストレージに保存するときみたいに、Context.MODE_PRIVATEを指定して外部に非公開にできない)
  • 保存したファイルはアプリのアンインストール時に削除される
外部ストレージに置いたファイルは他アプリからもアクセス可能なので、
他アプリから使用するようなデータは外部ストレージに保存します。

外部ストレージが使用可能かチェックする

外部ストレージは常に使用可能とは限らないので、読み書きする前に使用可能かチェックする必要があります。
読み書き可能かどうかはEnvironment.getExternalStorageState()の戻り値で判断できます。

チェック用のコードですが、http://developer.android.com/training/basics/data-storage/files.htmlにあるisExternalStorageWritable()とisExternalStorageReadable()がそのまま使えるので、これを使うことにします。

外部ストレージにファイルを作成し、データを保存する

外部ストレージにファイルを作成し、データを書き込むコードは以下のようになります。
// 外部ストレージに書き込み可能かチェック
if (isExternalStorageWritable()) {
 FileOutputStream outputStream;
 
 // ※以下、例外処理は省略

 // 外部ストレージにファイルを作成し、書き込む。 
 File file = new File(getExternalFilesDir(null), "myfile.txt");
 outputStream = new FileOutputStream(file);

 outputStream.write("test".getBytes());
 
 // ちなみにDDMSで確認したところ、確認時の環境下では
 // "/mnt/sdcard/Android/data/[パッケージ名]/files/myfile.txt"
 // に書き込まれた。
 
 outputStream.close();
}
getExternalFilesDir()の引数にはディレクトリのタイプを指定します。
Environment.DIRECTORY_MUSIC や Environment.DIRECTORY_PICTURESといった定数を指定でき、
これらを指定することでディレクトリ内のデータがシステムから適切に扱われるようになります。
例えば、Environment.DIRECTORY_RINGTONESを指定したディレクトリにあるオーディオファイルは、着信音として扱われます。
これらの定数ではなくnullを指定すると、アプリ用ディレクトリのルートディレクトリが返されます。

外部ストレージに保存したファイルからデータを読み込む

ファイルからデータを読み込むコードは以下のようになります。
// 外部ストレージから読み込み可能かチェック
if (isExternalStorageReadable()) {
 FileInputStream inputStream;
 byte[] buffer = new byte[256];

 // ※以下、例外処理は省略
 
 File file = new File(getExternalFilesDir(null), "myfile.txt");

 if (file.exists()) {
  inputStream = new FileInputStream(file);
  inputStream.read(buffer);

  String data = new String(buffer, "UTF-8");

  inputStream.close();
 }
}

2013年1月14日月曜日

[Android]キャッシュファイルに読み書きを行う

内部ストレージにはキャッシュファイル専用のディレクトリがあります。
このディレクトリの特徴として以下の3点が挙げられます。
  • アプリのprivate領域にある
  • 内部ストレージが不足状態になると、このフォルダ内のデータはシステムによって削除される可能性がある
  • キャッシュファイルはアプリのアンインストール時に削除される
2点目が大きな特徴です。この特徴があるため、ファイルが必要無くなったら削除を行い、1MB程度の使用量に抑えておく必要があります。

キャッシュディレクトリにファイルを作成し、データを保存する

キャッシュディレクトリにファイルを作成し、データを書き込むコードは以下のようになります。
FileOutputStream outputStream = null;
try {
    // キャッシュ領域にファイルを作成し、書き込む。
    File file = new File(getCacheDir(), "cache.txt");
    file.createNewFile();
    if (file.exists()) {
        outputStream = new FileOutputStream(file);

        outputStream.write("test".getBytes());
        // ちなみにDDMSで確認したところ、確認時の環境下では
        // "/data/data/[パッケージ名]/cache/cache.txt"
        // に書き込まれた。
    }
} catch (IOException e) {
    Log.e("MyApp", "exception", e);
}
finally {
    try {
        if(outputStream != null) { outputStream.close(); }
    }
    catch (IOException e){
        Log.e("MyApp", "exception", e);
    }
}

キャッシュディレクトリに保存したファイルからデータを読み込む

ファイルからデータを読み込むコードは以下のようになります。
FileInputStream inputStream = null;
byte[] buffer = new byte[256];
try {
    File file = new File(getCacheDir(), "cache.txt");
    if (file.exists()) {
        inputStream = new FileInputStream(file);
        inputStream.read(buffer);
        String data = new String(buffer, "UTF-8");
    }
}catch (IOException e) {
    Log.e("MyApp", "exception", e);
}finally {
    try {
        if(inputStream != null) { inputStream.close(); }
    } catch (IOException e) {
        Log.e("MyApp", "exception", e);
    }
}

キャッシュディレクトリに保存したファイルを削除する

ファイルの削除はFileオブジェクトのdelete()を使います。
File file = new File(getCacheDir(), "cache.txt");
file.delete();

※2015/7/5  五嶋さんのコメントを受け、書き込み、読み込みのコードにtry-catch文を追加しました。

2013年1月7日月曜日

[Android]内部ストレージのファイルに読み書きを行う

Androidアプリのファイル保存先の一つに内部ストレージがあります。
内部ストレージの特徴として以下の3点が挙げられます。
  • 常に使用可能
  • ファイルはアプリのprivate領域に保存される
  • 保存したファイルはアプリのアンインストール時に削除される
通常、アプリのみで使用するようなデータ(他のアプリから使用したりしないデータ)は
内部ストレージに保存するようです。

内部ストレージにファイルを作成し、データを保存する

内部ストレージにファイルを作成し、データを書き込むコードは以下のようになります。
FileOutputStream outputStream;

// ※以下、例外処理は省略

// 内部ストレージにファイルを作成し、書き込む。
outputStream = openFileOutput("myfile.txt", Context.MODE_PRIVATE);
outputStream.write("test".getBytes());

// ちなみにDDMSで確認したところ、確認時の環境下では
// "/data/data/[パッケージ名]/files/myfile.txt"
// に書き込まれた。

outputStream.close();
openFileOutput()でoutputStreamを直接取得してデータを書き込む方法の他に、
getFilesDir()を使って内部ストレージのルートディレクトリのFileオブジェクトを取得し、
そのFileオブジェクトを使ってデータを書き込む方法があります。

内部ストレージに保存したファイルからデータを読み込む

ファイルからデータを読み込むコードは以下のようになります。
FileInputStream inputStream;
byte[] buffer = new byte[256];

// ※以下、例外処理は省略

inputStream = openFileInput(FILE_NAME);
inputStream.read(buffer);

String data = new String(buffer, "UTF-8");

inputStream.close();
こちらも同様にgetFilesDir()からFileオブジェクトを取得し、それを利用する方法があります。