FileProvider - IllegalArgumentException: Failed to

2020-01-23 15:19发布

I'm trying to take a picture with camera, but I'm getting the following error:

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>

I was searching whole day about this error and trying to understand FileProvider, but I have no idea what this error message tries to tell me. If you want more info/code, write me in the comment.

30条回答
贪生不怕死
2楼-- · 2020-01-23 15:54

This confusing me a bit too.

The problem is on "path" attribute in your xml file.

From this document FileProvider 'path' is a subdirectory, but in another document (camera/photobasics) shown 'path' is full 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>

I just change this 'path' to full path and it just work.

查看更多
爷的心禁止访问
3楼-- · 2020-01-23 15:54

The problem might not just be the path xml.

Following is my fix:

Looking into the root course in 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);
        }

        // ...
    }

This means mRoots should contains the tag of requested uri. So I write some code to print mRoots and tag of uri, and then easily find the tags do not match.

It comes out that setting provider authority as ${applicationID}.provider is a stupid idea! This authority is so common that might be used by other providers, which will mess up the path config!

查看更多
女痞
4楼-- · 2020-01-23 15:56

Check how many storages your device offers - sharing files from secondary storage is not supported. Look at 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];
                }
            }

So, they take only the first storage.

Also, you can see that getExternalCacheDirs() is used to obtain list of storages through the ContextCompat interface. See documentation for its limits (it's told to not recognize USB Flashes for example). Best is to make some debug output of list of storages from this API on your own, so that you can check that path to storage matches the path passed to getUriForFile().

There's already a 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 as well.

查看更多
一纸荒年 Trace。
5楼-- · 2020-01-23 15:56
  • For Xamarin.Android users

This could also be the result of not updating your support packages when targeting Android 7.1, 8.0+. Update them to v25.4.0.2+ and this particular error might go away(giving you´ve configured your file_path file correctly as others stated).


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.

查看更多
不美不萌又怎样
6楼-- · 2020-01-23 15:57

You need to change the xml file file_paths.xml from

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

to

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <fexeternal-path name="my_images" path="Android/data/com.example.marek.myapplication/files/Pictures"/>
</paths>
查看更多
爷的心禁止访问
7楼-- · 2020-01-23 15:59

Got similar problem after enabled flavors (dev, stage).

Before flavors my path resource looked like this:

<?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" in Manifest appId was pl.myapp.dev or pl.myapp.stage depends on flavor and app started crashing. I removed full path and replaced it with dot and everything started working.

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <external-path
        name="my_images"
        path="." />
</paths>
查看更多
登录 后发表回答