ストレージへアクセスする方法

投稿日:  更新日:

ストレージへアクセスする方法は、「扱うデータの種類」「アクセス先」「セキュリティの確保」などの要件により、最適なアクセス方法が存在するので、使い分けが必要です。

今回は「アクセスする方法」について、まとめます。

※環境:Android Studio Narwhal | 2025.1.1 Patch 1

スポンサーリンク

アクセスする方法

Androidアプリが、プログラムからストレージへアクセスする方法は3つあります。

  • ・Java(Kotlin)/ Android API
  • ・Media Store
  • ・SAF(Storage Access Framework)

「扱うデータの種類」「アクセス先」「セキュリティの確保」などの要件により、最適なアクセス方法が存在するので、使い分けが必要です。

Java(Kotlin)/ Android API

Fileクラスを使ったJava(Kotlin)API標準の方法です。

保存先のパスはAndroid APIに組み込まれているので、関数を使って容易にFileオブジェクトを取得できます。

fun writeToFile_Basic(data: ByteArray, file: File) {
    try {
        file.outputStream().use { stream ->
            stream.write(data)
        }
    } catch (e: Exception) { Log.i(TAG, "[writeToFile] ${e}") }
}
                                val _file = File(this@Activity.filesDir, _filename)  // 保存先のパス
                                writeToFile_Basic(_data, _file)

サンプルはアクセス方法を大まかに表現したものです。

※詳細は以下を参照
「内部ストレージにJava/Android APIでアクセス」
「外部ストレージ_プライマリにJava/Android APIでアクセス」
「外部ストレージ_セカンダリにJava/Android APIでアクセス」

Media Store

Content Resolver/Provider経由で、外部ストレージに保存されるメディアデータへ、アクセスする方法です。

メディアデータはデータベースで効率よく管理されています。

Media Storeの概要

private val ContentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI

fun Context.insertImage(data: ByteArray): Uri? {
    val _contentValues = ContentValues()

    val _mediaUri = contentResolver.insert(ContentUri, _contentValues)
    _mediaUri?.let { writeToUri_Resolver(data, _mediaUri) }

    return _mediaUri
}
fun Context.writeToUri_Resolver(data: ByteArray, uri: Uri) {
    try {
        contentResolver.openOutputStream(uri, "w")?.use { outputStream ->
            outputStream.write(data)
            outputStream.flush()
        }
    } catch (e: Exception) { Log.i(TAG, "[writeToUri] ${e}") }
}
_uri = insertImage(_data)

サンプルはアクセス方法を大まかに表現したものです。

※詳細は以下を参照
「」

SAF(Storage Access Framework)

Content Resolver/Provider経由で、外部ストレージに保存される全てのデータへ、アクセスする方法です。

アクセス対象のファイルは、Clientアプリが提供する標準のファイルピッカー(GUI)を使って、選択できます。

SAFの概要

SAFのファイルピッカー

fun FileCreateIntent(filename: String) =	// Clientアプリのインテント
    Intent(Intent.ACTION_CREATE_DOCUMENT).apply {
        addCategory(Intent.CATEGORY_OPENABLE)
        putExtra(Intent.EXTRA_TITLE, filename)
        type = "*/*"
    }

fun ComponentActivity.CreateDocLauncher(callback: (Uri) -> Unit) =
    registerForActivityResult(
        ActivityResultContracts.StartActivityForResult()
    ) { result ->							// Clientアプリの結果を処理
        if(result.resultCode == RESULT_OK) {
            val _intent = result.data
            _intent?.let {
                val _uri = it.data
                _uri?.let { callback(it) }	// ※Aを実行
            }
        }
        else {
            Log.i(TAG, "ファイルが選べません !")
        }
    }
        val _create = CreateDocLauncher { uri ->    // Clientランチャーの作成
            writeToUri_Resolver(_data, uri)			// Uriへデータの書き込み(※A)
        }
		
		_create.launch(FileCreateIntent(_filename))	// Clientアプリの起動
