FileProvider - IllegalArgumentException:未能找到配置的根

我试图用相机拍照,但我得到以下错误:

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.access$100(MainActivity.java:22)
at com.example.marek.myapplication.MainActivity$1.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,但我不知道这个错误消息试图告诉我什么。如果你想要更多信息/代码,请在评论中告诉我。

229183 次浏览

你的文件存储在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文件。

从本文档中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改成full path就可以了。

检查您的设备提供了多少存储空间—不支持从辅助存储空间共享文件。查看FileProvider.java source (from 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接口获取存储列表。请参阅文档了解其限制(例如,它被告知不能识别USB闪存)。最好的方法是自己对这个API的存储列表进行一些调试输出,这样你就可以检查存储的路径与传递给getUriForFile()的路径是否匹配。

谷歌的问题跟踪器中已经有票分配(截至06-2017年),要求支持多个存储。最后,我也找到了关于这个问题

我看到至少你没有在file_paths.xml中提供与其他人相同的路径。 所以请确保在3个地方提供完全相同的包名或路径,包括:

  • manifest中的android:authorities属性
  • file_paths.xml中的path属性
  • 当调用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 7.1, 8.0+。将它们更新为v25.4.0.2 +,这个特定的错误可能就会消失(因为你已经正确配置了你的file_path文件,就像其他人说的那样)。


给出上下文:我从a中的牛轧糖切换到瞄准奥利奥 Xamarin的。形式应用程序,并与Xam.Plugin.Media拍照 开始失败,出现上述错误消息,因此更新包

我做了什么来解决这个问题

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>

fileppaths .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类-

Uri fileProvider = FileProvider.getUriForFile(getContext(),"com.mydomain.fileprovider",newFile);

在启用口味(dev, stage)后出现类似的问题。

在口味之前,我的路径资源是这样的:

<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path
name="my_images"
path="Android/data/pl.myapp/files/Pictures" />
</paths>

After added 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>

但是为了让它在最新的android中工作,在路径的末尾应该有一个“/”,就像这样:

<?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>

这些对我都没用。唯一可行的方法是不要在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 < / p >

xml file_paths文件中的以下更改对我有用。

 <external-files-path name="my_images" path="Pictures"/>
<external-files-path name="my_movies" path="Movies"/>

我可能会迟到,但我找到了解决办法。工作对我来说很好,我只是把路径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>

这对我也很管用。而不是给完整的路径,我给了path="Pictures",它工作得很好。

<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-files-path
name="images"
path="Pictures">
</external-files-path>
</paths>

我有同样的问题,我尝试了下面的代码为其工作。

1.创建Xmlfile: provider_paths

<?xml version="1.0" encoding="utf-8"?>
<paths>
<files-path name="my_images" path="myfile/"/>
</paths>

2. Mainfest文件

 <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.在你的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>

但是对于INTERNAL STORAGE,要小心路径,因为它使用getFilesDir()方法 这意味着你的文件将位于应用程序的根目录("/")

  File storeDir = getFilesDir(); // path "/"

所以你的提供者文件必须是这样的:

<paths>
<files-path name="my_images" path="/" />
</paths>

请注意,external-path不是指向二级存储,即“可移动存储”(尽管名称为“external”)。如果你得到“未能找到配置的根”,你可以将这一行添加到你的XML文件中。

<root-path name="root" path="." />

在这里查看更多细节FileProvider和辅助外部存储

以上这些对我都没用, 经过几个小时的调试,我发现问题在createImageFile(),特别是absolute path vs 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中使用

下面是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();
}
}

你好,朋友,试试这个

在这段代码中

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

创建类MyFileProvider(只创建类,不声明任何方法)

当你使用文件提供程序时使用(.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日

我们应该只使用我们需要的特定路径。

有关更多信息,请参阅已接受的答案: https://stackoverflow.com/a/42516202/4498813

我的问题是,我在不同类型的文件路径中有重叠的名称,就像这样:

<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()注释了另一个子目录。< / p >

我要找的是

data/user/0/com.psh.mTest/app_imageDir/20181202101432629.png

Context.getFilesDir()
< p >返回 /data/user/0/com.psh.mTest/files < / p >

标签应该是

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的标签,然后很容易发现标签不匹配

事实证明,将提供者权限设置为${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>

花了两周时间试图找到一些解决方案…如果你在尝试了以上所有方法后到达这里:

1 - __abc0

<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 -不忘记验证相机是否在模拟器中激活。

< p > 我的问题是错误的文件名: 我在res/xml下创建file_paths.xml,而资源在Manifest中设置为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>

改变你的main/res/xml/provider_paths.xml

<paths>
<files-path path="images/" name="myimages" />
<external-path name="download" path="download/"/>
</paths>

<?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>