Android 12裁剪MediaStore图片触发SecurityException求助
解决Android 12中MediaStore Uri裁剪触发的SecurityException问题
问题根源
Android 12(API 31)及更高版本中,通过MediaStore查询得到的content://media/external/...类型Uri,默认仅授予当前应用访问权限。启动第三方裁剪应用时,该应用无法直接访问你的应用持有的这个Uri,因此触发SecurityException。
解决方案
核心是给裁剪应用临时授予Uri的读权限,有两种可靠实现方式:
方式1:给Intent添加权限标志
构建裁剪Intent时,添加FLAG_GRANT_READ_URI_PERMISSION标志,让系统自动将Uri的读权限传递给目标应用:
val intent = Intent("com.android.camera.action.CROP").also { it.setDataAndType(su, MediaType.IMAGE.value()) // 关键:添加Uri读权限标志 it.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) it.putExtra("aspectX", 1)//ratio it.putExtra("aspectY", 1) it.putExtra("outputX", size)//size it.putExtra("outputY", size) it.putExtra("scale", true) it.putExtra("return-data", false)//no thumbnail got from back intent it.putExtra("outputFormat", format) it.putExtra(MediaStore.EXTRA_OUTPUT, cropUri) }
方式2:显式授予权限给所有支持裁剪的应用
部分设备上仅添加Intent标志可能不生效,可先查询所有能处理裁剪Intent的应用,逐个授予Uri权限:
val intent = Intent("com.android.camera.action.CROP").also { it.setDataAndType(su, MediaType.IMAGE.value()) it.putExtra("aspectX", 1)//ratio it.putExtra("aspectY", 1) it.putExtra("outputX", size)//size it.putExtra("outputY", size) it.putExtra("scale", true) it.putExtra("return-data", false)//no thumbnail got from back intent it.putExtra("outputFormat", format) it.putExtra(MediaStore.EXTRA_OUTPUT, cropUri) } // 显式给所有支持裁剪的应用授予Uri读权限 val resInfoList = act.packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY) for (resolveInfo in resInfoList) { val packageName = resolveInfo.activityInfo.packageName act.grantUriPermission(packageName, su, Intent.FLAG_GRANT_READ_URI_PERMISSION) }
关键说明
MediaStore.getRedactedUri()仅用于隐藏Uri中的敏感信息(如媒体ID),不涉及权限授予,因此无法解决该问题。- 裁剪系统相机拍摄的图片正常,是因为相机返回的Uri已通过拍摄Intent自动授予了临时权限,或图片存储在应用私有目录(裁剪应用可通过Uri访问)。
内容的提问来源于stack exchange,提问作者JiangNan
相关产品推荐
相关产品推荐

