Androidの全ファイルアクセス
Androidでファイルマネージャなんかを作りたいときに役立つあれこれです。
はじめに:なるべくコンテンツプロバイダを使う
AndroidのファイルアクセスはFile
APIとUri
とコンテンツプロバイダ使用する2通りに方法が存在しますが、セキュリティなどの観点から、基本的には後者を利用しましょう。例えばダウンロードフォルダにアクセスしたい時などはACTION_VIEW
Intentを使いますがこれの返り値はcontent
Uriになっています。これからなるべくFileAPIを使ってアクセスして欲しくないGoogleの意志が感じられます。。。
コンテンツプロバイダだとファイルマネージャは作れない
コンテンツプロバイダだとファイルの絶対パスが取得できないためファイルの階層構造を意識する必要があるファイルマネージャが作れません。
ではそんな時にどう作ればいいのかというのが本記事の主旨です。
本題:全ファイルアクセスするためには
FileAPIを用いてもデフォルトではファイルにアクセスする権限がないためにエラーが発生してしまいます。
なので権限を取得したりするなど厄介ごとが複数あるので要注意です。
公式ドキュメント
1. AndroidManifestで権限をリクエストする
AndroidManifest.xmlで以下のように権限をリクエストします。ただしこれだけではまだ足りません。
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<!-- ↓↓↓ ここ ↓↓↓ -->
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
<application>
...
2. アプリで権限をリクエストする
全ファイルにアクセスするためには特別な権限が必要なのでSettings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION
インテントを使って取得します。
Composeだと次のようになります。
val context = LocalContext.current
Button(onClick = {
val intent = Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION)
context.startActivity(intent)
}){
Text("権限をリクエスト")
}
表示されたボタンをクリックすると全ファイルをアクセスするための権限を付与するための設定画面が表示され、ユーザが設定をオンにすることでファイルにアクセスすることができるようになっています。
これで全ファイルにアクセスする準備が整いました。
3. ルートディレクトリの取得の仕方に注意
File("/")
ではルートディレクトリにアクセスできません。Environment.getExternalStorageDirectory()
(戻り値はFile)を使用します。
val root = Environment.getExternalStorageDirectory()
val rootChildren = root.listFiles()
val rootName = root.name
...
Discussion