使用ExifInterface触发FileNotFoundException及图片方向异常求助
解决Firebase Storage图片方向颠倒及Exif读取FileNotFoundException问题
我之前也碰到过一模一样的问题,折腾了好一阵才搞定,给你分享几个实用的解决思路:
1. 先搞定ExifInterface的FileNotFoundException
你遇到的这个报错核心原因是:从图库拿到的content://开头的URI并不是真实的本地文件路径,而旧版的ExifInterface构造方法只认文件路径,所以直接传会抛异常。这里有两个靠谱的解决办法:
方法一:用InputStream读取Exif信息(推荐适配高版本)
Android 9(API 28)及以上的ExifInterface支持直接传入InputStream,我们可以通过ContentResolver打开URI对应的流来读取:
ContentResolver contentResolver = getContentResolver(); try (InputStream inputStream = contentResolver.openInputStream(selectedImageUri)) { if (inputStream == null) { // 处理流打开失败的情况 return; } ExifInterface exif = new ExifInterface(inputStream); // 读取图片的方向属性 int imageOrientation = exif.getAttributeInt( ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL ); // 接下来就可以用这个orientation来处理图片旋转了 } catch (IOException e) { e.printStackTrace(); }
方法二:把Content URI转成真实文件路径(适配低版本)
如果需要兼容Android 8及以下,可以写个工具方法把content URI转换为本地文件路径,注意不同厂商的图库URI格式可能略有差异,这个方法覆盖大部分场景:
public String getRealFilePath(Context context, Uri uri) { if (uri == null) return null; String[] projection = {MediaStore.Images.Media.DATA}; Cursor cursor = context.getContentResolver().query(uri, projection, null, null, null); if (cursor == null) return null; int columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); cursor.moveToFirst(); String filePath = cursor.getString(columnIndex); cursor.close(); return filePath; }
拿到路径后就可以正常初始化ExifInterface了:ExifInterface exif = new ExifInterface(filePath);
2. 根据Exif方向旋转图片,解决显示颠倒问题
读取到图片的orientation后,我们需要根据不同的方向值对图片进行旋转/翻转处理,之后再上传到Firebase Storage:
public Bitmap adjustImageOrientation(Bitmap originalBitmap, int orientation) { Matrix matrix = new Matrix(); switch (orientation) { case ExifInterface.ORIENTATION_ROTATE_90: matrix.postRotate(90); break; case ExifInterface.ORIENTATION_ROTATE_180: matrix.postRotate(180); break; case ExifInterface.ORIENTATION_ROTATE_270: matrix.postRotate(270); break; case ExifInterface.ORIENTATION_FLIP_HORIZONTAL: matrix.postScale(-1, 1); break; case ExifInterface.ORIENTATION_FLIP_VERTICAL: matrix.postScale(1, -1); break; default: return originalBitmap; } return Bitmap.createBitmap(originalBitmap, 0, 0, originalBitmap.getWidth(), originalBitmap.getHeight(), matrix, true); }
把旋转后的Bitmap转换成文件(比如压缩成JPEG)再上传,这样Firebase Storage里的图片就是正确的方向了。
3. 关于URI差一个斜杠的小细节
你提到的URI差一个斜杠其实不用太在意,这是不同图库应用返回URI的格式差异,只要我们用ContentResolver或者上面的路径转换方法处理,不管URI格式细节,都能正确读取到图片信息,不影响后续操作。
内容的提问来源于stack exchange,提问作者javacoder123
相关产品推荐
相关产品推荐

