FileProvider - IllegalArgumentException:找不到已配置的根目录
FileProvider - IllegalArgumentException: Failed to find configured root
我正在尝试用相机拍照,但出现以下错误:
FATAL EXCEPTION: main
Process: com.example.marek.myapplication, PID: 6747
java.lang.IllegalArgumentException: Failed to find configured root that contains /storage/emulated/0/Android/data/com.example.marek.myapplication/files/Pictures/JPEG_20170228_175633_470124220.jpg
at android.support.v4.content.FileProvider$SimplePathStrategy.getUriForFile(FileProvider.java:711)
at android.support.v4.content.FileProvider.getUriForFile(FileProvider.java:400)
at com.example.marek.myapplication.MainActivity.dispatchTakePictureIntent(MainActivity.java:56)
at com.example.marek.myapplication.MainActivity.access0(MainActivity.java:22)
at com.example.marek.myapplication.MainActivity.onClick(MainActivity.java:35)
AndroidManifest.xml:
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.example.marek.myapplication.fileprovider"
android:enabled="true"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
Java:
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// Ensure that there's a camera activity to handle the intent
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
// Create the File where the photo should go
File photoFile = null;
try {
photoFile = createImageFile();
} catch (IOException ex) {
Toast.makeText(getApplicationContext(), "Error while saving picture.", Toast.LENGTH_LONG).show();
}
// Continue only if the File was successfully created
if (photoFile != null) {
Uri photoURI = FileProvider.getUriForFile(this,
"com.example.marek.myapplication.fileprovider",
photoFile);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
}
}
file_paths.xml
<?xml version="1.0" encoding="utf-8"?>
<paths>
<files-path name="my_images" path="images/"/>
</paths>
我整天都在搜索这个错误并试图理解 FileProvider
,但我不知道这个错误消息试图告诉我什么。如果你想要更多info/code,请在评论中写信给我。
您的文件存储在 getExternalFilesDir()
下。这映射到 <external-files-path>
,而不是 <files-path>
。此外,您的文件路径中不包含 images/
,因此 XML 中的 path
属性无效。
将 res/xml/file_paths.xml
替换为:
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-files-path name="my_images" path="/" />
</paths>
2020 年 3 月 13 日更新
特定路径的提供程序路径如下:
<files-path/>
--> Context.getFilesDir()
<cache-path/>
--> Context.getCacheDir()
<external-path/>
--> Environment.getExternalStorageDirectory()
<external-files-path/>
--> Context.getExternalFilesDir(String)
<external-cache-path/>
--> Context.getExternalCacheDir()
<external-media-path/>
--> Context.getExternalMediaDirs()
参考:https://developer.android.com/reference/androidx/core/content/FileProvider
这也让我有点困惑。
问题出在您的 xml 文件中的 "path" 属性上。
来自这份文件FileProvider
'path' 是一个子目录,
但在另一份文件 (camera/photobasics) 中显示
'path' 是完整路径。
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="my_images" path="Android/data/com.example.package.name/files/Pictures" />
</paths>
我只是将此 'path' 更改为完整路径,它就可以正常工作。
检查您的设备提供的存储空间数量 - 不支持从辅助存储空间共享文件。查看 FileProvider.java
来源(来自 support-core-utils 25.3.1):
} else if (TAG_EXTERNAL_FILES.equals(tag)) {
File[] externalFilesDirs = ContextCompat.getExternalFilesDirs(context, null);
if (externalFilesDirs.length > 0) {
target = externalFilesDirs[0];
}
} else if (TAG_EXTERNAL_CACHE.equals(tag)) {
File[] externalCacheDirs = ContextCompat.getExternalCacheDirs(context);
if (externalCacheDirs.length > 0) {
target = externalCacheDirs[0];
}
}
因此,他们只占用第一个存储空间。
另外可以看到getExternalCacheDirs()
是通过ContextCompat
接口获取存储列表的。请参阅 documentation 了解其限制(例如,它被告知不能识别 USB 闪存)。最好是自己从这个 API 生成一些存储列表的调试输出,这样你就可以检查存储路径是否与传递给 getUriForFile()
.
的路径匹配
已经有一个 ticket assigned (as for 06-2017) in Google's issue tracker, asking to support more than one storage. Eventually, I found SO question on this。
我看到至少您没有提供与 file_paths.xml 中其他人相同的路径。
所以请确保您在 3 个地方提供完全相同的包名称或路径,包括:
android:authorities
清单中的属性
path
file_paths.xml 中的属性
调用 FileProvider.getUriForFile() 时的 authority
参数。
试试这个
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path
name="my_images"
path="" />
</paths>
如果您正在使用内部缓存,则使用。
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<cache-path name="cache" path="/" />
</paths>
- Xamarin.Android 用户
这也可能是因为在针对 Android 7.1、8.0+ 时未更新您的支持包。将它们更新为 v25.4.0.2+ 并且此特定错误可能会消失(假设您已经按照其他人的说明正确配置了 file_path 文件)。
Giving context: I switched to targeting Oreo from Nougat in a
Xamarin.Forms app and taking a picture with the Xam.Plugin.Media
started failing with the above error message, so updating the packages
did the trick for me ok.
我做了什么来解决这个问题 -
AndroidManifest.xml
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.mydomain.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/filepaths"/>
</provider>
filepaths.xml(允许 FileProvider 共享应用程序外部文件目录中的所有文件)
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-files-path name="files"
path="/" />
</paths>
并在 java class -
Uri fileProvider = FileProvider.getUriForFile(getContext(),"com.mydomain.fileprovider",newFile);
启用 flavors (dev, stage) 后出现类似问题。
在添加风味之前,我的路径资源如下所示:
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path
name="my_images"
path="Android/data/pl.myapp/files/Pictures" />
</paths>
添加后android:authorities="${applicationId}.fileprovider"
在 Manifest 中 appId 是 pl.myapp.dev 或 pl.myapp.stage 取决于风格和应用程序开始崩溃。
我删除了完整路径并将其替换为点,一切都开始工作了。
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path
name="my_images"
path="." />
</paths>
Android官方文档说file_paths.xml应该有:
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="my_images"
path="Android/data/com.example.package.name/files/Pictures" />
</paths>
But to make it work in the latest android there should be a "/" at the end of the path, like this:
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="my_images"
path="Android/data/com.example.package.name/files/Pictures/" />
</paths>
None 这对我有用。唯一可行的方法是不在 xml 中声明显式路径。所以这样做并开心:
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="my_images" path="." />
</paths>
这里也有关于这个问题的优秀教程:
https://www.youtube.com/watch?v=9ZxRTKvtfnY&t=613s
xml file_paths 文件中的以下更改对我有用。
<external-files-path name="my_images" path="Pictures"/>
<external-files-path name="my_movies" path="Movies"/>
我会迟到,但我找到了适合我的 it.Working 解决方案,我只是将路径 XML 文件更改为:
<?xml version="1.0" encoding="utf-8"?>
<paths>
<root-path name="root" path="." />
</paths>
我注意到有关 path.xml
文件的政策或行为在支持库 26 和 27 之间发生了变化。为了从相机捕获图片,我看到了以下变化:
对于 26,我不得不使用 <external-path>
和 path
参数中给出的完整路径。
对于 27,我不得不使用 <external-files-path>
并且只使用 path
参数中的子文件夹。
所以支持库 27 对我特别有用,因为 path.xml
文件是
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-files-path name="camera_image" path="Pictures/"/>
</paths>
这对我有用,因为 well.Instead 给出了完整路径我给了 path="Pictures" 并且工作正常。
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-files-path
name="images"
path="Pictures">
</external-files-path>
</paths>
I had the same problem, I tried the below code for its working.
1.Create Xml文件:provider_paths
<?xml version="1.0" encoding="utf-8"?>
<paths>
<files-path name="my_images" path="myfile/"/>
</paths>
2。清单文件
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.ril.learnet.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths"/>
</provider>
3.In 你的 Java 文件。
File file = new File(getActivity().getFilesDir(), "myfile");
if (!file.exists()) {
file.mkdirs();
}
String destPath = file.getPath() + File.separator + attachmentsListBean.getFileName();
file mfile = new File(destPath);
Uri path;
Intent intent = new Intent(Intent.ACTION_VIEW);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
{
path = FileProvider.getUriForFile(AppController.getInstance().getApplicationContext(), AppController.getInstance().getApplicationContext().getPackageName() + ".provider", mfile );
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
} else {
path = Uri.fromFile(mfile);
}
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setDataAndType(path, "image/*");
getActivity().startActivity(intent);
这取决于你想做什么样的存储,内部或外部
用于外部存储
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-files-path name="my_images" path="my_images" />
</paths>
但对于内部存储,请注意路径,因为它使用 getFilesDir() 方法
这意味着您的文件将位于应用程序的根目录中 ("/")
File storeDir = getFilesDir(); // path "/"
所以你的提供者文件必须是这样的:
<paths>
<files-path name="my_images" path="/" />
</paths>
请注意,外部路径并未指向您的辅助存储,即 "removable storage"(尽管名称为 "external")。如果您得到 "Failed to find configured root",您可以将此行添加到您的 XML 文件。
<root-path name="root" path="." />
在此处查看更多详细信息FileProvider and secondary external storage
none 以上对我有用,
经过几个小时的调试,我发现问题出在 createImageFile()
,特别是 absolute path
与 relative path
我假设你们正在使用官方 Android 拍照指南。 https://developer.android.com/training/camera/photobasics
private static File createImageFile(Context context) throws IOException {
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
File storageDir = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES);
File image = File.createTempFile(
imageFileName, /* prefix */
".jpg", /* suffix */
storageDir /* directory */
);
// Save a file: path for use with ACTION_VIEW intents
mCurrentPhotoPath = image.getAbsolutePath();
return image;
}
记下 storageDir
,这是创建文件的位置。所以为了得到这个文件的绝对路径,我干脆用image.getAbsolutePath()
,这个路径在onActivityResult
如果你需要拍照后的Bitmap图片
下面是file_path.xml
,直接用.
这样就用绝对路径了
<paths>
<external-path
name="my_images"
path="." />
</paths>
如果拍照后需要位图
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Bitmap bmp = null;
try {
bmp = BitmapFactory.decodeFile(mCurrentPhotoPath);
} catch (Exception e) {
e.printStackTrace();
}
}
你好朋友试试这个
In this Code
1) 如何在清单中声明 2 个文件提供程序。
2) 文件下载的第一个提供商
3) 用于相机和图库的第二个提供程序
第 1 步
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths" />
</provider>
Provider_paths.xml
<?xml version="1.0" encoding="utf-8"?>
<paths>
<files-path name="apks" path="." />
</paths>
第二供应商
<provider
android:name=".Utils.MyFileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true"
tools:replace="android:authorities"
tools:ignore="InnerclassSeparator">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_path" />
</provider>
file_path.xml
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path name="storage/emulated/0" path="."/>
</paths>
.Utils.MyFileProvider
Create Class MyFileProvider(仅创建 class 无任何方法声明)
当你使用 File Provider 时使用了 (.fileprovider) 这个名称,而你用于图像 (.provider) 时使用了这个名称。
如果有任何问题无法理解此代码,您可以联系 rp1741995@gmail.com 我会帮助您。
如果没有任何帮助并且您遇到错误
failed to find configured root that contains /data/data/...
然后尝试更改某些行,例如:
File directory = thisActivity.getDir("images", Context.MODE_PRIVATE);
至:
File directory = new File(thisActivity.getFilesDir(), "images");
并在 xml 文件中:
<files-path name="files" path="." />
这很奇怪,因为我访问的文件夹是 /images
。
这可能会解决每个人的问题:
添加了所有标签,因此您无需担心文件夹路径。
将 res/xml/file_paths.xml 替换为:
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path
name="external"
path="." />
<external-files-path
name="external_files"
path="." />
<cache-path
name="cache"
path="." />
<external-cache-path
name="external_cache"
path="." />
<files-path
name="files"
path="." />
</paths>
编辑:2021 年 6 月 1 日
我们应该只使用我们需要的特定路径。
自己尝试备用路径并使用您需要的路径。
有关详细信息,请参阅已接受的答案:
我的问题是我在不同类型的文件路径中有重叠的名称,如下所示:
<cache-path
name="cached_files"
path="." />
<external-cache-path
name="cached_files"
path="." />
在我将名称 ("cached_files") 更改为唯一后,我摆脱了错误。我的猜测是这些路径存储在一些 HashMap 或不允许重复的东西中。
我为此花了 5 个小时..
我已经尝试了以上所有方法,但这取决于您的应用程序当前使用的存储空间。
https://developer.android.com/reference/android/support/v4/content/FileProvider#GetUri
尝试代码之前先查看文档。
以我为例
因为 files-path
子目录将是 Context.getFilesDir()
。
奇怪的是它 Context.getFilesDir()
注释了另一个子目录。
我要找的是
data/user/0/com.psh.mTest/app_imageDir/20181202101432629.png
Context.getFilesDir()
returns
/data/user/0/com.psh.mTest/files
所以标签应该是
.....files-path name="app_imageDir" path="../app_imageDir/" ......
那就成功了!!
问题可能不仅仅是路径 xml。
以下是我的修复:
查看 android.support.v4.content.FileProvider$SimplePathStrategy.getUriForFile()
中的根课程:
public File getFileForUri(Uri uri) {
String path = uri.getEncodedPath();
final int splitIndex = path.indexOf('/', 1);
final String tag = Uri.decode(path.substring(1, splitIndex));
path = Uri.decode(path.substring(splitIndex + 1));
final File root = mRoots.get(tag); // mRoots is parsed from path xml
if (root == null) {
throw new IllegalArgumentException("Unable to find configured root for " + uri);
}
// ...
}
这意味着 mRoots
应该包含请求的 uri 的标记。 所以我写了一些代码来打印mRoots
和uri的标签,然后很容易发现标签不匹配。
原来把provider权限设为${applicationID}.provider
是个蠢主意!这个权限很常见,可能被其他提供者使用,这会弄乱路径配置!
我遇到了这个错误 Failed to find configured root that contains...
以下解决方法解决了我的问题
res/xml/file_paths.xml
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="media" path="." />
</paths>
AndroidManifest.xml
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="[PACKAGE_NAME]"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths">
</meta-data>
</provider>
ActivityClass.java
void shareImage() {
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("image/*");
intent.putExtra(Intent.EXTRA_STREAM, FileProvider.getUriForFile(this,"com.slappstudio.pencilsketchphotomaker", selectedFilePath));
startActivity(Intent.createChooser(intent,getString(R.string.string_share_with)));
}
您需要将 xml 文件从
更改为 file_paths.xml
<?xml version="1.0" encoding="utf-8"?>
<paths>
<files-path name="my_images" path="images/"/>
</paths>
至
<?xml version="1.0" encoding="utf-8"?>
<paths>
<exeternal-path name="my_images" path="Android/data/com.example.marek.myapplication/files/Pictures"/>
</paths>
我确定我迟到了,但下面对我有用。
<paths>
<root-path name="root" path="." />
</paths>
花了 2 周时间寻找解决方案...如果您在尝试以上所有操作后到达这里:
1 - 验证您的标签提供商是否在标签应用程序内
<application>
<provider android:name="android.support.v4.content.FileProvider" android:authorities="com.companyname.Pocidadao.fileprovider" android:exported="false" android:grantUriPermissions="true">
<meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths"></meta-data>
</provider>
</application>
2 - 如果你尝试了很多路径都没有成功,那么用这个测试:
<?xml version="1.0" encoding="utf-8"?>
<paths>
<cache-path name="cache" path="." />
<external-path name="external" path="." />
<root-path name="root" path="." />
<files-path name="my_images" path="/" />
<files-path name="my_images" path="myfile/"/>
<files-path name="files" path="." />
<external-path name="external_files" path="." />
<external-path name="images" path="Pictures" />
<external-path name="my_images" path="." />
<external-path name="my_images" path="Android/data/com.companyname.yourproject/files/Pictures" />
<external-path name="my_images" path="Android/data/com.companyname.yourproject/files/Pictures/" />
<external-files-path name="images" path="Pictures"/>
<external-files-path name="camera_image" path="Pictures/"/>
<external-files-path name="external_files" path="." />
<external-files-path name="my_images" path="my_images" />
<external-cache-path name="external_cache" path="." />
</paths>
测试这个,如果相机工作,然后开始消除一些线条并继续测试...
3 - 不要忘记验证相机是否在您的模拟器中处于活动状态。
我的问题是错误的文件名:
我在 res/xml 下创建 file_paths.xml
,而清单中的资源设置为 provider_paths.xml
:
<provider
android:authorities="ir.aghigh.radio.fileprovider"
android:name="android.support.v4.content.FileProvider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths"/>
</provider>
我将 provider_paths
更改为 file_paths
,问题已解决。
您需要确保 file_paths.xml 文件的内容包含此字符串 => "/Android/data/com.example.marek.myapplication/files/Pictures/"
从报错信息来看,就是你的图片存放路径。查看预期示例
files_path.xml 下面:
<external-path name="qit_images" path="Android/data/com.example.marek.myapplication/files/Pictures/" />
如果您的文件路径类似于 /storage/emulated/0/"yourfile"
您只需要修改您的 FileProvider xml
<paths>
<external-path name="external" path="." />
</paths>
然后需要分享文件的时候再调用这个函数
Intent sharingIntent = new Intent(Intent.ACTION_SEND);
Uri fileUri = FileProvider.getUriForFile(getContext(),
"com.example.myapp.fileprovider",
file);
sharingIntent.setType("*/*"); // any flie type
sharingIntent.putExtra(Intent.EXTRA_STREAM, fileUri);
startActivity(Intent.createChooser(sharingIntent, "Share file"));
适用于 android M ~ Pie
@CommonsWare 的回答很棒。
但就我而言,我必须添加多个路径。
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path name="external_files" path="." />
<files-path name="external_files" path="." />
</paths>
我正在尝试用相机拍照,但出现以下错误:
FATAL EXCEPTION: main
Process: com.example.marek.myapplication, PID: 6747
java.lang.IllegalArgumentException: Failed to find configured root that contains /storage/emulated/0/Android/data/com.example.marek.myapplication/files/Pictures/JPEG_20170228_175633_470124220.jpg
at android.support.v4.content.FileProvider$SimplePathStrategy.getUriForFile(FileProvider.java:711)
at android.support.v4.content.FileProvider.getUriForFile(FileProvider.java:400)
at com.example.marek.myapplication.MainActivity.dispatchTakePictureIntent(MainActivity.java:56)
at com.example.marek.myapplication.MainActivity.access0(MainActivity.java:22)
at com.example.marek.myapplication.MainActivity.onClick(MainActivity.java:35)
AndroidManifest.xml:
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.example.marek.myapplication.fileprovider"
android:enabled="true"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
Java:
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// Ensure that there's a camera activity to handle the intent
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
// Create the File where the photo should go
File photoFile = null;
try {
photoFile = createImageFile();
} catch (IOException ex) {
Toast.makeText(getApplicationContext(), "Error while saving picture.", Toast.LENGTH_LONG).show();
}
// Continue only if the File was successfully created
if (photoFile != null) {
Uri photoURI = FileProvider.getUriForFile(this,
"com.example.marek.myapplication.fileprovider",
photoFile);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
}
}
file_paths.xml
<?xml version="1.0" encoding="utf-8"?>
<paths>
<files-path name="my_images" path="images/"/>
</paths>
我整天都在搜索这个错误并试图理解 FileProvider
,但我不知道这个错误消息试图告诉我什么。如果你想要更多info/code,请在评论中写信给我。
您的文件存储在 getExternalFilesDir()
下。这映射到 <external-files-path>
,而不是 <files-path>
。此外,您的文件路径中不包含 images/
,因此 XML 中的 path
属性无效。
将 res/xml/file_paths.xml
替换为:
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-files-path name="my_images" path="/" />
</paths>
2020 年 3 月 13 日更新
特定路径的提供程序路径如下:
<files-path/>
-->Context.getFilesDir()
<cache-path/>
-->Context.getCacheDir()
<external-path/>
-->Environment.getExternalStorageDirectory()
<external-files-path/>
-->Context.getExternalFilesDir(String)
<external-cache-path/>
-->Context.getExternalCacheDir()
<external-media-path/>
-->Context.getExternalMediaDirs()
参考:https://developer.android.com/reference/androidx/core/content/FileProvider
这也让我有点困惑。
问题出在您的 xml 文件中的 "path" 属性上。
来自这份文件FileProvider 'path' 是一个子目录, 但在另一份文件 (camera/photobasics) 中显示 'path' 是完整路径。
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="my_images" path="Android/data/com.example.package.name/files/Pictures" />
</paths>
我只是将此 'path' 更改为完整路径,它就可以正常工作。
检查您的设备提供的存储空间数量 - 不支持从辅助存储空间共享文件。查看 FileProvider.java
来源(来自 support-core-utils 25.3.1):
} else if (TAG_EXTERNAL_FILES.equals(tag)) {
File[] externalFilesDirs = ContextCompat.getExternalFilesDirs(context, null);
if (externalFilesDirs.length > 0) {
target = externalFilesDirs[0];
}
} else if (TAG_EXTERNAL_CACHE.equals(tag)) {
File[] externalCacheDirs = ContextCompat.getExternalCacheDirs(context);
if (externalCacheDirs.length > 0) {
target = externalCacheDirs[0];
}
}
因此,他们只占用第一个存储空间。
另外可以看到getExternalCacheDirs()
是通过ContextCompat
接口获取存储列表的。请参阅 documentation 了解其限制(例如,它被告知不能识别 USB 闪存)。最好是自己从这个 API 生成一些存储列表的调试输出,这样你就可以检查存储路径是否与传递给 getUriForFile()
.
已经有一个 ticket assigned (as for 06-2017) in Google's issue tracker, asking to support more than one storage. Eventually, I found SO question on this。
我看到至少您没有提供与 file_paths.xml 中其他人相同的路径。 所以请确保您在 3 个地方提供完全相同的包名称或路径,包括:
android:authorities
清单中的属性path
file_paths.xml 中的属性
调用 FileProvider.getUriForFile() 时的 authority
参数。
试试这个
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path
name="my_images"
path="" />
</paths>
如果您正在使用内部缓存,则使用。
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<cache-path name="cache" path="/" />
</paths>
- Xamarin.Android 用户
这也可能是因为在针对 Android 7.1、8.0+ 时未更新您的支持包。将它们更新为 v25.4.0.2+ 并且此特定错误可能会消失(假设您已经按照其他人的说明正确配置了 file_path 文件)。
Giving context: I switched to targeting Oreo from Nougat in a Xamarin.Forms app and taking a picture with the Xam.Plugin.Media started failing with the above error message, so updating the packages did the trick for me ok.
我做了什么来解决这个问题 -
AndroidManifest.xml
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.mydomain.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/filepaths"/>
</provider>
filepaths.xml(允许 FileProvider 共享应用程序外部文件目录中的所有文件)
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-files-path name="files"
path="/" />
</paths>
并在 java class -
Uri fileProvider = FileProvider.getUriForFile(getContext(),"com.mydomain.fileprovider",newFile);
启用 flavors (dev, stage) 后出现类似问题。
在添加风味之前,我的路径资源如下所示:
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path
name="my_images"
path="Android/data/pl.myapp/files/Pictures" />
</paths>
添加后android:authorities="${applicationId}.fileprovider" 在 Manifest 中 appId 是 pl.myapp.dev 或 pl.myapp.stage 取决于风格和应用程序开始崩溃。 我删除了完整路径并将其替换为点,一切都开始工作了。
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path
name="my_images"
path="." />
</paths>
Android官方文档说file_paths.xml应该有:
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="my_images"
path="Android/data/com.example.package.name/files/Pictures" />
</paths>
But to make it work in the latest android there should be a "/" at the end of the path, like this:
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="my_images"
path="Android/data/com.example.package.name/files/Pictures/" />
</paths>
None 这对我有用。唯一可行的方法是不在 xml 中声明显式路径。所以这样做并开心:
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="my_images" path="." />
</paths>
这里也有关于这个问题的优秀教程: https://www.youtube.com/watch?v=9ZxRTKvtfnY&t=613s
xml file_paths 文件中的以下更改对我有用。
<external-files-path name="my_images" path="Pictures"/>
<external-files-path name="my_movies" path="Movies"/>
我会迟到,但我找到了适合我的 it.Working 解决方案,我只是将路径 XML 文件更改为:
<?xml version="1.0" encoding="utf-8"?>
<paths>
<root-path name="root" path="." />
</paths>
我注意到有关 path.xml
文件的政策或行为在支持库 26 和 27 之间发生了变化。为了从相机捕获图片,我看到了以下变化:
对于 26,我不得不使用
<external-path>
和path
参数中给出的完整路径。对于 27,我不得不使用
<external-files-path>
并且只使用path
参数中的子文件夹。
所以支持库 27 对我特别有用,因为 path.xml
文件是
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-files-path name="camera_image" path="Pictures/"/>
</paths>
这对我有用,因为 well.Instead 给出了完整路径我给了 path="Pictures" 并且工作正常。
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-files-path
name="images"
path="Pictures">
</external-files-path>
</paths>
I had the same problem, I tried the below code for its working.
1.Create Xml文件:provider_paths
<?xml version="1.0" encoding="utf-8"?>
<paths>
<files-path name="my_images" path="myfile/"/>
</paths>
2。清单文件
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.ril.learnet.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths"/>
</provider>
3.In 你的 Java 文件。
File file = new File(getActivity().getFilesDir(), "myfile");
if (!file.exists()) {
file.mkdirs();
}
String destPath = file.getPath() + File.separator + attachmentsListBean.getFileName();
file mfile = new File(destPath);
Uri path;
Intent intent = new Intent(Intent.ACTION_VIEW);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
{
path = FileProvider.getUriForFile(AppController.getInstance().getApplicationContext(), AppController.getInstance().getApplicationContext().getPackageName() + ".provider", mfile );
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
} else {
path = Uri.fromFile(mfile);
}
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setDataAndType(path, "image/*");
getActivity().startActivity(intent);
这取决于你想做什么样的存储,内部或外部
用于外部存储
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-files-path name="my_images" path="my_images" />
</paths>
但对于内部存储,请注意路径,因为它使用 getFilesDir() 方法 这意味着您的文件将位于应用程序的根目录中 ("/")
File storeDir = getFilesDir(); // path "/"
所以你的提供者文件必须是这样的:
<paths>
<files-path name="my_images" path="/" />
</paths>
请注意,外部路径并未指向您的辅助存储,即 "removable storage"(尽管名称为 "external")。如果您得到 "Failed to find configured root",您可以将此行添加到您的 XML 文件。
<root-path name="root" path="." />
在此处查看更多详细信息FileProvider and secondary external storage
none 以上对我有用,
经过几个小时的调试,我发现问题出在 createImageFile()
,特别是 absolute path
与 relative path
我假设你们正在使用官方 Android 拍照指南。 https://developer.android.com/training/camera/photobasics
private static File createImageFile(Context context) throws IOException {
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
File storageDir = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES);
File image = File.createTempFile(
imageFileName, /* prefix */
".jpg", /* suffix */
storageDir /* directory */
);
// Save a file: path for use with ACTION_VIEW intents
mCurrentPhotoPath = image.getAbsolutePath();
return image;
}
记下 storageDir
,这是创建文件的位置。所以为了得到这个文件的绝对路径,我干脆用image.getAbsolutePath()
,这个路径在onActivityResult
如果你需要拍照后的Bitmap图片
下面是file_path.xml
,直接用.
这样就用绝对路径了
<paths>
<external-path
name="my_images"
path="." />
</paths>
如果拍照后需要位图
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Bitmap bmp = null;
try {
bmp = BitmapFactory.decodeFile(mCurrentPhotoPath);
} catch (Exception e) {
e.printStackTrace();
}
}
你好朋友试试这个
In this Code
1) 如何在清单中声明 2 个文件提供程序。
2) 文件下载的第一个提供商
3) 用于相机和图库的第二个提供程序
第 1 步
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths" />
</provider>
Provider_paths.xml
<?xml version="1.0" encoding="utf-8"?>
<paths>
<files-path name="apks" path="." />
</paths>
第二供应商
<provider
android:name=".Utils.MyFileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true"
tools:replace="android:authorities"
tools:ignore="InnerclassSeparator">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_path" />
</provider>
file_path.xml
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path name="storage/emulated/0" path="."/>
</paths>
.Utils.MyFileProvider
Create Class MyFileProvider(仅创建 class 无任何方法声明)
当你使用 File Provider 时使用了 (.fileprovider) 这个名称,而你用于图像 (.provider) 时使用了这个名称。
如果有任何问题无法理解此代码,您可以联系 rp1741995@gmail.com 我会帮助您。
如果没有任何帮助并且您遇到错误
failed to find configured root that contains /data/data/...
然后尝试更改某些行,例如:
File directory = thisActivity.getDir("images", Context.MODE_PRIVATE);
至:
File directory = new File(thisActivity.getFilesDir(), "images");
并在 xml 文件中:
<files-path name="files" path="." />
这很奇怪,因为我访问的文件夹是 /images
。
这可能会解决每个人的问题: 添加了所有标签,因此您无需担心文件夹路径。 将 res/xml/file_paths.xml 替换为:
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path
name="external"
path="." />
<external-files-path
name="external_files"
path="." />
<cache-path
name="cache"
path="." />
<external-cache-path
name="external_cache"
path="." />
<files-path
name="files"
path="." />
</paths>
编辑:2021 年 6 月 1 日
我们应该只使用我们需要的特定路径。 自己尝试备用路径并使用您需要的路径。
有关详细信息,请参阅已接受的答案:
我的问题是我在不同类型的文件路径中有重叠的名称,如下所示:
<cache-path
name="cached_files"
path="." />
<external-cache-path
name="cached_files"
path="." />
在我将名称 ("cached_files") 更改为唯一后,我摆脱了错误。我的猜测是这些路径存储在一些 HashMap 或不允许重复的东西中。
我为此花了 5 个小时..
我已经尝试了以上所有方法,但这取决于您的应用程序当前使用的存储空间。
https://developer.android.com/reference/android/support/v4/content/FileProvider#GetUri
尝试代码之前先查看文档。
以我为例
因为 files-path
子目录将是 Context.getFilesDir()
。
奇怪的是它 Context.getFilesDir()
注释了另一个子目录。
我要找的是
data/user/0/com.psh.mTest/app_imageDir/20181202101432629.png
Context.getFilesDir()
returns
/data/user/0/com.psh.mTest/files
所以标签应该是
.....files-path name="app_imageDir" path="../app_imageDir/" ......
那就成功了!!
问题可能不仅仅是路径 xml。
以下是我的修复:
查看 android.support.v4.content.FileProvider$SimplePathStrategy.getUriForFile()
中的根课程:
public File getFileForUri(Uri uri) {
String path = uri.getEncodedPath();
final int splitIndex = path.indexOf('/', 1);
final String tag = Uri.decode(path.substring(1, splitIndex));
path = Uri.decode(path.substring(splitIndex + 1));
final File root = mRoots.get(tag); // mRoots is parsed from path xml
if (root == null) {
throw new IllegalArgumentException("Unable to find configured root for " + uri);
}
// ...
}
这意味着 mRoots
应该包含请求的 uri 的标记。 所以我写了一些代码来打印mRoots
和uri的标签,然后很容易发现标签不匹配。
原来把provider权限设为${applicationID}.provider
是个蠢主意!这个权限很常见,可能被其他提供者使用,这会弄乱路径配置!
我遇到了这个错误 Failed to find configured root that contains...
以下解决方法解决了我的问题
res/xml/file_paths.xml
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="media" path="." />
</paths>
AndroidManifest.xml
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="[PACKAGE_NAME]"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths">
</meta-data>
</provider>
ActivityClass.java
void shareImage() {
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("image/*");
intent.putExtra(Intent.EXTRA_STREAM, FileProvider.getUriForFile(this,"com.slappstudio.pencilsketchphotomaker", selectedFilePath));
startActivity(Intent.createChooser(intent,getString(R.string.string_share_with)));
}
您需要将 xml 文件从
更改为 file_paths.xml<?xml version="1.0" encoding="utf-8"?>
<paths>
<files-path name="my_images" path="images/"/>
</paths>
至
<?xml version="1.0" encoding="utf-8"?>
<paths>
<exeternal-path name="my_images" path="Android/data/com.example.marek.myapplication/files/Pictures"/>
</paths>
我确定我迟到了,但下面对我有用。
<paths>
<root-path name="root" path="." />
</paths>
花了 2 周时间寻找解决方案...如果您在尝试以上所有操作后到达这里:
1 - 验证您的标签提供商是否在标签应用程序内
<application>
<provider android:name="android.support.v4.content.FileProvider" android:authorities="com.companyname.Pocidadao.fileprovider" android:exported="false" android:grantUriPermissions="true">
<meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths"></meta-data>
</provider>
</application>
2 - 如果你尝试了很多路径都没有成功,那么用这个测试:
<?xml version="1.0" encoding="utf-8"?>
<paths>
<cache-path name="cache" path="." />
<external-path name="external" path="." />
<root-path name="root" path="." />
<files-path name="my_images" path="/" />
<files-path name="my_images" path="myfile/"/>
<files-path name="files" path="." />
<external-path name="external_files" path="." />
<external-path name="images" path="Pictures" />
<external-path name="my_images" path="." />
<external-path name="my_images" path="Android/data/com.companyname.yourproject/files/Pictures" />
<external-path name="my_images" path="Android/data/com.companyname.yourproject/files/Pictures/" />
<external-files-path name="images" path="Pictures"/>
<external-files-path name="camera_image" path="Pictures/"/>
<external-files-path name="external_files" path="." />
<external-files-path name="my_images" path="my_images" />
<external-cache-path name="external_cache" path="." />
</paths>
测试这个,如果相机工作,然后开始消除一些线条并继续测试...
3 - 不要忘记验证相机是否在您的模拟器中处于活动状态。
我的问题是错误的文件名:
我在 res/xml 下创建 file_paths.xml
,而清单中的资源设置为 provider_paths.xml
:
<provider
android:authorities="ir.aghigh.radio.fileprovider"
android:name="android.support.v4.content.FileProvider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths"/>
</provider>
我将 provider_paths
更改为 file_paths
,问题已解决。
您需要确保 file_paths.xml 文件的内容包含此字符串 => "/Android/data/com.example.marek.myapplication/files/Pictures/"
从报错信息来看,就是你的图片存放路径。查看预期示例
files_path.xml 下面:
<external-path name="qit_images" path="Android/data/com.example.marek.myapplication/files/Pictures/" />
如果您的文件路径类似于 /storage/emulated/0/"yourfile"
您只需要修改您的 FileProvider xml
<paths>
<external-path name="external" path="." />
</paths>
然后需要分享文件的时候再调用这个函数
Intent sharingIntent = new Intent(Intent.ACTION_SEND);
Uri fileUri = FileProvider.getUriForFile(getContext(),
"com.example.myapp.fileprovider",
file);
sharingIntent.setType("*/*"); // any flie type
sharingIntent.putExtra(Intent.EXTRA_STREAM, fileUri);
startActivity(Intent.createChooser(sharingIntent, "Share file"));
适用于 android M ~ Pie
@CommonsWare 的回答很棒。
但就我而言,我必须添加多个路径。
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path name="external_files" path="." />
<files-path name="external_files" path="." />
</paths>