如何检查可用于 Intent 的 ContentProvider(或阻止特定的 ContentProvider)
How to inspect ContentProvider available for Intent (or block specific one)
我使用 Intent 机制让用户 select 通过标准方式获取图像
val intent = Intent(Intent.ACTION_GET_CONTENT)
intent.type = "image/*"
intent.addCategory(Intent.CATEGORY_OPENABLE)
ctx.startActivityForResult(intent, RequestCodes.SelectPhoto)
然后我将 Uri 传递给另一个 activity 以裁剪照片。我之前需要 Uri 来做一些预检查。
在 Android 模拟器上,照片等默认提供程序(显然)允许我的整个应用程序打开 Uri,而不仅仅是请求 activity。然而,在亚洲有一个 "weird" 供应商,com.miui.gallery.provider.GalleryOpenProvider
没有 - cropper 中发生了一个邪恶的 SecurityException。
所以我尝试使用 ACTION_OPEN_DOCUMENT,根据规范,它将授予我整个应用程序权限,直到设备重新启动,但不幸的是,它不支持 Google 云端照片, 在模拟器中。
所以我正在寻找一种方法来确定 com.miui.gallery.provider.GalleryOpenProvider
是否会出现在 GET_CONTENT 的列表中,如果是,要么阻止它,要么退回到使用 [=28] =].我想避免在将 Uri 提供给裁剪器之前复制流,裁剪器 activity 无论如何都将其视为只读。
这是开始裁剪的完整功能 (kotlin)。 CropActivity 是对旧的开源 Gallery 应用程序的修改 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)
}
then I pass the Uri to another activity to maybe crop the photo
将 Uri
传递到 Intent
的 "data" 方面,并添加 FLAG_GRANT_READ_URI_PERMISSION
以将读取权限转移到其他组件。见 this sample app:
@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
传递给服务,但同样的原则也适用于 activity。
有关 Uri
访问生命周期的更多信息,另请参阅 this blog post。
或者,不使用单独的活动,而是做其他事情(例如,多个片段)。
On the Android emulators, the default providers such as Photos (apparently) give my whole app permission to open the Uri, not just the requesting activity.
如果 Uri
具有 file
方案或来自导出的无许可 ContentProvider
。
So I try to use ACTION_OPEN_DOCUMENT, which per the specs say that it will give my whole app permission until device reboot
它与您从 ACTION_GET_CONTENT
获得的 Uri
值遵循相同的一般规则。
So I am looking for a way to determine if com.miui.gallery.provider.GalleryOpenProvider is going to be on the list for GET_CONTENT
这完全不可能。任何应用程序都可以 return 来自该提供商的 Uri
。在 实践 中,该提供程序只能由其托管应用程序使用。如果您找到该提供商的应用程序包名称,并且您在 PackageManager
上使用 queryIntentActivities()
和您的 ACTION_GET_CONTENT
Intent
,您可以确定是否 activity 来自应用在 ACTION_GET_CONTENT
实施列表中。
但是,如果您使用 FLAG_GRANT_READ_URI_PERMISSION
,正如我之前提到的,那应该不是必需的。
if so either prevent it
除了滚动你自己的 "chooser" 风格 UI 之外,这完全不可能。
我使用 Intent 机制让用户 select 通过标准方式获取图像
val intent = Intent(Intent.ACTION_GET_CONTENT)
intent.type = "image/*"
intent.addCategory(Intent.CATEGORY_OPENABLE)
ctx.startActivityForResult(intent, RequestCodes.SelectPhoto)
然后我将 Uri 传递给另一个 activity 以裁剪照片。我之前需要 Uri 来做一些预检查。
在 Android 模拟器上,照片等默认提供程序(显然)允许我的整个应用程序打开 Uri,而不仅仅是请求 activity。然而,在亚洲有一个 "weird" 供应商,com.miui.gallery.provider.GalleryOpenProvider
没有 - cropper 中发生了一个邪恶的 SecurityException。
所以我尝试使用 ACTION_OPEN_DOCUMENT,根据规范,它将授予我整个应用程序权限,直到设备重新启动,但不幸的是,它不支持 Google 云端照片, 在模拟器中。
所以我正在寻找一种方法来确定 com.miui.gallery.provider.GalleryOpenProvider
是否会出现在 GET_CONTENT 的列表中,如果是,要么阻止它,要么退回到使用 [=28] =].我想避免在将 Uri 提供给裁剪器之前复制流,裁剪器 activity 无论如何都将其视为只读。
这是开始裁剪的完整功能 (kotlin)。 CropActivity 是对旧的开源 Gallery 应用程序的修改 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)
}
then I pass the Uri to another activity to maybe crop the photo
将 Uri
传递到 Intent
的 "data" 方面,并添加 FLAG_GRANT_READ_URI_PERMISSION
以将读取权限转移到其他组件。见 this sample app:
@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
传递给服务,但同样的原则也适用于 activity。
有关 Uri
访问生命周期的更多信息,另请参阅 this blog post。
或者,不使用单独的活动,而是做其他事情(例如,多个片段)。
On the Android emulators, the default providers such as Photos (apparently) give my whole app permission to open the Uri, not just the requesting activity.
如果 Uri
具有 file
方案或来自导出的无许可 ContentProvider
。
So I try to use ACTION_OPEN_DOCUMENT, which per the specs say that it will give my whole app permission until device reboot
它与您从 ACTION_GET_CONTENT
获得的 Uri
值遵循相同的一般规则。
So I am looking for a way to determine if com.miui.gallery.provider.GalleryOpenProvider is going to be on the list for GET_CONTENT
这完全不可能。任何应用程序都可以 return 来自该提供商的 Uri
。在 实践 中,该提供程序只能由其托管应用程序使用。如果您找到该提供商的应用程序包名称,并且您在 PackageManager
上使用 queryIntentActivities()
和您的 ACTION_GET_CONTENT
Intent
,您可以确定是否 activity 来自应用在 ACTION_GET_CONTENT
实施列表中。
但是,如果您使用 FLAG_GRANT_READ_URI_PERMISSION
,正如我之前提到的,那应该不是必需的。
if so either prevent it
除了滚动你自己的 "chooser" 风格 UI 之外,这完全不可能。