fun Context.writeToUri_Resolver(data: ByteArray, uri: Uri) {
    try {
        contentResolver.openOutputStream(uri, "w")?.use { outputStream ->
            outputStream.write(data)
            outputStream.flush()
        }
    } catch (e: Exception) { Log.i(TAG, "[writeToUri] ${e}") }
}

サンプルはアクセス方法を大まかに表現したものです。

※詳細は以下を参照
SAFを使用してファイルを開く

スポンサーリンク

アクセス先の分類

アクセス方法をアクセス先毎に分類しました。

アクセス先により、利用できないアクセス方法があります。また、最適なアクセス方法が存在するので、使い分けが必要です。

上段と下段は次の意味を持ちます。

  • 上段:「アプリ自身が作成したファイル(自)」へアクセスする場合
  • 下段:「他のアプリが作成したファイル(他)」へアクセスする場合

内部ストレージ

利用可能なアクセス方法は「Java(Kotlin)/ Android API」のみです。

内部ストレージ
/data/data/ユーザーID
Java /
Android
API
Media Store
API
SAF
アプリ固有
(パッケージ名/files)
自:◎wr
他:×  
         
※自:自アプリのファイル
 他:他アプリのファイル
 ◎:アクセスできる(最適)
 ○:アクセスできる
 △:アクセスできる(不適または制限有)
 ×:アクセスできない
 空:アクセスできない(サポート外)
 w:書き込みできる
 r:読み出しできる
 p:パーミッションが必要

※内部ストレージの詳細は「ストレージの用途別記憶領域とボリューム」を参照
※アクセス方法の詳細は以下を参照
「内部ストレージにJava/Android APIでアクセス」

外部ストレージ_プライマリ

「メディアデータ」のアクセスは「Media Store」が最適です。他の方法は、データベースの更新が行われません。

「ドキュメント・他のファイル」のアクセスは「SAF(Storage Access Framework)」が最適です。SAFは、ピッカー(GUI)を使いユーザの意思で保存先(ディレクトリ)とファイル名が決められます。保存先を新たに作ることも可能です。

アクセスするパーミッションと権限の範囲が、「対象範囲別ストレージ(API≧29)」と「きめ細かいメディア権限(API≧33)」で大きく変更されている点に注意して下さい。

API≦28API=29API=30~32API≧33
外部ストレージ プライマリ
/storage/emulated/ユーザーID
Java /
Android
API
Media Store
API
SAF
メディアデータPictures
自:△wrp
他:△wrp
 
自:◎wrp
他:◎wrp
 
自:△wr 
他:△wr 
 
DCIM
Movies
Music
Alarms
Notifications
Podcasts
Ringtones
Audiobooks(API≧30)
Recordings(API≧31)
ドキュメント
他のファイル
Downloads
自:○wrp
他:○wrp
自:◎wrp
他:◎wrp
自:◎wr 
他:◎wr 
Documants
Android
(Android/dataを除く)
ユーザーフォルダ
ユーザーファイル
アプリ別
 Android/data/パッケージ名/files
自:○wr 
他:△wrp
自:○wr 
他:○wr 
※自:自アプリのファイル
 他:他アプリのファイル
 ◎:アクセスできる(最適)
 ○:アクセスできる
 △:アクセスできる(不適または制限有)
 ×:アクセスできない
 空:アクセスできない(サポート外)
 w:書き込みできる
 r:読み出しできる
 p:パーミッションが必要
外部ストレージ プライマリ
/storage/emulated/ユーザーID
Java /
Android
API
Media Store
API
SAF
メディアデータPictures
自:×   
他:×   
 
自:◎wr 
他:◎ rp
 
自:△wr 
他:△wr 
 
DCIM
Movies
Music
Alarms
Notifications
Podcasts
Ringtones
Audiobooks(API≧30)
Recordings(API≧31)
ドキュメント
他のファイル
Downloads
自:×   
他:×   
自:◎wr 
他:×   
自:◎wr 
他:◎wr 
Documants
Android
(Android/dataを除く)
ユーザーフォルダ
ユーザーファイル
アプリ別
 Android/data/パッケージ名/files
