You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

小米设备通过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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 06:30:18