FileProvider and secondary external storage

落爺英雄遲暮 提交于 2019-11-29 19:28:13

问题


How can I serve files from the SECONDARY external storage using the FileProvider?

The current implementation of the FileProvider handles only the first directory returned by ContextCompat.getExternalFilesDirs

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

It seems, that there is no way to define a <path> entry for the FileProvider, that matches the secondary external storage path...


回答1:


And the answer is... FileProvider does not support that. With Android 7 this is even more an issue, due to deprecation of the file:// Uri scheme.

I issued a bug report.




回答2:


FileProvider not support secondary storage because of the code below:

Code from support:support-core-utils:26.1.0 FileProvider

            } else if (TAG_EXTERNAL_FILES.equals(tag)) {
                File[] externalFilesDirs = ContextCompat.getExternalFilesDirs(context, null);
                if (externalFilesDirs.length > 0) {
                    target = externalFilesDirs[0];// Code here, That's why!!!
                }
            } else if (TAG_EXTERNAL_CACHE.equals(tag)) {

However, there is a special TAG in FileProvider : root-path which is not covered in official reference.

            if (TAG_ROOT_PATH.equals(tag)) {
                target = DEVICE_ROOT;// DEVICE_ROOT = new File("/");
            } else if (TAG_FILES_PATH.equals(tag)) {

So, root-path matches all the path.

Just type this code in your FileProvider xml, then FileProvider can handle File in secondary storage.

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

Be aware, it may leak your directory structure.




回答3:


To handle files located on external sdcards, I changed my provider_paths.xml to

<paths>
    <external-path path="." name="external_files" />
    <root-path path="." name="sdcard1" />

</paths>



回答4:


As workaround you can use absolute pathes:

<!-- secondary external storage with path /storage/extSdCard -->
<root-path path="/storage/extSdCard/Android/data/YOUR_PACKAGE/files/" name="extSdCard" />

<!-- secondary external storage with path /storage/sdcard1  -->
<root-path path="/storage/sdcard1/Android/data/YOUR_PACKAGE/files/" name="sdcard1" />



回答5:


So I ended up doing the following:

Try to create to Uri via FileProvider, If it fails due to:

java.lang.IllegalArgumentException: Failed to find configured root that contains

I'm just creating a regular Uri.

Here's my code:

try {
        uri = FileProvider.getUriForFile(context,
                MY_AUTHORITY_STRING,
                imageFile);
    } catch (Exception e) {
        CLog.d(TAG, e);
        uri = Uri.fromFile(imageFile);
    }

I don't know why, but it's working, the FileProvider can't access the file (As it's in secondary external storage) and then the uri is created successfully in the catch clause.

Weird Google...very weird.



来源:https://stackoverflow.com/questions/40318116/fileprovider-and-secondary-external-storage

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!