使用ACTION_VIEW在缓存目录中打开文件

use*_*004 9 android caching android-intent

我一直在寻找这个,但我无法让它正常工作.让我解释.

我有一个android应用程序,它将文件(图像,文档,...)保存在缓存目录中.起初我习惯于将getExternalCacheDir()方法保存在那里,但因为它应该缓存在没有SD卡的设备上,我必须使用getCacheDir().

当我习惯使用getExternalCacheDir()方法时,在另一个应用程序中打开这些文件是没有问题的,如下所示:

Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(file), mimetype);
Run Code Online (Sandbox Code Playgroud)

但是在使用时getCacheDir(),这些文件将保存在应用程序沙箱中,并且无法从应用程序外部访问.所以我用谷歌搜索了它,然后来了**ContentProvider.ContentProvider可以使用外部应用程序打开私有文件.但是当我尝试实现它时,它不起作用.

由于这篇文章,我尝试实现ContentProvider:如何使用Intent.ACTION_VIEW打开保存到内部存储的私有文件?但没有成功.

package com.myapplication.providers;

import java.io.File;
import java.io.FileNotFoundException;

import android.content.ContentProvider;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.os.ParcelFileDescriptor;

public class FileProvider extends ContentProvider {

    @Override
    public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
        File privateFile = new File(getContext().getCacheDir(), uri.getPath());
        return ParcelFileDescriptor.open(privateFile, ParcelFileDescriptor.MODE_READ_ONLY);
    }

    @Override
    public int delete(Uri arg0, String arg1, String[] arg2) {
        return 0;
    }

    @Override
    public String getType(Uri arg0) {
        return null;
    }

    @Override
    public Uri insert(Uri arg0, ContentValues arg1) {
        return null;
    }

    @Override
    public boolean onCreate() {
        return false;
    }

    @Override
    public Cursor query(Uri arg0, String[] arg1, String arg2, String[] arg3,
            String arg4) {
        return null;
    }

    @Override
    public int update(Uri arg0, ContentValues arg1, String arg2, String[] arg3) {
        return 0;
    }
}
Run Code Online (Sandbox Code Playgroud)

将此提供程序添加到应用程序清单

<provider
    android:name="com.myapplication.providers.FileProvider"
    android:authorities="com.myapplication"
    android:exported="true" />
Run Code Online (Sandbox Code Playgroud)

并使用此代码打开文件:

Uri uri = Uri.parse("content://com.myapplication/" + filename);

Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setDataAndType(uri, mimetype);
Run Code Online (Sandbox Code Playgroud)

提前致谢!

use*_*004 31

我发现我必须以不同的方式做事.

v4支持库提供了可以使用的FileProvider类,而不是创建我自己的ContentProvider.

AndroidManifest.xml

<application ...>

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

</application>
Run Code Online (Sandbox Code Playgroud)

FILE_PROVIDER_PATHS是一个xml文件,用于描述其他应用程序可以读取的文件.

所以我将一个file_paths.xml文件添加到res/xml文件夹中.

<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <cache-path name="my_cache" path="." />
</paths>
Run Code Online (Sandbox Code Playgroud)

然后你唯一要做的就是创建并启动显示文件的意图.

File file = new File(getCacheDir(), "test.pdf");

Uri uri = FileProvider.getUriForFile(context, "be.myapplication", file);

Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setDataAndType(uri, "application/pdf");

startActivity(intent);
Run Code Online (Sandbox Code Playgroud)

实际上就是这样.

重要提示:请不要忘记FLAG_GRANT_READ_URI_PERMISSION为意图设置标志.否则它将无法工作.

  • 我错过了FLAG_GRANT_READ_URI_PERMISSION,谢谢! (4认同)