如何检查ContentProvider可用于Intent(或阻止特定的一个)

我使用Intent机制让用户通过标准的方式选择图像

val intent = Intent(Intent.ACTION_GET_CONTENT) intent.type = "image/*" intent.addCategory(Intent.CATEGORY_OPENABLE) ctx.startActivityForResult(intent, RequestCodes.SelectPhoto) 

然后我将Uri传递给另一个活动,可能会裁剪照片。 我需要之前的Uri做一些预先检查。

在Android模拟器上,像Photos(默认)这样的默认提供程序会让我的整个应用程序有权打开Uri,而不仅仅是请求活动。 然而,在亚洲有一个“奇怪”的提供者, com.miui.gallery.provider.GalleryOpenProvider并没有 – 在com.miui.gallery.provider.GalleryOpenProvider器中发生了一个邪恶的SecurityException。

所以我尝试使用ACTION_OPEN_DOCUMENT,根据规范说,它会给我的整个应用程序权限,直到设备重新启动,但不幸的是,一个不支持在模拟器云中的谷歌照片。

所以我正在寻找一种方法来确定是否将列表中的com.miui.gallery.provider.GalleryOpenProvidercom.miui.gallery.provider.GalleryOpenProvider ,如果是这样,要么阻止它,否则回落到使用ACTION_OPEN_DOCUMENT。 我希望避免在把Uri交给收割机之前将其拷贝,作物活动无论如何都将其视为只读。

这是启动作物(kotlin)的全部function。 CropActivity是对旧版开源图库应用com.android.gallery3d的修改。

 private fun startCrop(ctx: Activity, uri: Uri) { val intent = Intent(ctx, CropActivity::class.java) intent.data = uri val file = this.createImageFile(ctx, "photofinal") if (file == null) { this.showStorageUnavailable(ctx) return } val outputUri = Uri.fromFile(file) intent.putExtra(MediaStore.EXTRA_OUTPUT, outputUri) intent.putExtra(CropExtras.KEY_MIN_CROP_SIDE, Config.minimumImageDimension) intent.putExtra(CropExtras.KEY_MOST_OBLONG_ASPECT, Config.maxPhotoAspectRatio) intent.putExtra(CropExtras.KEY_EXIF_ORIENTATION, exifOrientation) ctx.startActivityForResult(intent, RequestCodes.CropPhoto) } 

然后我将Uri传递给另一个活动,可能会裁剪照片

Uri传递给Intent的“数据”方面,并添加FLAG_GRANT_READ_URI_PERMISSION将读取权限转移到其他组件。 看这个示例应用程序 :

  @Override public void onActivityResult(int requestCode, int resultCode, Intent resultData) { if (resultCode==Activity.RESULT_OK) { getActivity() .startService(new Intent(getActivity(), DurablizerService.class) .setData(resultData.getData()) .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)); } } 

在这里,我碰巧把Uri传递给一个服务,但同样的原则也适用于一个活动。

有关Uri访问生存期的更多信息,另请参阅此博客文章 。

或者,不要使用单独的活动,而是做其他事情(例如,多个片段)。

在Android模拟器上,像Photos(默认)这样的默认提供程序会让我的整个应用程序有权打开Uri,而不仅仅是请求活动。

如果Uri具有file方案或来自导出的无权限的ContentProvider则会发生这种情况。

所以我尝试使用ACTION_OPEN_DOCUMENT,根据规范说,它会给我的整个应用程序权限,直到设备重新启动

它遵循与从ACTION_GET_CONTENT获得的Uri值相同的一般规则。

所以我正在寻找一种方法来确定是否将com.miui.gallery.provider.GalleryOpenProvider列表上的GET_CONTENT

这不是完全可能的。 任何应用程序都可以从该提供程序返回一个Uri实际上 ,该提供商只能由其托管应用程序使用。 如果您find该提供程序的应用程序的软件包名称,并且您使用ACTION_GET_CONTENT IntentPackageManager上使用了queryIntentActivities() ,则可以确定该应用程序中的活动是否在ACTION_GET_CONTENT实现列表中。

但是,如果您使用FLAG_GRANT_READ_URI_PERMISSION ,正如我前面所述,这不应该是必需的。

如果是的话,要么阻止它

除了通过滚动你自己的“选择器”风格的用户界面,这是不可能的。