【发布时间】:2014-09-26 16:42:33
【问题描述】:
我设置了一个ContentProvider,仅供我的应用内部使用,以响应带有流的 URI,通过该流我构造并提供一个 zip 文件。
Uri 作为额外的 (Intent.EXTRA_STREAM) 传递给 Intent (Intent.ACTION_SEND) 以便发送。但是,这样做时,它会间歇性地失败并出现以下异常:
E/DatabaseUtils(26058): java.lang.SecurityException: Permission Denial: reading MyContentProvider uri content://spinner.myapp.db/file/stream/zip/1 from pid=26141, uid=10038 requires the provider be exported, or grantUriPermission()
我尝试通过intent.addFlags(Intent.FLAG_GRANT_READ_URI_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);
【问题讨论】:
-
这是您可以重现的东西,还是您至少在测试中看到的东西?或者您是否从生产应用程序中获得这些异常?如果是后者,则可能是某些脚本小子正在尝试访问内容。而且,如果这真的只适用于您自己的应用程序......为什么您首先要使用流媒体
ContentProvider? -
@CommonsWare 目前仅限于我的应用程序开发版本。我一直在使用 ContentProvider,因为它似乎是最适合我的应用程序的模式(包括使用 Loaders 等)。
-
我当然可以看到
Loader用于数据库样式内容的参数,即使我不使用那种特定的方法。不过,我还没有看到通过ContentProvider进行应用内流式传输的任何价值。话虽这么说,我不明白你是如何得到这个例外的。当它出现时,pid和uid是你的吗?还是您不小心尝试将此Uri传递给第三方应用? -
@CommonsWare 我不认为
pid和uid是我的。他们是谁,我不知道。我只是设置一个 Intent 如下:Intent intent = new Intent(Intent.ACTION_SEND); intent.setType("application/x-compressed"); intent.putExtra(Intent.EXTRA_STREAM, Uri.parse(MyContentProvider.CONTENT_URI_FILE_ZIP_STREAM + "/1");之后,我使用Intent.createChooser()选择要发送文件的应用程序(Gmail、Dropbox 等)。 -
“因为只有我自己的应用程序在访问 ContentProvider”——不,不是。您不是 Gmail 的作者,如果您是,那么您也不是 Dropbox 的作者。您也不是许多其他应用程序的作者,这些应用程序会为
ACTION_SEND提供application/x-compressedMIME 类型。在较新版本的 Android 上,grantUriPermissions()应该可以工作,但以前只适用于Uri,它是Intent的“数据”,而不是打包在附加组件中的Uri。
标签: java android android-intent uri android-securityexception