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

Android 10/11 scoped storage下已保存图片检索bitmap为null问题求助

问题根因

  • Android 10及以上的分区存储机制禁止直接通过绝对路径访问共享存储中的媒体文件,你代码中Uri.getPath()拿到的只是content URI的路径片段,不是文件实际存储路径,用BitmapFactory.decodeFile()读取该路径自然找不到文件,返回null并抛出FileNotFoundException。
  • 额外问题:你保存代码最终返回的是自行拼接的绝对路径,该路径在分区存储场景下完全无法用于后续文件访问,应该直接返回插入媒体库得到的newImageUri用于后续检索。

修复方案

1. 保存代码优化(可选但强烈建议)

新增IS_PENDING标记,避免媒体库在文件写入完成前就索引该文件导致读取失败:

File dirDest = new File(Environment.DIRECTORY_PICTURES, context.getString(R.string.app_name));
Long date = System.currentTimeMillis();
String extension = ".jpg";

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
    ContentResolver resolver = context.getContentResolver();
    ContentValues contentValues = new ContentValues();
    contentValues.put(MediaStore.Images.Media.DISPLAY_NAME, date + extension);
    contentValues.put(MediaStore.Images.Media.MIME_TYPE, "image/jpg");
    contentValues.put(MediaStore.Images.Media.DATE_ADDED, date / 1000); // DATE_ADDED要求单位为秒,不是毫秒
    contentValues.put(MediaStore.Images.Media.DATE_MODIFIED, date / 1000);
    contentValues.put(MediaStore.Images.Media.SIZE, bitmap.getByteCount());
    contentValues.put(MediaStore.Images.Media.WIDTH, bitmap.getWidth());
    contentValues.put(MediaStore.Images.Media.HEIGHT, bitmap.getHeight());
    contentValues.put(MediaStore.Images.Media.RELATIVE_PATH, dirDest + File.separator);
    contentValues.put(MediaStore.Images.Media.IS_PENDING, 1); // 标记为待处理,写入完成前媒体库不会暴露该文件
    Uri newImageUri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);
    FileOutputStream fos = (FileOutputStream) resolver.openOutputStream(Objects.requireNonNull(newImageUri));
    callback.write(fos);
    fos.flush();
    fos.close();
    // 写入完成后更新标记为可访问
    contentValues.clear();
    contentValues.put(MediaStore.Images.Media.IS_PENDING, 0);
    resolver.update(newImageUri, contentValues, null, null);
    // 返回Uri字符串而不是自行拼接的路径,后续检索直接用这个Uri
    return newImageUri.toString();
}

2. 检索代码修复

不要用绝对路径解码,通过ContentResolver打开输入流解码Bitmap:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
    String[] projection = {MediaStore.Images.Media._ID,
            MediaStore.Images.Media.RELATIVE_PATH,
            MediaStore.Images.Media.DISPLAY_NAME,
            MediaStore.Images.Media.SIZE,
            MediaStore.Images.Media.MIME_TYPE,
            MediaStore.Images.Media.WIDTH,
            MediaStore.Images.Media.HEIGHT,
            MediaStore.Images.Media.DATE_MODIFIED};
    if (uri != null) {
        Cursor cursor = null;
        try {
            cursor = context.getContentResolver().query(uri, projection, null, null, null);
            if (cursor != null && cursor.moveToFirst()) {
                // 直接通过ContentResolver开输入流解码Bitmap,不需要转File路径
                try (InputStream inputStream = context.getContentResolver().openInputStream(uri)) {
                    bitmap = BitmapFactory.decodeStream(inputStream);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }
    }
}

内容的提问来源于stack exchange,提问作者Muhammad Umair

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.10 06:12:01