自:○wr 
他:×   
自:○wr 
他:○wr 
※自:自アプリのファイル
 他:他アプリのファイル
 ◎:アクセスできる(最適)
 ○:アクセスできる
 △:アクセスできる(不適または制限有)
 ×:アクセスできない
 空:アクセスできない(サポート外)
 w:書き込みできる
 r:読み出しできる
 p:パーミッションが必要
外部ストレージ プライマリ
/storage/emulated/ユーザーID
Java /
Android
API
Media Store
API
SAF
メディアデータPictures
自:×   
他:×   
 
自:◎wr 
他:◎ rp
※1
自:△wr 
他:△wr 
 
DCIM
Movies
Music
Alarms
Notifications
Podcasts
Ringtones
Audiobooks(API≧30)
Recordings(API≧31)
ドキュメント
他のファイル
Downloads
自:○wr 
他:×   
自:◎wr 
他:×   
自:◎wr 
他:◎wr 
Documants
Android
(Android/dataを除く)
自:×   
他:×   
ユーザーフォルダ
ユーザーファイル
アプリ別
 Android/data/パッケージ名/files
自:○wr 
他:×   
自:×   
他:×   
※自:自アプリのファイル
 他:他アプリのファイル
 ◎:アクセスできる(最適)
 ○:アクセスできる
 △:アクセスできる(不適または制限有)
 ×:アクセスできない
 空:アクセスできない(サポート外)
 w:書き込みできる
 r:読み出しできる
 p:パーミッションが必要
※1:書き込みはファイル毎に権限の取得が必要、通常のパーミッションとは別
外部ストレージ プライマリ
/storage/emulated/ユーザーID
Java /
Android
API
Media Store
API
SAF
メディアデータPictures
自:×   
他:×   
 
自:◎wr 
他:◎ rp
※1
自:△wr 
他:△wr 
 
DCIM
Movies
Music
Alarms
Notifications
Podcasts
Ringtones
Audiobooks(API≧30)
Recordings(API≧31)
ドキュメント
他のファイル
Downloads
自:○wr 
他:×   
自:◎wr 
他:×   
自:◎wr 
他:◎wr 
Documants
Android
(Android/dataを除く)
自:×   
他:×   
ユーザーフォルダ
ユーザーファイル
アプリ別
 Android/data/パッケージ名/files
自:○wr 
他:×   
自:×   
他:×   
※自:自アプリのファイル
 他:他アプリのファイル
 ◎:アクセスできる(最適)
 ○:アクセスできる
 △:アクセスできる(不適または制限有)
 ×:アクセスできない
 空:アクセスできない(サポート外)
 w:書き込みできる
 r:読み出しできる
 p:パーミッションが必要(コレクション毎)
※1:書き込みはファイル毎に権限の取得が必要、通常のパーミッションとは別

※外部ストレージ_プライマリの詳細は「ストレージの用途別記憶領域とボリューム」を参照
※アクセス方法の詳細は以下を参照
「外部ストレージ_プライマリにJava/Android APIでアクセス」

外部ストレージ_セカンダリ

「ドキュメント・他のファイル」のアクセスは「SAF(Storage Access Framework)」が最適です。SAFは、ピッカー(GUI)を使いユーザの意思で保存先(ディレクトリ)とファイル名が決められます。保存先を新たに作ることも可能です。

主に他のデバイス(他の携帯端末やパソコンなど)と共有するデータを保存する領域なので、ユーザの意思(公開してもよいか?!)を重視したアクセス方法にします。

AP<29AP=29API≧30
外部ストレージ セカンダリ
/storage/NNN-NNN/
Java /
Android
API
Media Store
API
SAF
ドキュメント
他のファイル
Downloads
自:×   
他:×   
自:◎wr
他:◎wr
Documents
Android
(Android/dataを除く)
ユーザーフォルダ
ユーザーファイル
アプリ別
(Android/data/パッケージ名/files)
自:○wr 
他:△ rp
自:○wr
他:○wr
※自:自アプリのファイル
 他:他アプリのファイル
 ◎:アクセスできる(最適)
 ○:アクセスできる
 △:アクセスできる(不適または制限有)
 ×:アクセスできない
 空:アクセスできない(サポート外)
 w:書き込みできる
 r:読み出しできる
 p:パーミッションが必要
