Android中使用ExifInterface获取图片旋转角度遇FileNotFoundException问题
解决ExifInterface的FileNotFoundException问题(含非ASCII路径场景)
这个问题我之前处理过好几次!核心问题主要出在非ASCII字符路径的兼容性和Uri转路径的坑上,咱们一步步拆解:
1. 旧版ExifInterface不支持带非英文字符的路径
Android 7.0(API 24)之前系统自带的ExifInterface有编码缺陷,当文件路径包含韩文、中文这类非ASCII字符时,会直接触发FileNotFoundException。
解决办法分两种情况:
- API 24及以上:直接使用
ExifInterface(InputStream)构造方法,通过ContentResolver获取文件输入流,完全绕开路径问题:ContentResolver resolver = getActivity().getContentResolver(); InputStream inputStream = resolver.openInputStream(data.getData()); if (inputStream != null) { ExifInterface exif = new ExifInterface(inputStream); // 这里可以获取旋转角度等信息 inputStream.close(); // 记得关闭流 } - 需要兼容低版本:改用AndroidX库中的
ExifInterface,它修复了路径编码问题,支持带非ASCII字符的路径:
先在build.gradle中添加依赖:
然后代码中替换导入:implementation "androidx.exifinterface:exifinterface:1.3.6"import androidx.exifinterface.media.ExifInterface; ... // 直接用你的img_path即可 ExifInterface exif = new ExifInterface(img_path);
2. 检查Uri转真实路径的逻辑是否正确
你用到的getImagePathToUri方法如果实现不当,在不同Android版本(尤其是Android 10+的分区存储机制下)可能会返回无效路径。其实现在更推荐的做法是避免直接获取真实路径,用ContentResolver操作文件(比如上面的InputStream方式),这样既适配新系统,又不会踩路径编码的坑。
3. 别忘了权限检查
如果你的App运行在Android 6.0(API 23)及以上,要确保已经动态申请了READ_EXTERNAL_STORAGE权限,否则即使路径正确,也会因为权限不足无法读取文件。
修正后的完整onActivityResult示例
public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (resultCode != getActivity().RESULT_OK) return; if (requestCode == REQ_CODE_SELECT_IMAGE) { try { ContentResolver resolver = getActivity().getContentResolver(); InputStream inputStream = resolver.openInputStream(data.getData()); if (inputStream == null) return; ExifInterface exif; // 根据系统版本选择合适的ExifInterface实现 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { exif = new ExifInterface(inputStream); } else { exif = new androidx.exifinterface.media.ExifInterface(inputStream); } // 获取图片旋转角度 int orientation = exif.getAttributeInt( ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL ); int rotateAngle = 0; switch (orientation) { case ExifInterface.ORIENTATION_ROTATE_90: rotateAngle = 90; break; case ExifInterface.ORIENTATION_ROTATE_180: rotateAngle = 180; break; case ExifInterface.ORIENTATION_ROTATE_270: rotateAngle = 270; break; } inputStream.close(); // 这里可以用rotateAngle做图片旋转处理 } catch (IOException e) { e.printStackTrace(); } } }
内容的提问来源于stack exchange,提问作者Adrian
相关产品推荐
相关产品推荐

