Android 34通过图片路径加载图片失败,报错FileNotFoundException
问题原因
你遇到的FileNotFoundException是因为ActivityResultContracts.GetContent()返回的Uri是Content Provider Uri,并非真实的文件系统路径。Uri.getPath()得到的/document/image:35只是该Uri的内部路径标识,不是文件在存储介质上的实际位置,因此BitmapFactory.decodeFile()无法找到对应的文件。
解决方案
方案一:获取MediaStore中图片的真实文件路径(适合必须存储路径的场景)
通过ContentResolver查询MediaStore,提取图片的真实文件路径:
private String getRealPathFromUri(Uri uri) { String[] projection = {MediaStore.Images.Media.DATA}; Cursor cursor = null; try { cursor = getContentResolver().query(uri, projection, null, null, null); if (cursor == null) return null; int columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); cursor.moveToFirst(); return cursor.getString(columnIndex); } catch (Exception e) { e.printStackTrace(); return null; } finally { if (cursor != null) { cursor.close(); } } }
在你的代码中替换路径获取逻辑:
// 替换原有的 String path = FilePathUri.getPath(); String path = getRealPathFromUri(FilePathUri); if (path != null) { Bitmap bitmapFromPath = BitmapFactory.decodeFile(path); imageView.setImageBitmap(bitmapFromPath); }
注意:该方法仅适用于MediaStore收录的图片,对于通过SAF选择的非MediaStore文件(比如外部存储根目录的文件)无法获取真实路径,此时需要使用方案二。
方案二:保存Uri字符串到数据库,通过ContentResolver加载图片(推荐,符合Android存储规范)
Android 10及以上版本(包括34)的Scoped Storage机制推荐使用Uri而非直接操作文件路径。你可以直接将Uri的字符串形式存入数据库,加载时通过ContentResolver打开输入流解码图片:
保存Uri到数据库
// 将Uri转为字符串保存 String savedUriString = FilePathUri.toString(); // 执行数据库插入操作...
从数据库加载图片
// 从数据库取出Uri字符串 String savedUriString = "从数据库获取的Uri字符串"; Uri savedUri = Uri.parse(savedUriString); try (InputStream inputStream = getContentResolver().openInputStream(savedUri)) { Bitmap bitmap = BitmapFactory.decodeStream(inputStream); imageView.setImageBitmap(bitmap); } catch (IOException e) { e.printStackTrace(); }
这种方式无需处理复杂的路径转换,完全符合Android的权限模型,避免Scoped Storage带来的限制。
内容的提问来源于stack exchange,提问作者parsecer
相关产品推荐
相关产品推荐

