Android 12中ExifInterface获取图片位置信息失效问题咨询
问题原因
Android 10(API 29)及以上版本对媒体文件的位置元数据做了隐私加密处理,现有逻辑不满足新版本的读取规则:
- 仅在清单文件声明
ACCESS_MEDIA_LOCATION不会自动生效,该权限属于运行时权限,需要主动向用户申请授权 - 直接通过
ContentResolver.openInputStream()获取的媒体Uri输入流,系统会默认抹除所有GPS相关的Exif标签,读到的是脱敏后的文件数据,自然拿不到位置信息 - Android 9及以下版本没有这套脱敏机制,所以原有逻辑可以正常运行
修复步骤
- 先在代码中动态申请
ACCESS_MEDIA_LOCATION权限,确认用户授权后再执行位置读取逻辑 - 针对API 29及以上版本,读取Exif前先调用
MediaStore.setRequireOriginal()获取未脱敏的原始文件Uri,再基于这个Uri构造ExifInterface读取GPS字段 - 流的关闭逻辑放到Exif解析完成之后,避免解析过程中流被提前释放导致异常
修正后的可运行代码如下:
boolean hasLatLong = false; Uri imageUri = imagePickerModel.getUri(); if (Build.VERSION.SDK_INT > Build.VERSION_CODES.P) { // 校验媒体位置权限是否已授权 if (ContextCompat.checkSelfPermission(v.getContext(), Manifest.permission.ACCESS_MEDIA_LOCATION) == PackageManager.PERMISSION_GRANTED) { InputStream inputStream = null; try { // 获取未做位置脱敏的原始图片Uri Uri originalImageUri = MediaStore.setRequireOriginal(imageUri); inputStream = v.getContext().getContentResolver().openInputStream(originalImageUri); if (inputStream != null) { ExifInterface exifInterface = new ExifInterface(inputStream); hasLatLong = exifInterface.getLatLong() != null; } } catch (IOException e) { e.printStackTrace(); } finally { // 解析完成后再关闭流 if (inputStream != null) { try { inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } } } else { hasLatLong = exif.getLatLong() != null; }
注意:如果图片来自第三方私有目录、本身没有写入GPS元数据,或者用户拒绝了位置权限授权,
getLatLong()依然会返回null,需要对应做好空值兼容。
内容的提问来源于stack exchange,提问作者Krutika Chotara
相关产品推荐
相关产品推荐

