Android 如何使用 Intent.ACTION_VIEW 打开保存到内部存储的私人文件?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21304489/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 04:19:26  来源:igfitidea点击:

How to open private files saved to the internal storage using Intent.ACTION_VIEW?

androidandroid-intent

提问by Abhinav

I am trying a sample program to store a file in the internal storage and the open it using Intent.ACTION_VIEW.

我正在尝试使用示例程序将文件存储在内部存储器中并使用 Intent.ACTION_VIEW 打开它。

For storing the file in private mode I followed the steps provided here.

为了以私有模式存储文件,我遵循了此处提供的步骤

I was able to find the created file in the internal storage at /data/data/com.storeInternal.poc/files .*

我能够在 /data/data/com.storeInternal.poc/files 的内部存储中找到创建的文件。*

But when I tried to open file,it does not open.

但是当我尝试打开文件时,它没有打开。

Please find below the code I used for it.

请在下面找到我用于它的代码。

public class InternalStoragePOCActivity extends Activity {
    /** Called when the activity is first created. */
    String FILENAME = "hello_file.txt";
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        createFile();
        openFile(FILENAME);
    }

    public FileOutputStream getStream(String path) throws FileNotFoundException {
        return openFileOutput(path, Context.MODE_PRIVATE);
    }

    public void createFile(){

        String string = "hello world!";
        FileOutputStream fout = null;
        try {
            //getting output stream
            fout = getStream(FILENAME);
            //writng data
            fout.write(string.getBytes());
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            if(fout!=null){
                //closing the output stream
                try {
                    fout.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }

    }

    public void openFile(String filePath) {
        try {
            File temp_file = new File(filePath);

            Uri data = Uri.fromFile(temp_file);
            String type = getMimeType(data.toString());

            Intent intent = new Intent(android.content.Intent.ACTION_VIEW);
            intent.setDataAndType(data, type);
            startActivity(intent);

        } catch (Exception e) {
            Log.d("Internal Storage POC ", "No Supported Application found to open this file");
            e.printStackTrace();

        }
    }

    public static String getMimeType(String url) {
        String type = null;
        String extension = MimeTypeMap.getFileExtensionFromUrl(url);

        if (extension != null) {
            MimeTypeMap mime = MimeTypeMap.getSingleton();
            type = mime.getMimeTypeFromExtension(extension);
        }

        return type;
    }
}

How may I open the file stored using Context.MODE_PRIVATEby any other existing/appropriate app. Eg: file.pdf should be opened by PDF reader,Video by video Players,etc.

如何通过任何其他现有/适当的应用程序打开使用Context.MODE_PRIVATE存储的文件。例如:file.pdf 应由 PDF 阅读器打开,视频由视频播放器等打开。

回答by NigelK

You can't share/send a file in internal storage, as referenced by a URI, via an Intent to another app. An app cannot read another app's private data (unless it's through a Content Provider). You pass the URI of the file in the intent (not the actual file itself) and the app that receives the intent needs to be able to read from that URI.

您无法通过 Intent 将内部存储中的文件(由 URI 引用)共享/发送到另一个应用程序。一个应用程序不能读取另一个应用程序的私人数据(除非它是通过内容提供者)。您在 Intent 中传递文件的 URI(而不是实际文件本身),接收 Intent 的应用程序需要能够从该 URI 中读取。

The simplest solution is to copy the file to external storage first and share it from there. If you don't want to do that, create a Content Provider to expose your file. An example can be found here: Create and Share a File from Internal Storage

最简单的解决方案是先将文件复制到外部存储并从那里共享。如果您不想这样做,请创建一个 Content Provider 来公开您的文件。可以在此处找到示例:从内部存储创建和共享文件

EDIT: To use a content provider:

编辑:要使用内容提供程序:

First create your content provider class as below. The important override here is 'openFile'. When your content provider is called with a file URI, this method will run and return a ParcelFileDescriptor for it. The other methods need to be present as well since they are abstract in ContentProvider.

首先创建您的内容提供程序类,如下所示。这里重要的覆盖是'openFile'。当使用文件 URI 调用您的内容提供程序时,此方法将运行并为其返回 ParcelFileDescriptor。其他方法也需要存在,因为它们在 ContentProvider 中是抽象的。

public class MyProvider extends ContentProvider {

@Override
public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
    File privateFile = new File(getContext().getFilesDir(), 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;
}
}

Define your provider in the Manifest within the application tag, with exported=true to allow other apps to use it:

在应用程序标签的 Manifest 中定义您的提供程序,使用导出的=true 以允许其他应用程序使用它:

<provider android:name=".MyProvider" android:authorities="your.package.name" android:exported="true" />

In the openFile() method you have in your Activity, set up a URI as below. This URI points to the content provider in your package along with the filename:

在您的 Activity 中的 openFile() 方法中,设置一个 URI,如下所示。此 URI 与文件名一起指向包中的内容提供程序:

Uri uri = Uri.parse("content://your.package.name/" + filePath);

Finally, set this uri in the intent:

最后,在意图中设置这个 uri:

intent.setDataAndType(uri, type);

Remember to insert your own package name where I have used 'your.package.name' above.

记得在我上面使用过“your.package.name”的地方插入你自己的包名。

回答by CooL AndroDev

 File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath()
        + "Foder path" + "/" + "File Name");

        Uri uri = Uri.fromFile(file);
        Intent in = new Intent(Intent.ACTION_VIEW);
        in.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        in.setDataAndType(uri, "mime type");
        startActivity(in);

[Note : Please select mime type as per your file type]

[注意:请根据您的文件类型选择 MIME 类型]

回答by Arifullah Jan

If anyone still faces an issue like: the file couldn't be accessed. This might help u. Along with the content provider u have to set the following flag too...

如果有人仍然面临这样的问题:无法访问文件。这可能对你有帮助。与内容提供者一起,您也必须设置以下标志......

intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

or

或者

intent.setFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);