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

投稿日:  更新日:

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

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

※環境: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:書き込みはURI(ファイル)毎にアクセス許可が必要、通常のパーミッションとは別
外部ストレージ プライマリ
/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:パーミッションが必要(images/video/audioデータ毎)
※1:書き込みはURI(ファイル)毎にアクセス許可が必要、通常のパーミッションとは別

※外部ストレージ_プライマリの詳細は「ストレージの用途別記憶領域とボリューム」を参照
※アクセス方法の詳細は以下を参照
外部ストレージ_プライマリに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(API≧23、Android 6.0)が導入されて、SDカードの扱い方をユーザ側で指定できるようになりました。 「Adoptable Storage」について、まとめます。 ※環境:Android Studio Narwhal | 2025.1.1 Patch 1 ...
ストレージはデータの用途別に記憶領域が分けられます。 保存先を守らないと、セキュリティリスクが発生したり、他のアプリと協調した動作が出来なくなったり、します。 ですので、適切な場所へデータを保存しましょう。 今回は「用途別記憶領域とボリューム」について、まとめます。 ※環境:Android Studio Narwhal | 2025.1.1 Patch 1 ...
「内部ストレージ」にアクセスする方法について、まとめます。 「内部ストレージ」は、セキュリティが高いうえに、端末の内部メモリーに構築されるので、必ず存在します。 使いたい時に安心して使え、もっとも使い勝手のよいストレージと言えます。 アプリのデータを保存したいならば、保存先として真っ先に考えるストレージです。 ※環境:Android Studio Narwhal | 2025.1.1 Patch 1 ...
外部ストレージへアクセスするアプリは、パーミッション(許可)をユーザーから取得する必要があります。 パーミッションを得たアプリは、許可された権限の範囲内で、ストレージへアクセスが可能です。 これらは、ユーザーデータのプライバシー保護と密接に関係しています。 プライバシー保護をより強固にするために、パーミッションと権限の範囲の仕様は改変されてきました。 今回は、改変の歴史を辿りつつ、「パーミッションと権限の範囲」について、まとめます。 ※環境:Android Studio Narwhal | 2025.1.1 Patch 1 ...
「外部ストレージ_プライマリ」にアクセスする方法について、まとめます。 「外部ストレージ_プライマリ」は、アプリ間で共有するデータを保存するストレージです。 主にカメラ、音楽プレーヤー、動画プレーヤーで扱うデータを保存します。 「外部ストレージ_プライマリ」に保存したデータは、他のアプリに公開することになるので、秘匿性の高いデータの保存に適しません。 ※環境:Android Studio Narwhal | 2025.1.1 Patch 1 ...
「外部ストレージ_セカンダリ」にアクセスする方法について、まとめます。 「外部ストレージ_セカンダリ」は、デバイス間(または、アプリ間)で共有するデータを保存するストレージです。 デバイスとは、他の携帯端末やパソコンなどを指します。 ストレージがSDカードのような取り外し可能なリソース上に構築されているので、データの共有は取り外したストレージを他のデバイスへ取り付けて行います。 「外部ストレージ_セカンダリ」に保存したデータは、他のデバイスに公開することになるので、秘匿性の高いデータの保存に適しません。 ※環境:Android Studio Narwhal | 2025.1.1 Patch 1 ...
「外部ストレージ_プライマリ」に保存されるメディアデータは、Media Storeと呼ばれる特別な方法でアクセスします。 他の方法も可能ですが、Media Storeが最も適した方法です。 この「メディアデータへMedia Storeでアクセス」する方法を、まとめます。 この記事は、Imagesデータ編です。また、基本的なアクセス(読み書き)に的を絞って説明しています。 ※環境:Android Studio Narwhal | 2025.1.1 Patch 1 ...
メディアデータはデータベースによって管理されています。 Media Store APIを使ってメディアデータへアクセスしているのであれば、データベースの所在や構成などを意識する必要はありません。 ただ、「より複雑な制御をしたい場合」や「デバックを効率化したい場合」などに、データベースの知識が役立ちます。 今回は「メディアデータのデータベースによる管理」について、まとめます。 この記事は、Imagesデータ編です。 ※環境:Android Studio Narwhal | 2025.1.1 Patch 1 ...
「外部ストレージ_プライマリ」に保存されるメディアデータは、Media Storeと呼ばれる特別な方法でアクセスします。 他の方法も可能ですが、Media Storeが最も適した方法です。 この「メディアデータへMedia Storeでアクセス」する方法を、まとめます。 この記事は、Imagesデータ編です。また、基本的なアクセス(読み書き)に的を絞って説明しています。 ※環境:Android Studio Narwhal | 2025.1.1 Patch 1 ...
メディアデータはデータベースによって管理されています。 Media Store APIを使ってメディアデータへアクセスしているのであれば、データベースの所在や構成などを意識する必要はありません。 ただ、「より複雑な制御をしたい場合」や「デバックを効率化したい場合」などに、データベースの知識が役立ちます。 今回は「メディアデータのデータベースによる管理」について、まとめます。 この記事は、Imagesデータ編です。 ※環境:Android Studio Narwhal | 2025.1.1 Patch 1 ...
「外部ストレージ_プライマリ」に保存されるメディアデータは、Media Storeと呼ばれる特別な方法でアクセスします。 他の方法も可能ですが、Media Storeが最も適した方法です。 別の記事で「メディアデータへMedia Storeでアクセス」する方法を、まとめました。 その記事は、基本的なアクセスとして「追加(insert)&読み書き」のみを説明しています。 この記事は、上記に加えて「参照(query)・更新(update)・削除(delete)」を説明します。 ※環境:Android Studio Narwhal | 2025.1.1 Patch 1 ...
「外部ストレージ_プライマリ」に保存されるメディアデータは、データベースで管理されます。 Media Storeを使うと、このデータベースを通してメディアデータへアクセスできます。 データベース(SQLite)が持つ検索機能を使ってアクセス対象を絞り込めるので、とても便利です。 この記事は、「絞り込みアクセス」について、まとめます。 ※環境:Android Studio Narwhal | 2025.1.1 Patch 1 ...
メディアデータはMedia Storeを使ったアクセスが最適です。 その理由は、メディア特有の付加情報を使って、データを管理できるからです。 管理されたデータはブログラムから扱い易いです。また、ユーザの使い勝手(エクスペリエンス)も向上します。 バケットはメディアデータを管理する付加情報の一つです。 無くてもアクセスは可能ですが、積極的に取り入れた方が良いと思います。 今回は「ファイル名とバケットを指定したアクセス」について、まとめます。 「API≦28」と「API≧29」で動作が異なります。注意して下さい。 ※環境:Android Studio Narwhal Feature Drop | 2025.1.2 ...
メディアデータはMedia Storeを使ったアクセスが最適です。 その理由は、メディア特有の付加情報を使って、データを管理できるからです。 管理されたデータはブログラムから扱い易いです。また、ユーザの使い勝手(エクスペリエンス)も向上します。 バケットはメディアデータを管理する付加情報の一つです。 無くてもアクセスは可能ですが、積極的に取り入れた方が良いと思います。 今回は「ファイル名とバケットを指定したアクセス」について、まとめます。 「API≦28」と「API≧29」で動作が異なります。注意して下さい。 ※環境:Android Studio Narwhal Feature Drop | 2025.1.2 ...
メディアデータはアプリ間で共有されるので、アプリがデータへアクセスするには、アクセス許可が必要です。 この許可の権限の範囲は、プライバシー保護の観点から、徐々に狭められてきました。 そして、対象範囲別ストレージにおいて、他アプリが所有するファイルへの書き込みは、URI(ファイル)毎の許可が必要になっています。 許可の取得は、ユーザと対話をする形式(ダイアログ)で行われます。手順が少し複雑です。 ここに「他アプリが所有するファイルへ書き込み」する方法を、まとめます。 ※環境:Android Studio Narwhal Feature Drop | 2025.1.2 Patch 1 ...
スポンサーリンク