使用上下文提供程序的数据还是请求Google照片读取权限?

24

我的应用程序允许用户从其他应用程序导入他们的照片和视频。现在,由于Google用Google Photos替换了Google+ Photos,我的应用程序出现了一些问题。其中之一是在应用程序重新启动后重复使用已导入的文件。我有一种感觉,当Google Photos返回带有图像URI的意图时,他们加强了授予权限,因此在我的应用程序被杀死后,它不再具备访问上传的文件的权限。我遇到了安全异常:

java.lang.SecurityException: Permission Denial: opening provider com.google.android.apps.photos.contentprovider.MediaContentProvider from ProcessRecord{2c17ab9e 2124:com.myapp.myapp/u0a436} (pid=2124, uid=10436) that is not exported from uid 10427

编辑:

我也遇到了重复使用由com.google.android.apps.docs.sync.filemanager.FileProvider提供的文件时出现的同样问题。

有任何建议或变通方法吗?我知道我可以在失去权限之前读取文件,理论上我可以复制它,但我不太喜欢这种方法。

6个回答

28

是的,这是有意为之的设计,就像在Android开发者网站上所描述的那样。

出于安全原因,权限是临时的,因此一旦客户端应用程序的任务堆栈完成,文件就不再可访问。您必须在接收到意图答案时获取文件数据,在onActivityResult方法中存储文件数据的副本,因为当onActivityResult返回时,该文件将不再可用。


这也是我的结论,所以我会选择你的答案作为答案。谢谢。 - vkislicins
1
它看起来像是反模式。在主线程中复制文件的副本? - tse
@tse 只要您的活动没有停止,您就可以从任何线程访问它所针对的意图。 - Adrien Aubel
3
我之前也遇到过类似的问题,后来我使用了ACTION_OPEN_DOCUMENT而不是ACTION_PICK来解决它。据我所知,ACTION_OPEN_DOCUMENT会授予持久的权限,相较于ACTION_PICK不那么严格。当我使用ACTION_PICK时,在一个活动中获取URI并在另一个活动中显示图片时,我就失去了权限,这和开发者文档上说的一样。 - onusopus
@onusopus 谢谢,你的回答应该被接受为最佳答案。 - ralphgabb
@onusopus 仍然适用,谢谢。但是问题仍然存在,权限在重新启动后丢失。 - Prof

13
  1. 当你使用“Google相册”应用程序时,可能会出现SecurityException日志。

  2. 这个问题的主要原因是“Google相册”将ContentUri与固定字符串共享,例如“content://com.google.android.apps.photos.contentprovider/1/1”,然后将其连接到静态临时值。当实际接收Intent.ACTION_SEND的Activity或Context时,“Google相册”不提供文件路径。也许这是“Google相册”的政策,不向其他应用程序公开私有图像文件。

  3. 例如,你在Manifest文件中定义了两个Activity,Actvity A和Activity B。Activity A用于接收Intent.ACTION_SEND,Activity B用于处理图像文件。Activity A将Intent转发给Activity B。然后Activity B不是“Google相册”的正确Activity,你遇到了SecurityException。

因此,我建议你在Activity A上暂时保存文件,并在Activity B上使用临时文件路径。


我认为您的答案对我的问题是正确的。 - jihoon kim
1
我有同样的问题,Google照片会引起很多问题 :-/ - Oliver Dixon

3
也许您可以在清单文件中添加此用户权限。
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />

1
你可以使用InputStream来访问文件吗?例如:"context.getContentResolver().openInputStream(uri);"? - Zephyr
1
这正是当我收到权限错误时所做的事情。 - vkislicins

2

看起来这个问题很相似

我认为当活动(而不是片段)结束时,由其检索的所有URI都会失效

我也遇到了同样的问题-尝试在后台上传图片。但是用户在UI线程中可能会更改活动,从而使URI无效


是的,看起来很相似,但我认为新的照片应用程序内容提供程序的权限已经改变了,因为我有一种感觉之前尝试过那个权限,但没有成功。最终,我将文件复制到我的领域并在我的内容提供程序中注册它们以保留访问权限。如果您找到更好的解决方案,请告诉我! - vkislicins

1

您需要显式地设置权限以使所有软件包与您的意图匹配。这通常发生在Android 4.4中。

您可以使用此实用程序来完成此操作:

List<ResolveInfo> resInfoList = getContext().getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
        for (ResolveInfo resolveInfo : resInfoList) {
            String packageName = resolveInfo.activityInfo.packageName;
            getContext().grantUriPermission(packageName, imageFileUri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
        }

0

我的问题不在于最初的获取调用 - 而是权限保留。在获取文件访问权限后,如果应用程序被挂起或用户离开应用程序,则访问权限将被撤销。 - vkislicins
请在此处包含答案,而不仅仅是链接。请参见http://meta.stackexchange.com/questions/8231/are-answers-that-just-contain-links-elsewhere-really-good-answers - Nicolas Raoul

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接