FileUriExposedException とは
このエラーが発生する原因は下記です。
Android N (API 24+) ではアプリ間のファイル共有に大きな変更があり、
file://
を使った Intent によるファイル共有ができなくなりました。
具体的には、Android N 向けアプリのプライベートディレクトリのパーミッションが 0700 になりました。ファイルの所有者であっても、このパーミッションを緩和することはできません。
よって、Android N 以降のアプリでは、file://
を含む Intent がアプリから外部アプリに発行されると FileUriExposedException が発生します。
Android N での file:// スキーマによるファイル共有の挙動より抜粋
対処方法
手順1
まずは、ファイル共有用のxmlファイルを作成します。(res/xml/provider_paths.xml
)
このファイルがあることで何が起こるのかなど、意味が実はよくわかってないので知ってる方いましたら、教えてください〜
1 2 3 4 5 |
<?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <external-path name="external_files" path="."/> </paths> |
手順2
続いて AndroidManifest.xml
にプロバイダーの記述を追加します。この中で先ほど作成したxmlを指定します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<manifest ...> <application ...> <activity .../> <provider android:name="android.support.v4.content.FileProvider" android:authorities="${applicationId}.provider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/provider_paths"/> </provider> </application> </manifest> |
手順3
最後に、Uriの取得方法を下記のように変更して、Intent.FLAG_GRANT_READ_URI_PERMISSION
を追加するとエラーが解消されるはずです。
1 2 3 4 5 6 7 8 |
Uri apkURI = FileProvider.getUriForFile(this, getApplicationContext().getPackageName() + ".provider", file); String mimeType = getMimeType(file);//*1 Intent intent = new Intent(); intent.setAction(Intent.ACTION_VIEW); intent.setDataAndType(apkURI, mimeType); intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); startActivity(intent); |
*1… getMimeType(file)
について、MimeTypeの取得方法はこちらも参考にどうぞ