Android
アプリ固有のストレージでのファイル操作
(API30以降)

2023.8.4 Coskx Lab  

1 はじめに

Android11(R)API30以降ではファイル保存領域の扱いが厳格になっています。
大きく分けると次のようになっています。

  1. 内部ストレージ内のアプリ固有のディレクトリ
    他のアプリからはアクセス出来ないディレクトリ
  2. 外部ストレージ内のアプリ固有のディレクトリ
    他のアプリは通常アクセスできないが,特別に権限を持ったファイルマネージャアプリなどではアクセス可能なディレクトリ
  3. 共有ストレージ内のメディア用途のディレクトリ
    メディア ファイル用で他のアプリもアクセスできるディレクトリ
  4. 共有ストレージ内の一般用途のディレクトリ
    他のアプリからアクセスされることを前提としたディレクトリ

ここでは,次の2つについて説明します。

ここで扱わない「共有ストレージ内のディレクトリ(一般的なファイル)」については次を参照してください。
共有ストレージ

なお,本説明内容のテストプログラムをダウンロードできます。
MainActivity.javaとactivity_main.xmlが入っています。(API24以上でテスト済)
ダウンロード

ストレージ詳細  


2 使用環境


3 内部ストレージ内のアプリ固有のディレクトリ

内部ストレージ内のアプリ固有のディレクトリへのファイルの書き込み,読み込みをします。
内部ストレージ内のアプリ固有のディレクトリ名を取得すれば,任意のファイル名で作業ができます。
内部ストレージ内のアプリ固有のディレクトリは
メソッド File getFilesDir()
で得ることができます。
内部ストレージ内のアプリ固有のディレクトリ名を文字列として確認するためには,
String internalstorage = String.valueOf( this.getFilesDir() );
で得ることができます。(MainActivity内)
Device File Explorerで見るときとは異なり,実際は次のように得られました。
/data/user/0/[applicationId]/files

3.1 内部ストレージ内のアプリ固有のディレクトリへのファイル書き込み

内部ストレージ内のアプリ固有のディレクトリへのファイル書き込みの例を示します。

String internalfname = "intsample.txt";
String internaltext = "Hello,\nTHis is a internalstorage sample text.\n";
File file1;
String message;

file1 = new File(this.getFilesDir(), internalfname);
try (FileWriter writer = new FileWriter(file1,true)) {
    writer.write(internaltext);
    writer.flush();
    writer.close();
    message = "File saved.";
} catch (IOException e) {
    message = e.getMessage();
    e.printStackTrace();
}
Log.i(TAG, message);

3.2 内部ストレージ内のアプリ固有のディレクトリからのファイル読み込み

内部ストレージ内のアプリ固有のディレクトリからのファイル読み込みの例を示します。

String internalfname = "intsample.txt";
File file1;
String message;

StringBuilder text = new StringBuilder();
file1 = new File(this.getFilesDir(), internalfname);
try (BufferedReader reader = new BufferedReader(new FileReader(file1))) {
    String lineBuffer;
    lineBuffer = reader.readLine();
    while (lineBuffer != null) {
        text.append(lineBuffer).append("\n");
        lineBuffer = reader.readLine();
    }
    message = "text read = [\n" + text + "]";
} catch (IOException e) {
    message = e.getMessage();
    e.printStackTrace();
}
Log.i(TAG, message);

3.3 内部ストレージ内のアプリ固有のディレクトリ内のファイル一覧を得る

内部ストレージ内のアプリ固有のディレクトリ内のファイル一覧を得る例を示します。

File dir;
File[] files;
String message;

StringBuilder text = new StringBuilder("\n");
dir = this.getFilesDir();
files = dir.listFiles();
if (files != null) {
    for (File file : files) {
        text.append(file.getName()).append("\n");
    }
}
message = "listed filenames = [" + text.toString() + "]";
Log.i(TAG, message);

3.4 内部ストレージ内のアプリ固有のディレクトリ内のファイルを全消去する

内部ストレージ内のアプリ固有のディレクトリ内のファイルを全消去する例を示します。

File dir;
File[] files;
String message;

StringBuilder text = new StringBuilder("\n");
dir = this.getFilesDir();
files = dir.listFiles();
if (files != null) {
    for (File file : files) {
        text.append(file.getName()).append("\n");
        file.delete();
    }
}
message = "deleted files = [" + text.toString() + "]";
Log.i(TAG, message);