外部ストレージ セカンダリ
/storage/NNN-NNN/
Java /
Android
API
Media Store
API
SAF
ドキュメント
他のファイル
Downloads
自:×   
他:×   
自:◎wr
他:◎wr
Documents
Android
(Android/dataを除く)
ユーザーフォルダ
ユーザーファイル
アプリ別
(Android/data/パッケージ名/files)
自:○wr 
他:×   
自:○wr
他:○wr
※自:自アプリのファイル
 他:他アプリのファイル
 ◎:アクセスできる(最適)
 ○:アクセスできる
 △:アクセスできる(不適または制限有)
 ×:アクセスできない
 空:アクセスできない(サポート外)
 w:書き込みできる
 r:読み出しできる
 p:パーミッションが必要
外部ストレージ セカンダリ
/storage/NNN-NNN/
Java /
Android
API
Media Store
API
SAF
ドキュメント
他のファイル
Downloads
自:△wr 
他:×   
自:◎wr
他:◎wr
Documents
Android
(Android/dataを除く)
自:×   
他:×   
ユーザーフォルダ
ユーザーファイル
アプリ別
(Android/data/パッケージ名/files)
自:○wr 
他:×   
自:×  
他:×  
※自:自アプリのファイル
 他:他アプリのファイル
 ◎:アクセスできる(最適)
 ○:アクセスできる
 △:アクセスできる(不適または制限有)
 ×:アクセスできない
 空:アクセスできない(サポート外)
 w:書き込みできる
 r:読み出しできる
 p:パーミッションが必要

※外部ストレージ_セカンダリの詳細は「ストレージの用途別記憶領域とボリューム」を参照
※アクセス方法の詳細は以下を参照
「外部ストレージ_セカンダリにJava/Android APIでアクセス」

スポンサーリンク

Appendix:Googleのドキュメント

StorageのドキュメントがGoogleから提供されています。詳細は以下のリンクを参照してください。

データ ストレージとファイル ストレージの概要

Storageについて、ほぼ網羅されたドキュメントだと思われます。しかし、非常に説明が難解です。

スポンサーリンク

関連記事:

ストレージのリソース
ストレージのリソースは、内部メモリー、外部メモリー、クラウドの3つがあります。 外部メモリーは、主にSDカードです。 このSDカードはAndroid端末の世代が進むにつれて、扱いを変えてきました。 リソースとSDカードを主眼に置いたストレージの変遷について、まとめます。 ※環境:Android Studio Narwhal | 2025.1.1 Patch 1 ...
Adoptable Storage(SDカードの扱い方を指定)
Adoptable Storage(API≧23、Android 6.0)が導入されて、SDカードの扱い方をユーザ側で指定できるようになりました。 「Adoptable Storage」について、まとめます。 ※環境:Android Studio Narwhal | 2025.1.1 Patch 1 ...
ストレージの用途別記憶領域とボリューム
ストレージはデータの用途別に記憶領域が分けられます。 保存先を守らないと、セキュリティリスクが発生したり、他のアプリと協調した動作が出来なくなったり、します。 ですので、適切な場所へデータを保存しましょう。 今回は「用途別記憶領域とボリューム」について、まとめます。 ※環境:Android Studio Narwhal | 2025.1.1 Patch 1 ...
内部ストレージにJava/Android APIでアクセス
「内部ストレージ」にアクセスする方法について、まとめます。 「内部ストレージ」は、セキュリティが高いうえに、端末の内部メモリーに構築されるので、必ず存在します。 使いたい時に安心して使え、もっとも使い勝手のよいストレージと言えます。 アプリのデータを保存したいならば、保存先として真っ先に考えるストレージです。 ※環境:Android Studio Narwhal | 2025.1.1 Patch 1 ...
スポンサーリンク