🗂️

Androidの全ファイルアクセス

2022/11/25に公開

Android でファイルマネージャなんかを作りたいときに役立つあれこれです。

はじめに:なるべくコンテンツプロバイダを使う

Android のファイルアクセスはFile API とUriとコンテンツプロバイダ使用する 2 通りに方法が存在しますが、セキュリティなどの観点から、基本的には後者を利用しましょう。例えばダウンロードフォルダにアクセスしたい時などはACTION_VIEWIntent を使いますがこれの返り値はcontent Uri になっています。これからなるべく FileAPI を使ってアクセスして欲しくない Google の意志が感じられます。。。

https://developer.android.com/guide/topics/providers/content-provider-basics?hl=ja

コンテンツプロバイダだとファイルマネージャは作れない

コンテンツプロバイダだとファイルの絶対パスが取得できないためファイルの階層構造を意識する必要があるファイルマネージャが作れません
ではそんな時にどう作ればいいのかというのが本記事の主旨です。

本題:全ファイルアクセスするためには

FileAPI を用いてもデフォルトではファイルにアクセスする権限がないためにエラーが発生してしまいます。
なので権限を取得したりするなど厄介ごとが複数あるので要注意です。

公式ドキュメント
https://developer.android.com/training/data-storage/manage-all-files?hl=ja

1. AndroidManifest で権限をリクエストする

AndroidManifest.xml で以下のように権限をリクエストします。ただしこれだけではまだ足りません

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