1. ホーム
  2. android

Android Nで報告されたエラーを解決する: android.os.FileUriExposedException: file:///storage/emulated/0/

2022-02-23 21:37:21
<パス

android Nのファイルアクセスクラッシュを解決する android.os.FileUriExposedException file:///storage/emulated/0/xxx

原因

Android Nではファイルへのアクセスを取りやめており、Android Nの通り、アプリ間でファイルを共有するには、content://URIを送信し、そのURIに一時的なアクセスを許可する必要があります。
そして、この認可を行う最も簡単な方法は、FileProvider クラスを使用することです。

解決策

1. メインフェスタにFileProviderの登録を追加する


 ......
     

2. Configure the filepaths file
where. 

The root directory represented by files-path: Context.getFilesDir()
The root directory represented by external-path: Environment.getExternalStorageDirectory()
The root directory represented by cache-path: getCacheDir() path represents the directory to be shared
name is just a label, take it as long as you can understand it
As an example : uri link obtained via provider content://com.honjane.providerdemo.fileprovider/files_path/files/b7d4b092822da.pdf The name corresponds to the files_path in the link path corresponds to the files in the link, but of course files are in the honjane/ directory 3. Accessing files /** * Open the file * Throws ActivityNotFoundException when there is no app in the phone that can open the file * @param context activity * @param file File * @param contentType File type e.g. text (text/html) */ public static void startActionFile(Context context, File file, String contentType) throws ActivityNotFoundException { if (context == null) { return; } Intent intent = new Intent(Intent.ACTION_VIEW); intent.addCategory(Intent.CATEGORY_DEFAULT); intent.setDataAndType(getUriForFile(context, file), contentType); if (! (context instanceof Activity)) { intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); } context.startActivity(intent); } /** * Turn on the camera * * @param activity Activity * @param file File * @param requestCode result requestCode */ public static void startActionCapture(Activity activity, File file, int requestCode) { if (activity == null) { return; } Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); intent.putExtra(MediaStore.EXTRA_OUTPUT, getUriForFile(activity, file)); activity.startActivityForResult(intent, requestCode); } private static Uri getUriForFile(Context context, File file) { if (context == null || file == null) { throw new NullPointerException(); } Uri uri; if (Build.VERSION.SDK_INT >= 24) { uri = FileProvider.getUriForFile(context.getApplicationContext(), "your application name.fileprovider", file); } else { uri = Uri.fromFile(file); } return uri; } The same access to the camera album is done via FileProvider.getUriForFile to request a temporary shared space
It has been written as a tool class and uploaded to github, you need to download it directly
Easy to use, one line of code to get it done
Open the file. try { FileUtils.startActionFile(this,path,mContentType); }catch (ActivityNotFoundException e){ } Calling the camera. FileUtils.startActionCapture(this, file, requestCode); Fixing bugs. java.lang.IllegalArgumentException: Failed to find configured root that contains /storage/emulated/0/xxx/xxx/file/12b31d2cab6ed.pdf external corresponds to storage/emulated/0/, which at first glance seems fine. path is set to the root path of external, which corresponds to Environment.getExternalStorageDirectory() However, this method only gets the path to the internal SD card, so when the image in the selected album is on an external SD card, the image address is not found, so it throws a failed to find configured root that contains error. By analyzing the FileProvider source code, we found that after the xml is parsed to the corresponding tag, the buildPath() method is executed to use the path corresponding to the root tag (files-path, cache-path, external-path, etc.) as the root path to the file. In buildPath(), there are some constants to determine which directory path to build, in addition to the paths described above there is a TAG_ROOT_PATH = "root-path" which will only build other paths if they are not root-path. The root-path is not officially described, but after testing it, we found that it corresponds to the root path of the entire storage pointed to by DEVICE_ROOT, so this bug is fixed Modifying the filepaths file. Code download. https://github.com/honjane/fileProviderDemo
where.
The root directory represented by files-path: Context.getFilesDir()
The root directory represented by external-path: Environment.getExternalStorageDirectory()
The root directory represented by cache-path: getCacheDir() path represents the directory to be shared
name is just a label, take it as long as you can understand it
As an example : uri link obtained via provider content://com.honjane.providerdemo.fileprovider/files_path/files/b7d4b092822da.pdf The name corresponds to the files_path in the link path corresponds to the files in the link, but of course files are in the honjane/ directory 3. Accessing files /** * Open the file * Throws ActivityNotFoundException when there is no app in the phone that can open the file * @param context activity * @param file File * @param contentType File type e.g. text (text/html) */ public static void startActionFile(Context context, File file, String contentType) throws ActivityNotFoundException { if (context == null) { return; } Intent intent = new Intent(Intent.ACTION_VIEW); intent.addCategory(Intent.CATEGORY_DEFAULT); intent.setDataAndType(getUriForFile(context, file), contentType); if (! (context instanceof Activity)) { intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); } context.startActivity(intent); } /** * Turn on the camera * * @param activity Activity * @param file File * @param requestCode result requestCode */ public static void startActionCapture(Activity activity, File file, int requestCode) { if (activity == null) { return; } Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); intent.putExtra(MediaStore.EXTRA_OUTPUT, getUriForFile(activity, file)); activity.startActivityForResult(intent, requestCode); } private static Uri getUriForFile(Context context, File file) { if (context == null || file == null) { throw new NullPointerException(); } Uri uri; if (Build.VERSION.SDK_INT >= 24) { uri = FileProvider.getUriForFile(context.getApplicationContext(), "your application name.fileprovider", file); } else { uri = Uri.fromFile(file); } return uri; } The same access to the camera album is done via FileProvider.getUriForFile to request a temporary shared space
It has been written as a tool class and uploaded to github, you need to download it directly
Easy to use, one line of code to get it done
Open the file. try { FileUtils.startActionFile(this,path,mContentType); }catch (ActivityNotFoundException e){ } Calling the camera. FileUtils.startActionCapture(this, file, requestCode); Fixing bugs. java.lang.IllegalArgumentException: Failed to find configured root that contains /storage/emulated/0/xxx/xxx/file/12b31d2cab6ed.pdf external corresponds to storage/emulated/0/, which at first glance seems fine. path is set to the root path of external, which corresponds to Environment.getExternalStorageDirectory() However, this method only gets the path to the internal SD card, so when the image in the selected album is on an external SD card, the image address is not found, so it throws a failed to find configured root that contains error. By analyzing the FileProvider source code, we found that after the xml is parsed to the corresponding tag, the buildPath() method is executed to use the path corresponding to the root tag (files-path, cache-path, external-path, etc.) as the root path to the file. In buildPath(), there are some constants to determine which directory path to build, in addition to the paths described above there is a TAG_ROOT_PATH = "root-path" which will only build other paths if they are not root-path. The root-path is not officially described, but after testing it, we found that it corresponds to the root path of the entire storage pointed to by DEVICE_ROOT, so this bug is fixed Modifying the filepaths file. Code download. https://github.com/honjane/fileProviderDemo