如何通过Camera.PictureCallback获取拍摄图片的EXIF元数据
问题解答:Camera.PictureCallback获取EXIF元数据实现方案
核心结论
可以通过Camera.PictureCallback回调直接获取拍摄图像的EXIF元数据,该回调的data参数即为完整的JPEG原始字节流,包含全部EXIF信息。
具体实现代码
private Camera.PictureCallback mPicture = new Camera.PictureCallback() { @Override public void onPictureTaken(byte[] data, Camera camera) { try { // Android 7.0(API 24)及以上支持直接从输入流解析EXIF ExifInterface exif = new ExifInterface(new ByteArrayInputStream(data)); // 读取拍摄时间 String shootTime = exif.getAttribute(ExifInterface.TAG_DATETIME); // 读取经纬度信息 float[] latLongArr = new float[2]; boolean getLocationSuccess = exif.getLatLong(latLongArr); if (getLocationSuccess) { double latitude = latLongArr[0]; double longitude = latLongArr[1]; // 此处处理你获取到的经纬度逻辑 } // 可选:将图片保存到本地存储 File saveFile = new File(getExternalFilesDir(Environment.DIRECTORY_PICTURES), "shoot_" + System.currentTimeMillis() + ".jpg"); FileOutputStream fos = new FileOutputStream(saveFile); fos.write(data); fos.close(); } catch (IOException e) { e.printStackTrace(); } // 重启相机预览 camera.startPreview(); } };
注意事项
- 低版本兼容:Android 7.0以下系统的
ExifInterface不支持直接从流解析,可先将data字节数组写入临时文件,再传入文件路径构造ExifInterface进行解析。 - 定位信息写入前提:要让相机在EXIF中携带定位,需要提前申请
ACCESS_FINE_LOCATION或ACCESS_COARSE_LOCATION权限,且用户开启了定位开关,否则EXIF不会包含经纬度字段。 - 优化方案:如果默认拍摄的图片不带定位信息,可在拍照前主动给Camera实例设置定位参数,该方案仅需获取一次定位即可,无需持续监听,效率远高于持续使用LocationListener:
// 仅需在相机初始化后/拍照前调用一次即可 Location latestLocation = ...; // 你获取到的最新定位信息 Camera.Parameters params = camera.getParameters(); params.setGpsLatitude(latestLocation.getLatitude()); params.setGpsLongitude(latestLocation.getLongitude()); params.setGpsTimestamp(latestLocation.getTime()); camera.setParameters(params); - 兜底逻辑:若用户完全关闭定位,无论从LocationListener还是EXIF都无法获取有效经纬度,建议在此场景下提示用户开启定位功能。
内容的提问来源于stack exchange,提问作者stackved12
相关产品推荐
相关产品推荐

