2020/03/07

Android Q で外部ストレージのファイルが開けなくなった

Android Pi (API Level 28) まで正しく動いていたアプリが、Android Q 上で動作させると動かなくなってしまいました。

具体的には、External Storage にファイルを書き込もうとすると、以下のような例外が発生してしまうのです。

`java.io.FileNotFoundException: /storage/emulated/0/202003061644.zip: open failed: EACCES (Permission denied)`

Android Pi までは動作していたので、当然 `WRITE_EXTERNAL_STORAGE` と `READ_EXTERNAL_STORAGE` パーミッションは適切に静的にも動的にも取得しています。



### Android Q から External Storage のアクセス権が厳しくなった
調べてみると、Android Q からは External Storage に直接アクセス出来るエリアが限定されたようです。
具体的には [getExternalFilesDir()](https://developer.android.com/reference/android/content/Context#getExternalFilesDir(java.lang.String)) で取得されるディレクトリ以外はパス指定で読み書き出来ませんその代わり、パーミッションは必要なくなった。

> 参考
>
> [Exception 'open failed: EACCES (Permission denied)' on Android - Stack Overflow](https://stackoverflow.com/questions/8854359/exception-open-failed-eacces-permission-denied-on-android)
>
> [対象範囲別外部ストレージ アクセスを管理する  |  Android デベロッパー  |  Android Developers](https://developer.android.com/training/data-storage/files/external-scoped)

### 解決策(暫定)
以下のフラグを `AndroidManifest.xml" に書いておくと、API 28 までと同等のアクセス権に変わるとのこと。

```xml
`title: "AndroidManifest.xml";
<application
    android:requestLegacyExternalStorage="true"
```

しかし、これは暫定対応です。
来年(2020年)以降リリースのバージョンではこのフラグは動かないらしいです。

### 解決策
そもそも External Storage を使わないか、`getExternalFilesDir()`を使うようにするしかないと思われます。

なお、Media 系と Download ディレクトリは別途アクセスする方法が提供されています。

詳しくは上記、公式サイトをご参考ください。

0 件のコメント: