简体   繁体   English

使用FileProvider从Gallery中选择图像文件

[英]Picking an image file from Gallery using FileProvider

Compiling for Android N I've faced an issue of FileProvider . 为Android N编译我遇到了FileProvider的问题。 I need to let user to pick image from gallery/take picture with camera then crop it to square. 我需要让用户从相册中选择图像/用相机拍照然后将其裁剪成方形。

I've managed to implement a FileProvider for taking image with camera, but I have serious problem with picking image from gallery. 我已经设法实现了一个用相机拍摄图像的FileProvider ,但是从图库中选择图像时我FileProvider了严重的问题。 The problem is that in the gallery there are lot of files from different places and I've got the Exception for example: 问题是在库中有很多来自不同地方的文件,例如我有Exception:

  java.lang.IllegalArgumentException: Failed to find configured root that contains /storage/6133-3766/DCIM/100ANDRO/DSC_0035.JPG

So the question is, what can I put to file_paths.xml to get access to anywhere in /storage/ . 所以问题是,我可以将什么内容放到file_paths.xml来访问/storage/任何位置。 I can't rely on exact path, since there maybe pictures from WhatsApp and similar apps, for example the WhatsApp image gets this path: 我不能依赖于确切的路径,因为可能有来自WhatsApp和类似应用程序的图片,例如WhatsApp图像获取此路径:

/storage/emulated/0/WhatsApp/Media/WhatsApp Images/IMG-20160821-WA0000.jpg

which I've managed to resolve with empty path: 我已设法解决空路径:

<external-path name="external_storage" path=""/>

which is similar to Environment.getExternalStorageDirectory() according to documentation. 根据文档 ,它类似于Environment.getExternalStorageDirectory()

But still cannot figure out how to deal with images that stored in /storage/SOME_DIR/ . 但仍然无法弄清楚如何处理存储在/storage/SOME_DIR/ Please help. 请帮忙。

I think this question is based on a misunderstanding. 我认为这个问题是基于一个误解。

The purpose of a FileProvider is to grant access (to an external app), to a file that your app already controls. FileProvider的目的是将访问权限(对外部应用程序) 授予您的应用程序已经控制的文件。

You will never succeed in using your own file provider to gain access to a file owned by an external app. 你将永远不会在使用自己的文件提供给访问由外部应用程序拥有的文件成功。

It is up to the external app to grant you that access using a file provider, if it chooses to. 如果选择,则由外部应用程序授予您使用文件提供程序的访问权限。

That seems to be what the question is asking for. 这似乎是问题所要求的。 If I have not understood your question, let me know, but if I do understand it, what you are trying to do just won't work. 如果我没有理解你的问题,请告诉我,但如果我理解它,那么你想要做的就是行不通。

Agreed with @x-code 's answer you are not described very clear about issue although if you try to access another app's internal data then you must have permissions to do so. 同意@ x-code的回答你没有很清楚地说明问题,尽管如果你试图访问另一个应用程序的内部数据,那么你必须有权这样做。

Files that rightfully belong to your app and should be deleted when the user uninstalls your app. 合法属于您的应用的文件,应在用户卸载您的应用时删除。 Although these files are technically accessible by the user and other apps because they are on the external storage, they are files that realistically don't provide value to the user outside your app. 虽然这些文件在技术上可由用户和其他应用程序访问,因为它们位于外部存储上,但它们实际上不会为应用程序外的用户提供价值。

Actually i have found on documentation that SDK version 24 is now updated with many schemes and have massive changes in working with Files,from documentation the problem with file:// is described as.. 实际上,我在文档中发现SDK版本24现在已经使用许多方案进行了更新,并且在使用文件方面进行了大量更改,从文档中将file://的问题描述为..

Passing file:// URIs outside the package domain may leave the receiver with an unaccessible path. 传递file://包域外的URI可能会使接收器留下不可访问的路径。 Therefore, attempts to pass a file:// URI trigger a FileUriExposedException. 因此,尝试传递file:// URI会触发FileUriExposedException。 The recommended way to share the content of a private file is using the FileProvider. 共享私有文件内容的推荐方法是使用FileProvider。

Due to security reasons it is highly recommended to use Content:// instead of using file:// so basically use ContentProvider instead of FileProvider . 出于安全原因,强烈建议使用Content://而不是使用file://所以基本上使用ContentProvider而不是FileProvider

A simple example of using it is below, 下面是一个使用它的简单例子,

in AndroidMenifest.xml AndroidMenifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    ...
    <application
        ...
        <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="${applicationId}.provider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/provider_paths"/>
        </provider>
    </application>
</manifest> 

And then create a provider _paths.xml file in xml folder under res folder. 然后在res文件夹下的xml文件夹中创建一个提供程序_paths.xml文件。 Folder may be needed to create if it doesn't exist. 如果文件夹不存在,则可能需要创建文件夹。

The content of the file is shown below. 该文件的内容如下所示。 It describes that we would like to share access to the External Storage at root folder (path=".") with the name external_files . 它描述了我们希望在名称为external_files根文件夹(path=".")下共享对外部存储的访问。

res/xml/provider_paths.xml RES / XML / provider_paths.xml

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="external_files" path="."/>
</paths>

now to use it, 现在用它,

Uri photoURI = FileProvider.getUriForFile(MainActivity.this,
        BuildConfig.APPLICATION_ID + ".provider",
        createImageFile());

I have taken this from this blog so please read it for full understanding.Hope it helps everyone. 我已经从这个博客中获取了这个,所以请阅读它以获得完全的理解。希望它能帮助每个人。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM