jiichan.com

PROGRAMMING

Kotlin
javascript
PHP
Java

jetpack compose 外部(共有)ストレージの Document ファイルへのアクセス

androidで、端末内にファイルを保存したり読み込んだりする方法がよく分からなかったので整理してみました。
特に、内部ストレージ、外部ストレージ、アプリ固有のストレージ、共有ストレージ、メディア用途、その他の用途、 と種類が多く分かりずらいです。
また、Api のバージョンで permission の要・不要も変わります。
何回かに分けてストレージへのアクセス方法を確認してみます。

≪開発環境≫
windows11
andriod studio koala
≪実機デバッグ≫
android13

ストレージの構成

google のサイトなど色々調べ、大まかに分けてみたのが次の表です。

区分1区分2区分3アクセス
内部ストレージアプリ固有のストレージ自分のみOK
外部ストレージアプリ固有のストレージ
Android11以降作成不可
自分のみOK
共有ストレージメディア用途他のアプリからもOK
メディア以外用途他のアプリからもOK

他のアプリで作られたファイル (LINEの画像など) にアクセスする以外は、パーミッションは不要のようです。

テキストファイルへの書き込み

書き込み 方法


val context = LocalContext.current
var str = ""

// Picker Create 用のインスタンスを準備(インスタンスをlaunchすることで Picker が使える)
val createDocLauncher =
	rememberLauncherForActivityResult(ActivityResultContracts.CreateDocument("text/plain")) { uri: Uri? ->
		if (uri == null) return@rememberLauncherForActivityResult
		// ファイルを作成する
		context.contentResolver.openOutputStream(uri)?.use { outputStream ->
			outputStream.bufferedWriter().use { bf ->
				bf.write("これはテストです")
			}
		}
	}

// 外部ストレージ(共有ストレージ)に書き込み(Document) Picker ===============
Button(
	onClick = {
		createDocLauncher.launch("sample.txt")   // 引数は作成するファイル名
	}
) {
	Text(text = "共有(Document)書き込み/Picker")
}

テキストファイルからの読み込み

読み込み 方法


val context = LocalContext.current
var str = ""

// Picker Open 用のインスタンスを準備(インスタンスをlaunchすることで Picker が使える)
val openDocLauncher =
	rememberLauncherForActivityResult(ActivityResultContracts.OpenDocument()) { uri: Uri? ->
		if (uri == null) return@rememberLauncherForActivityResult
		// その内容を読み取る
		context.contentResolver?.openInputStream(uri)?.use { inputStream ->
			inputStream.bufferedReader().forEachLine { line ->  // line単位で文字列を読み取る
				str += line + "\n"
			}
			viewModel.fileStrExSet(str)
		}
	}

// 外部ストレージ(共有ストレージ)から読み込み(Document) Picker ===============
Button(
	onClick = {
		openDocLauncher.launch(arrayOf("text/*"))    // 引数はファイルのMIMEタイプ
	}
) {
	Text(text = "共有(Document)読み込み/Picker")
}

まとめ

jetpack compose での Picker 使用方法がどうにか分かりました。
rememberLauncherForActivityResult と引数の ActivityResultContracts の種類で使い分けできるようです。