小米设备通过Uri获取Bitmap时触发SecurityException权限拒绝问题求助
解决MIUI设备上GalleryOpenProvider权限拒绝问题
我之前开发时也碰到过小米设备上这个头疼的权限问题,结合你的代码和报错信息,给你几个实用的解决思路:
问题根源
报错里提到的com.miui.gallery.provider.GalleryOpenProvider是小米相册的私有内容提供者,它没有对外导出(exported=false),根据Android安全机制,第三方APP直接访问会被拒绝——这就是问题只在MIUI设备上出现的原因。你的代码直接通过getContentResolver().openInputStream()访问了这个私有Provider的Uri,所以触发了SecurityException。
可行解决方案
1. 改用系统标准MediaStore API访问图片
放弃直接访问MIUI私有Provider,改用Android系统提供的MediaStore接口处理图片Uri,这是最通用的解决方案:
如果你需要直接获取Bitmap:
Bitmap bitmap = null; try { // 使用系统MediaStore的方法获取Bitmap bitmap = MediaStore.Images.Media.getBitmap(context.getContentResolver(), bitmapUri); // 后续对bitmap的处理逻辑 } catch (IOException e) { e.printStackTrace(); }
如果你需要先获取图片尺寸(对应你代码里的inJustDecodeBounds逻辑):
可以先通过MediaStore查询获取宽高,再处理采样率:
BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; // 先查询MediaStore获取图片宽高 Cursor cursor = context.getContentResolver().query( bitmapUri, new String[]{MediaStore.Images.Media.WIDTH, MediaStore.Images.Media.HEIGHT}, null, null, null ); if (cursor != null && cursor.moveToFirst()) { int imgWidth = cursor.getInt(cursor.getColumnIndex(MediaStore.Images.Media.WIDTH)); int imgHeight = cursor.getInt(cursor.getColumnIndex(MediaStore.Images.Media.HEIGHT)); cursor.close(); // 计算合适的采样率(这里可以替换成你自己的计算逻辑) options.inSampleSize = calculateInSampleSize(options, imgWidth, imgHeight); options.inJustDecodeBounds = false; // 再获取Bitmap try (InputStream is = context.getContentResolver().openInputStream(bitmapUri)) { Bitmap bitmap = BitmapFactory.decodeStream(is, null, options); // 处理bitmap } catch (IOException e) { e.printStackTrace(); } } // 示例采样率计算方法 private int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) { final int height = options.outHeight; final int width = options.outWidth; int inSampleSize = 1; if (height > reqHeight || width > reqWidth) { final int halfHeight = height / 2; final int halfWidth = width / 2; while ((halfHeight / inSampleSize) >= reqHeight && (halfWidth / inSampleSize) >= reqWidth) { inSampleSize *= 2; } } return inSampleSize; }
2. 确保权限正确配置
- 对于Android 10及以下:确保Manifest中声明了
READ_EXTERNAL_STORAGE权限,并且已经通过动态权限申请获取了用户授权。 - 对于Android 13及以上:改用
READ_MEDIA_IMAGES权限,同样需要动态申请。
3. 获取标准的图片Uri
如果你的图片Uri是从小米特定入口获取的,建议改用系统标准的文件选择器(比如ACTION_PICK或ACTION_GET_CONTENT)来获取图片,这样得到的是符合系统规范的Uri,不会指向MIUI的私有Provider。
补充:永远不要依赖厂商的私有API或Provider,这些内容没有公开文档,随时可能在系统更新中变更,会导致APP兼容性问题。
内容的提问来源于stack exchange,提问作者sreejith
相关产品推荐
相关产品推荐

