Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
536 views
in Technique[技术] by (71.8m points)

android - how to set FileProvider for file in External Cache dir

For file in Cache dir , I can add this in xml to set FileProvider

    <cache-path
    name="image"
    path="image/"/>

But if I storage file in External Cache Dir,I cannot get external-cache-path tag or something like that to set FileProvider.And

    <external-path
    name="image_external"
    path="cache/image/"/>

did not help ,too.

This is my Manifest file:

 <provider
        android:name="android.support.v4.content.FileProvider"
        android:authorities="com.tizi.quanzi"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/file_paths"/>
 </provider>

This is the xml/file_paths file:

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <cache-path
        name="image"
        path="image/"/>
    <external-path
        name="image_external"
        path="cache/image/"/>
</paths>

And this is my Code:

String RootPath = App.getApplication().getExternalCacheDir().getAbsolutePath();
String filePath = RootPath + "/image/" + fileName;
// done something there to save file
Intent shareIntent = new Intent();

Uri contentUri = FileProvider.getUriForFile(App.getApplication(),
        App.getApplication().getPackageName(), new File(filePath));
App.getApplication().grantUriPermission(App.getApplication().getPackageName(),
        contentUri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
shareIntent.setData(contentUri);
shareIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.putExtra(Intent.EXTRA_STREAM, contentUri);
shareIntent.setType("image/*");

activity.startActivity(Intent.createChooser(shareIntent, "share image"));

And this is the error infomation:

    /AndroidRuntime: FATAL EXCEPTION: main
Process: com.tizi.quanzi, PID: 27487
java.lang.IllegalArgumentException: Failed to find configured root that contains /storage/emulated/0/Android/data/com.tizi.quanzi/cache/image/o9xygODHtdP6HXqsuUZghVCsBKTtY4FJgO1MpnmX.jpg
    at android.support.v4.content.FileProvider$SimplePathStrategy.getUriForFile(FileProvider.java:678)
    at android.support.v4.content.FileProvider.getUriForFile(FileProvider.java:377)
    at com.tizi.quanzi.tool.ShareImage.shareImage(ShareImage.java:67)
    at com.tizi.quanzi.tool.ShareImage.shareImage(ShareImage.java:61)
    at com.tizi.quanzi.adapter.GalleryAdapter$2.onClick(GalleryAdapter.java:119)
    at android.support.v7.app.AlertController$AlertParams$3.onItemClick(AlertController.java:956)
    at android.widget.AdapterView.performItemClick(AdapterView.java:310)
    at android.widget.AbsListView.performItemClick(AbsListView.java:1145)
    at android.widget.AbsListView$PerformClick.run(AbsListView.java:3042)
    at android.widget.AbsListView$3.run(AbsListView.java:3879)
    at android.os.Handler.handleCallback(Handler.java:739)
    at android.os.Handler.dispatchMessage(Handler.java:95)
    at android.os.Looper.loop(Looper.java:148)
    at android.app.ActivityThread.main(ActivityThread.java:5417)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Update:
The way to go with the Support Library 24.2.0 and above is how @ashughes says in his answer.

On that version they added two new tags to the implementation of FileProvider.java to be able to reference the external files and cache directories.

private static final String TAG_EXTERNAL_FILES = "external-files-path";
private static final String TAG_EXTERNAL_CACHE = "external-cache-path";

If you want to dig more into it, you can take a look at the changes made on this commit.

Original answer:
I had the same problem. I took a look at the class FileProvider.java, and as you said, there is no tag for external cache dir, just the four below.

private static final String TAG_ROOT_PATH = "root-path";
private static final String TAG_FILES_PATH = "files-path";
private static final String TAG_CACHE_PATH = "cache-path";
private static final String TAG_EXTERNAL = "external-path";

What I do is to use the external-path tag. This tag will point to the root of the external directory not to the cache one. So you can either specify the rest of the path from there to the cache directory on path, or you can use a dot so it points to the root of the external directory.

   <external-path
    name="external_files"
    path="."/>

When you were using

<external-path
    name="image_external"
    path="cache/image/"/>

The method getFileForUri was checking if the path of the file starts with /storage/emulated/0/cache/image/ which it doesn't, because the path of your file is /storage/emulated/0/Android/data/com.tizi.quanzi/cache/image/. And that's the reason you are getting the exception.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...