从Download文件夹自动获取单张图片到ImageView时遇文件异常求助
解决MediaStore获取单张图片时的FileNotFoundException问题
这个问题我之前也碰到过,本质是你传给getBitmap()的不是单张图片的具体Uri,而是一个包含多张图片的集合Uri,系统没办法直接定位到单个文件,所以才抛出了FileNotFoundException。下面给你一套完整的解决思路和可直接用的代码:
核心思路
先通过MediaStore查询Download文件夹中的单张图片(比如最新的那一张),拿到它的具体Uri,再用这个Uri加载图片到ImageView,而不是直接传入集合Uri。
完整代码实现
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ImageView imageView = findViewById(R.id.image_view); // 从Download文件夹获取第一张图片的Uri Uri targetImageUri = getFirstImageFromDownload(); if (targetImageUri != null) { // 将图片加载到ImageView loadImageToView(targetImageUri, imageView); } else { // 处理Download文件夹无图片的情况 Toast.makeText(this, "Download文件夹里没找到图片哦", Toast.LENGTH_SHORT).show(); } } // 查询Download文件夹中最新的一张图片Uri private Uri getFirstImageFromDownload() { Uri imageCollection = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; String[] projection = {MediaStore.Images.Media._ID}; String sortOrder = MediaStore.Images.Media.DATE_MODIFIED + " DESC"; // 按修改时间倒序,取最新的 String selection; String[] selectionArgs; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { // Android 10及以上,用RELATIVE_PATH定位Download文件夹 selection = MediaStore.Images.Media.RELATIVE_PATH + " LIKE ?"; selectionArgs = new String[]{"%Download%"}; } else { // Android 10以下,用DATA字段定位路径 selection = MediaStore.Images.Media.DATA + " LIKE ?"; selectionArgs = new String[]{"%Download/%"}; } // 用try-with-resources自动关闭Cursor,避免内存泄漏 try (Cursor cursor = getContentResolver().query( imageCollection, projection, selection, selectionArgs, sortOrder )) { if (cursor != null && cursor.moveToFirst()) { // 通过图片ID构建单个图片的Uri long imageId = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Images.Media._ID)); return ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, imageId); } } catch (Exception e) { e.printStackTrace(); } return null; } // 将图片加载到ImageView,兼容新旧版本 private void loadImageToView(Uri imageUri, ImageView imageView) { try { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { // Android 9及以上,推荐用ImageDecoder替代已废弃的getBitmap ImageDecoder.Source source = ImageDecoder.createSource(getContentResolver(), imageUri); Bitmap bitmap = ImageDecoder.decodeBitmap(source); imageView.setImageBitmap(bitmap); } else { // 兼容旧版本系统 Bitmap bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), imageUri); imageView.setImageBitmap(bitmap); } } catch (IOException e) { e.printStackTrace(); Toast.makeText(this, "图片加载失败", Toast.LENGTH_SHORT).show(); } }
关键细节说明
- 查询条件适配:Android 10引入分区存储后,不能直接访问文件路径,所以用
RELATIVE_PATH来定位Download文件夹;旧版本则用DATA字段匹配路径。 - 取单张图片:通过
DATE_MODIFIED DESC排序,取查询结果的第一条,也就是最新的图片;如果想取特定图片,可以修改selection条件(比如按文件名筛选)。 - 避免内存泄漏:用
try-with-resources自动关闭Cursor,不用手动调用close()。 - 废弃方法替代:
MediaStore.Images.Media.getBitmap()已经被废弃,Android 9及以上推荐用ImageDecoder来加载图片,性能更好也更稳定。
内容的提问来源于stack exchange,提问作者techtechie
相关产品推荐
相关产品推荐

