Android:如何获取外部存储PUBLIC目录中文件的content://URI [英] Android: How to get a content:// URI for a file in the external storage PUBLIC directory

查看:236
本文介绍了Android:如何获取外部存储PUBLIC目录中文件的content://URI的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已遵循此Google教程开始使用new Intent(MediaStore.ACTION_IMAGE_CAPTURE)捕获图像.本教程建议将公用目录与getExternalStoragePublicDirectory一起使用,这将对我的应用程序非常有用.但随后他们的示例改为使用getExternalFilesDir.然后使用MediaStore.EXTRA_OUTPUT将文件的URI传递给意图我不太好

I've followed this Google tutorial to start an intent to capture an image with new Intent(MediaStore.ACTION_IMAGE_CAPTURE). The tutorial recommends using the public directory with getExternalStoragePublicDirectory which would work great for my app. But then their example instead uses getExternalFilesDir. Then to pass the URI of the file to the intent with MediaStore.EXTRA_OUTPUT I have to get a content URI because I'd like to target Android N. Before targeting N I would just pass a file:// URI and everyone but Google was happy. Now on N I started getting the FileUriExposedException that seems to be not very favorable.

因此,鉴于我有一个像这样的文件...

So given that I have a File like this...

private File createImageFile() throws IOException {
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
    File storageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "MyAppFolder");
    if (!storageDir.exists() && !storageDir.mkdir())
        Log.w(TAG, "Couldn't create photo folder: " + storageDir.getAbsolutePath());
    File image = new File(storageDir, timeStamp + ".jpg");
    mCurrentPhotoPath = image.getAbsolutePath();
    return image;
}

...我可以使用公共图片目录的内置提供程序来获取内容URI吗?如果可以,怎么办?

...can I use a built-in provider for the public pictures directory to get a content URI? If so how?

我尝试过类似的事情

takePictureIntent.putExtra(
    MediaStore.EXTRA_OUTPUT, 
    FileProvider.getUriForFile(this, MediaStore.AUTHORITY, createImageFile()));

但是它只是抛出

IllegalArgumentException:缺少android.support.FILE_PROVIDER_PATHS元数据

IllegalArgumentException: Missing android.support.FILE_PROVIDER_PATHS meta-data

该机构是否正确?如果必须使用自己的提供程序来共享公共文件,那么我可以在FILE_PROVIDER_PATHS元数据中指定什么路径?我可以找到的所有选项都是针对私有目录的. >

Is that Authority correct? If I must use my own provider to share the public file then what path can I specify in my FILE_PROVIDER_PATHS meta-data? All of the options I can find are for private directories.

推荐答案

TL:DR <external-path name="MyAppFolder" path="." />可行,但是安全吗?

TL:DR <external-path name="MyAppFolder" path="." /> works, but is it safe?

您将需要制作自己的FileProvider.值得阅读其文档,但这是一个简短的摘要.

You will need to make your own FileProvider. It's worth reading its documentation, but here's a brief rundown.

如@CommonsWare所述,您需要将示例中的MediaStore.AUTHORITY替换为"com.example.fileprovider",这是您将在清单中定义的权限,例如...

As @CommonsWare mentioned, you'll need to replace MediaStore.AUTHORITY from your example with "com.example.fileprovider", which is the authority you will define in your manifest like so...

在AndroidManifest的<application>标记内,键入以下内容:

Within the <application> tag in the AndroidManifest, type the following:

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

您遇到的异常是由于没有链接到XML文件的<meta-data>标记,该标记具有允许您触摸FileProvider的所有路径.但正是我一直在努力解决的这个文件中的内容.

The exception you're getting is due to not having that <meta-data> tag that links to an xml file with all the paths that your FileProvider is allowed to touch. But it's what goes in this file that I've been struggling with myself.

在您链接的教程的结尾处,全尺寸照片部分,Google为此file_paths.xml提供的示例是:

Towards the end of the tutorial you linked, at the end of the Save the Full-size Photo section, the example Google gives for this file_paths.xml is:

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="my_images" path="Android/data/com.example.package.name/files/Pictures" />
</paths>

在您的示例中,

"my_images"将替换为"MyAppFolder". Google在该教程中声称

"my_images" would be replaced with "MyAppFolder" in your example. In that tutorial Google claims

路径组件对应于用Environment.DIRECTORY_PICTURES调用时getExternalFilesDir()返回的路径.确保将com.example.package.name替换为应用程序的实际包名称.

The path component corresponds to the path that is returned by getExternalFilesDir() when called with Environment.DIRECTORY_PICTURES. Make sure that you replace com.example.package.name with the actual package name of your app.

...然后键入该内容使我意识到,这并不指向您和我正在寻找的公共图片目录.这就解释了为什么使用该路径会产生此异常:

...and typing that out made me realize that that is NOT referring to the public Pictures directory that you and I are looking for. Which explains why using that path produces this exception:

java.lang.IllegalArgumentException:无法找到包含/storage/emulated/0/Pictures/MyAppFolder/{filename}.jpg

java.lang.IllegalArgumentException: Failed to find configured root that contains /storage/emulated/0/Pictures/MyAppFolder/{filename}.jpg

我将其留在此处以供将来参考,然后继续回答您的大问题-您可以指定什么路径以允许其他应用与您以应用定位API级别的应用创建的公共图片目录中的文件进行交互24 +?

I'll leave that in here for future reference, and move on to answering your big question--what path can you specify to allow other apps to interact with a file in the public Pictures directory created by your app targeting API level 24+?

正如@CommonsWare所说,所需子目录的详细信息因设备而异",因此您无法声明公共Pictures目录的路径,但我确实找到了一种可行的方法.

As @CommonsWare said, "the details of your desired subdirectory vary by device" so you can't declare the path to the public Pictures directory, but I did find a way that works.

<external-path name="MyAppFolder" path="." />将允许您的FileProvider将内容URI提供给其他应用程序(例如Camera),然后这些应用程序可以读取和写入其解析为的文件.

<external-path name="MyAppFolder" path="." /> will allow your FileProvider to give a content URI to other apps (like the Camera), which can then read and write to the file it resolves to.

如果对此有任何危险或不利之处,我希望听到他们的声音.

If there are any dangers or downsides to this, I would love to hear them.

这篇关于Android:如何获取外部存储PUBLIC目录中文件的content://URI的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