Java 有哪些选项可用于解决间歇性权限拒绝安全异常?

Java 有哪些选项可用于解决间歇性权限拒绝安全异常?,java,android,android-intent,uri,android-securityexception,Java,Android,Android Intent,Uri,Android Securityexception,我已经设置了一个ContentProvider,只供我的应用程序内部使用,用流响应URI,通过它我构造并提供一个zip文件 Uri作为额外的Intent.extra\u流传递给Intent Intent.ACTION\u SEND以发送它。但是,在执行此操作时,它会间歇性失败,出现以下异常: E/DatabaseUtils26058:java.lang.SecurityException:权限拒绝:读取MyContentProvider uricontent://spinner.myapp.db

我已经设置了一个ContentProvider,只供我的应用程序内部使用,用流响应URI,通过它我构造并提供一个zip文件

Uri作为额外的Intent.extra\u流传递给Intent Intent.ACTION\u SEND以发送它。但是,在执行此操作时,它会间歇性失败,出现以下异常:

E/DatabaseUtils26058:java.lang.SecurityException:权限拒绝:读取MyContentProvider uricontent://spinner.myapp.db/file/stream/zip/1 从pid=26141开始,uid=10038要求导出提供程序或grantUriPermission


我已尝试通过intent.addFlagsInt.FLAG\u GRANT\u READ\u URI\u PERMISSION;授予权限;,但这并没有奏效。我也不明白为什么我需要授予权限,因为只有我自己的应用程序才能访问ContentProvider

更新:

我现在也尝试使用setClipData,但没有成功。Gmail显然忽略了Uri,Dropbox崩溃了

String[] mimeTypes = { "application/x-compressed" };
ClipData clip = new ClipData("zip data", mimeTypes, new ClipData.Item(uri));
intent.setClipData(clip);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
啊,我明白了,所以发送应用程序必须为每个Uri授予自己的权限,而不是由调用应用程序的意图隐式提供

我被你的术语弄糊涂了,所以让我试试这种方法:

实现ContentProvider有四种基本方法:

将其导出并且不受任何权限的保护。这太愚蠢了。不要这样做

将其导出,但由权限保护,例如android:readPermission和android:writePermission属性。这很有效,但仅适用于专门为与您的内容提供商对话而编写的应用程序。它不适用于对您的内容提供者没有先验知识的应用程序,就像大多数支持行动的活动的实现者一样

不要将其导出,而是让您为特定请求授予Uri权限。通常,这是通过添加到startActivity使用的意图中来完成的,尽管还有其他方法,例如自己调用grantUriPermission。当您是需要第三方访问您的提供商的发起人时,这非常有效,例如启动具有操作发送意图的活动

不要将其导出,也不要授予对Uri的权限。在这种情况下,ContentProvider仅在您自己的应用程序中可用,并且第三方根本无法访问,即使您请求,例如您的操作发送请求

我如何为最终被选择执行发送的应用授予权限,或者我必须向所有可能的应用授予权限

这是我的一个评论中的一个错误,对此我深表歉意

现在,FLAG_GRANT_READ_URI_PERMISSION在您的意图中授予对您的URI的读取权限,无论该URI是该意图的数据还是在额外的文件中。这将被授予意图的最终使用者-换句话说,选择器不会以某种方式使用权限,并且所选活动没有权限。然而,过去的情况是,FLAG_GRANT_READ_URI_PERMISSION只对数据起作用,而不是对extras中的URI值起作用,我一下子就忘了这个漏洞是什么时候修复的

grantUriPermission要求您知道意图的最终消费者是谁,这意味着您需要滚动您自己的选择器,以便您可以找到用户想要处理您建议的操作和发送请求的实际应用程序


FWIW,它演示了如何使用标志“授予”\u“读取”\u“URI”\u权限来查看文件提供商提供的PDF。

这是您可以复制的,还是您至少在测试中看到的?或者您是否从生产应用程序中获取这些异常?如果是后者,可能是一些脚本小子试图访问内容。而且,如果这真的只适用于你自己的应用程序。。。为什么您首先要使用流媒体内容提供商?@commonware它目前仅限于我的应用程序开发版本。我一直在使用ContentProvider,因为它似乎是最适合我的应用程序的模式,包括使用加载器等。我当然可以看到数据库样式内容的加载器参数,尽管我没有使用那种特殊的方法。不过,我还没有看到通过ContentProvider进行应用内流媒体传输的任何价值。话虽如此,我不知道你怎么会得到这个例外。当它出现时,pid和uid是您的吗?还是你不小心试图将此Uri传递给第三方应用程序?@commonware我认为pid和uid不是我的。我不知道他们是谁的。我只是建立一个如下的意图:Intent Intent=newintentintent.ACTION\u SEND;intent.setTypeapplication/x-compressed;intent.putExtraIntent.EXTRA_流,Uri.parseMyContentProvider.CONTENT_Uri_文件_ZIP_流+/1;之后,我使用Intent.createChooser选择要发送文件Gmail、Dropbox等的应用程序,因为只有我自己的应用程序在访问ContentProvider-不,不是。你不是Gmail的作者,如果你是,那么你就不是
Dropbox的作者。你也不是很多其他应用程序的作者,这些应用程序都是为了应用程序/x压缩MIME类型而发送的。在较新版本的Android上,grantUriPermissions应该可以工作,但之前它只适用于作为意图数据的Uri,而不是额外打包的Uri。我的目标是Android 4.3版本18,minSdkVersion=15,我想我遇到了你提到的问题,仅对通过setData设置的URI(而不是putExtra)进行操作的FLAG_GRANT_READ_URI_权限。不幸的是,将Uri设置为数据而不是额外的似乎不适合发送文件,例如附件Gmail会将Uri放入“收件人”字段,Dropbox就会崩溃。我已经查找了有关此更改的文档,但还没有找到任何文档。我在中发现了一些关于此更改行为的提及,具体涉及到setClipData的使用。不过,到目前为止还没能让它发挥作用;Dropbox仍然死机,Gmail没有附加任何文件。@Spinner:我必须为此写一些示例。setClipData的问题是,客户端也需要更改以使用ClipData,而许多客户端可能不需要更改。特别是,如果Dropbox遇到与以前相同的错误而崩溃,那么他们可能根本没有注意到ClipData,只是使用了Uri,结果失败了。我不知道为什么Gmail不会崩溃,但不附加文件,除非整个Uri是无效的。你有关于什么时候发生的改变,导致FLAG_GRANT_READ_Uri_允许处理额外的东西的信息吗?由于setClipData更改是在Jelly Bean中进行的,因此人们会认为它是在那时出现的;然而,由于我运行的是4.3,这就意味着只有在4.4中进行了更改。这是假设我的设置功能正常。@Spinner:setClipData从4.1开始就存在了。话虽如此,我现在很难找到我的参考,如果/当FLAG_GRANT_READ_URI_权限与附加项一起工作。我可能记错了。