3

My application uses FileProvider to get a content URI for a file created in a subdirectory on the external storage and grant permissions to the selected camera application so it can save a photo to that file. It works like a charm on every device and emulator except one which I don't own - Huawei Honor 7 (I have a crash log from that device). I'm trying to understand the problem and find a way to fix it.

AndroidManifest.xml

<provider
    android:name="android.support.v4.content.FileProvider"
    android:authorities="<package>.fileprovider"
    android:exported="false"
    android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/file_provider_paths" />
</provider>

file_provider_paths.xml

<paths>
    <external-files-path name="external_storage" path="" />
</paths>

When I create an empty file to share with the camera application, I obtain the base external directory path using Context.getExternalFilesDir(null). It usually returns a path like this: /storage/emulated/0/Android/data/<package>/files

which is the same as these:

  • Context.getExternalFilesDirs(null)[0]
  • ContextCompat.getExternalFilesDirs(context, null)[0]

And I put the file a bit deeper, e.g. /storage/emulated/0/Android/data/<package>/files/247/images/ad4b7cd7-8917-43d5-8f6c-69555d76c0e0

Then I call FileProvider.getUriForFile(context, "<package>.fileprovider", file)

As I said, it works properly on everything I have, both emulators and devices, with APIs 19 to 25.


Now, there is that crash:

Caused by java.lang.IllegalArgumentException: Failed to find configured root that contains /storage/0123-4567/Android/data/<package>/files/42/images/51e4b571-67e4-4e7d-abb0-0ae921d339f4
       at android.support.v4.content.FileProvider$SimplePathStrategy.getUriForFile(FileProvider.java:711)
       at android.support.v4.content.FileProvider.getUriForFile(FileProvider.java:400)

I have found out that the current FileProvider implementation matches the external-files-path tag with this piece of code:

} else if (TAG_EXTERNAL_FILES.equals(tag)) {
    File[] externalFilesDirs = ContextCompat.getExternalFilesDirs(context, null);
    if (externalFilesDirs.length > 0) {
        target = externalFilesDirs[0];
    }
}

So my idea is that maybe Context.getExternalFilesDir(null) gives a different storage directory than ContextCompat.getExternalFilesDirs(context, null) at 0 index. If so, I would create a file on the storage which is not supported by the FileProvider.

I have also found some issue reported to Google regarding this limitation.

Do you think that's the real root cause or do you have any other ideas?

4

0 回答 0