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
関連
-
android.os の NetworkOnMainThreadException。
-
Android Studio を 3.6.3 にアップデートした後、構成 :classpath のアーティファクトをすべて解決できない。
-
プログラム "git.exe "を実行できない場合の正しい解決方法です。CreateProcessエラー=2
-
ジャークとして。起動アクティビティを特定できませんでした。デフォルトのアクティビティが見つかりません アクティビティ起動中のエラー
-
エラーが発生しました。ArrayAdapter は、リソース ID が TextView である必要があります。
-
Android開発で「Attempt to invoke virtual method 'XXX()' on null object reference」というヌルポインター例外に遭遇する。
-
android studioが "The activity must be exported or contain an intent-filter" と表示され実行される。
-
エラー:未宣言の識別子(AS)の使用
-
Android Get set image.setImageResource(R.drawable.xxx) リソース
-
StrictMode$AndroidBlockGuardPolicy.onNetwork は android.os の下でエラーになります。
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
Androidのadbデバイスがオフラインであることが判明
-
java.lang.NullPointerException: NULLオブジェクト参照で仮想メソッド......を呼び出そうとしました。
-
aapt2エラー:ログを確認する(具体的な原因の探り方)
-
gitlab 設定エラー。リモートリポジトリから読み込めなかったか、ホストキーの検証に失敗しました。
-
AndroidStudio reports Could not resolve all artifacts for configuration ':app:classpath'.
-
最新のandroidプロジェクトディレクトリにあるarmeabi-v7aとarmeabiの具体的な意味とその違いを教えてください。
-
android block certificate validation CertPathValidatorException: 認証パスのトラストアンカーが見つかりません
-
Android ProgressBarの色を変更する
-
Android ProgressBarのスタイルカラーを変更する
-
AndroidサポートデザインライブラリのFloatingActionButtonについて