Android 10になってファイルが読めなくなった

私が作成したAndroid用のあるアプリにはデータのインポート及びエクスポートの機能が付いているのですが、その機能がAndroid 10になってうまく動かなくなってしまいました。
エクスポート機能(ファイル保存)については解決したのでインポート機能(ファイル読込)の修正を行っていこうと思います。

エクスポート機能の修正についてはこちらの記事をご覧ください。

関連記事

私が作成したAndroid用のあるアプリにはデータのインポート及びエクスポートの機能が付いています。 開発当時はAndroid 9が最新でそれに合わせた実装をしていて特に問題なく動いていました。 2022年1月、私がメインで使ってい[…]

インポート機能の不具合も「Environment.getExternalStorageDirectory」メソッドで取得したパスをファイルの読み込みに使えなくなったことが原因です。
そのメソッドを使わない形に改修します。

「Android 10におけるプライバシーに関する主な変更点」とそれの「対応策」は前述の記事をご覧ください。

サンプルソース(Kotlin)

インポート時(ファイル読込時)に読込ファイル名と読込先を設定する場合はこのような感じになります。
(パーミッション取得やチェックのロジックは割愛します)

fun onOverwriteButtonClick(view: View) {
	val intent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
		addCategory(Intent.CATEGORY_OPENABLE)
		type = "text/plain"
	}
	startActivityForResult(intent, resources.getInteger(R.integer.overwrite_import_request))
}

「インポート」ボタンをタップするとこのメソッドに入ってきてインポートするファイルの選択画面が開きます。

ファイルの選択画面

上記の画面でファイルが選択されると「onActivityResult」が呼び出されますのでoverrideしてファイルを読み込む処理を実装します。

override fun onActivityResult(requestCode: Int, resultCode: Int, resultData: Intent?) {
	// 上書きインポート処理
	if ((requestCode == resources.getInteger(R.integer.overwrite_import_request)) && (resultCode == Activity.RESULT_OK)) {
		if (resultData?.data != null) {
			val uri = resultData.data as Uri

			// これが指定されたファイルから読み込む処理
			dataImport(uri, true)
		}
	}

	return
}
private fun dataImport(uri: Uri) {
    val records = ArrayList()

    try {
        contentResolver.openInputStream(uri)?.use { inputStream ->
            BufferedReader(InputStreamReader(inputStream)).use { reader ->
                var record: String? = reader.readLine()
                while (record != null) {
                    records.add(record)
                    record = reader.readLine()
                }
            }
        }
    } catch (e: FileNotFoundException) {
        e.printStackTrace()
    } catch (e: IOException) {
        e.printStackTrace()
    }

    // 以下略

InputStreamにuriを渡して読み込みます。
Environment.getExternalStorageDirectoryメソッドを使っていたときはFileにファイルパスを渡していました。

recordsにファイルから読み込んだ内容が格納されています。
あとはそこから読み込んでDBなどに保存する流れになります。


まとめ

Environment.getExternalStorageDirectoryメソッドを使っていたときと比べるとファイル指定の自由度が上がったと思います。

この記事がAndroid 10になってファイルを読み込めなくなった方の参考になれば幸いです。