4 外部ストレージ内のアプリ固有のディレクトリ

外部ストレージ内のアプリ固有のディレクトリへのファイルの書き込み,読み込みをします。
外部ストレージ内のアプリ固有のディレクトリ名を取得すれば,任意のファイル名で作業ができます。
外部ストレージ内のアプリ固有のディレクトリは
メソッド File getExternalFilesDir( Environment.DIRECTORY_DOCUMENTS )
で得ることができます。
外部ストレージ内のアプリ固有のディレクトリ名を文字列として確認するためには,
String externalstorage = String.valueOf( this.getExternalFilesDir( Environment.DIRECTORY_DOCUMENTS ) );
で得ることができます。(MainActivity内) 実際には次のように得られました。
/storage/emulated/0/Android/data/ [applicationId] /files/Documents

補足

File getExternalFilesDir( Environment.DIRECTORY_DOCUMENTS ) の代わりに
File getExternalFilesDir( Environment.DIRECTORY_PICTURES )
にすると
/storage/emulated/0/Android/data/ [applicationId] /files/Pictures
になります。
Environment.DIRECTORY_xxxxxxx にはいろいろな設定があります。

4.1 外部ストレージ内のアプリ固有のディレクトリへのファイル書き込み

外部ストレージ内のアプリ固有のディレクトリへのファイル書き込みの例を示します。
FileWriter()の第2引数は上書き又は追記を指示します。
 true:追記 false:上書き

String externalfname = "extsample.txt";
String externaltext = "Hello,\nTHis is a externalstorage sample text.\n";
File dir;
File file1;
String message;

dir = this.getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS);
file1 = new File(dir, externalfname);
Log.i(TAG,"file name = " + String.valueOf(file1));
boolean done = false;
try (FileWriter writer = new FileWriter(file1,true)) {
    writer.write(externaltext);
    writer.flush();
    writer.close();
    done = true;
    message = "File saved.";
} catch (IOException e) {
    message = e.getMessage();
    e.printStackTrace();
}
Log.i(TAG, message);

4.2 外部ストレージ内のアプリ固有のディレクトリからのファイル読み込み

外部ストレージ内のアプリ固有のディレクトリからのファイル読み込みの例を示します。

String externalfname = "extsample.txt";
File dir;
File file1;
String message;

StringBuilder text = new StringBuilder();
dir = this.getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS);
file1 = new File(dir, externalfname);
try (BufferedReader reader = new BufferedReader(new FileReader(file1))) {
    String lineBuffer;
    lineBuffer = reader.readLine();
    while (lineBuffer != null) {
        text.append(lineBuffer).append("\n");
        lineBuffer = reader.readLine();
    }
    message = "text read = [\n" + text + "]";
} catch (IOException e) {
    message = e.getMessage();
    e.printStackTrace();
}
Log.i(TAG, message);

4.3 外部ストレージ内のアプリ固有のディレクトリ内のファイル一覧を得る

外部ストレージ内のアプリ固有のディレクトリ内のファイル一覧を得る例を示します。

File dir;
File[] files;
String message;

StringBuilder text = new StringBuilder("\n");
dir = this.getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS);
files = dir.listFiles();
if (files != null) {
    for (File file : files) {
        text.append(file.getName()).append("\n");
    }
}
message = "listed filenames = [" + text.toString() + "]";
Log.i(TAG, message);

4.4 外部ストレージ内のアプリ固有のディレクトリ内のファイルを全消去する

外部ストレージ内のアプリ固有のディレクトリ内のファイルを全消去する例を示します。

File dir;
File[] files;
String message;

StringBuilder text = new StringBuilder("\n");
dir = this.getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS);
files = dir.listFiles();
if (files != null) {
    for (File file : files) {
        text.append(file.getName()).append("\n");
        file.delete();
    }
}
message = "deleted files = [" + text.toString() + "]";
Log.i(TAG, message);

5 補足

6 まとめ

内部ストレージ内のアプリ固有のディレクトリ,および外部ストレージ内のアプリ固有のディレクトリで,それぞれについてファイル操作について示しました。
内部ストレージ内のアプリ固有のディレクトリでは,getFilesDir()で対象ディレクトリを得ることができます。
外部ストレージ内のアプリ固有のディレクトリでは,getExternalFilesDir( Environment.DIRECTORY_DOCUMENTS )で対象ディレクトリを得ることができます。