Android中如何使用setImageDrawable()加载不同路径图片?
嘿,我来帮你搞定这个报错!你遇到的BitmapFactory: Unable to decode stream: java.io.FileNotFoundException,大概率是路径、权限或者文件本身的问题,咱们一步步排查:
1. 先确认文件路径和实际文件是否匹配
首先得搞清楚,代码里写的路径对应的文件是不是真的存在。你可以先把要加载的文件路径打印出来:
File targetFile = new File("/storage/emulated/0/Sensia_Sniffer/18_04_2018/18_56_18_photo.JPEG"); Log.d("ImagePathCheck", "目标文件路径:" + targetFile.getAbsolutePath());
然后打开Android Studio的Device File Explorer,顺着这个路径找过去,看看:
- 文件是不是真的在这个目录里
- 文件名有没有大小写错误(Android文件系统是区分大小写的,比如
photo.JPEG和photo.jpeg是两个不同的文件) - 路径里的文件夹名称有没有写错(比如
Sensia_Sniffer是不是拼对了)
2. 检查存储访问权限
你访问的/storage/emulated/0/...属于外部存储(不是app私有的内部存储),所以必须确保你有访问外部存储的权限:
静态权限声明
在AndroidManifest.xml里添加权限:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <!-- 如果是Android 13及以上,还需要添加这个 --> <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
动态权限申请
Android 6.0(API 23)及以上,光有静态声明还不够,得在代码里动态申请权限:
// 检查权限是否已授予 if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { // 申请权限 ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 1001); }
分区存储适配(Android 10+)
从Android 10(API 29)开始,系统默认启用了分区存储,直接访问外部存储的自定义目录会被限制。如果还没适配分区存储,可以先在AndroidManifest.xml的<application>标签里加一句兼容代码:
<application ... android:requestLegacyExternalStorage="true">
当然,长期来看还是建议适配MediaStore API来访问图片,这样更符合系统规范。
3. 确认文件是否真的存在
在加载图片前,先判断文件是否存在,避免报错:
File imageFile = new File("/storage/emulated/0/Sensia_Sniffer/18_04_2018/18_56_18_photo.JPEG"); if (imageFile.exists() && imageFile.isFile()) { // 文件存在,加载图片 Bitmap bitmap = BitmapFactory.decodeFile(imageFile.getAbsolutePath()); holder.picture.setImageBitmap(bitmap); } else { Log.e("ImageError", "文件不存在或者不是文件:" + imageFile.getAbsolutePath()); // 这里可以设置一张默认占位图 holder.picture.setImageDrawable(getResources().getDrawable(R.drawable.default_image)); }
如果这里打印了“文件不存在”,那你得检查保存图片的代码是不是有问题——比如保存路径写错了,或者保存时没有成功写入(比如IO异常没处理)。
4. 试试用图片加载库简化操作
自己用BitmapFactory加载不仅要处理权限、路径,还要考虑内存溢出的问题。推荐用Glide或者Picasso这类成熟的图片加载库,它们会帮你搞定所有细节:
比如用Glide的话,代码非常简洁:
Glide.with(context) .load(imageFile) .placeholder(R.drawable.loading_image) // 加载时的占位图 .error(R.drawable.error_image) // 加载失败时的图 .into(holder.picture);
Glide会自动处理权限检查、文件存在性判断、内存缓存等问题,省心很多。
先从路径和权限这两个最常见的原因排查,应该就能解决问题啦!
内容的提问来源于stack exchange,提问作者Iván de la Cruz




