Camera拍照录像保存位置信息

一、修改记录

版本修改日期作者修改内容
v1.02021.09.03罗然初版

二、概述

用户日常拍照或者录像,在某些场景下可能会需要在图片或者视频详情下面显示具体的位置信息(经纬度),获取位置信息目前有两种比较常用的方案:

  1. GPS 定位
  2. 网络定位

GPS 定位相比于网络定位来说优缺点都很明显,优点就是定位准确度、精度比较高,缺点则是需要在室外比较空旷的环境下才能获取到位置信息,而网络定位则没有这方面的限制,只需要网络畅通就可以获取到位置信息。比较好的方案就是优先使用网络定位,网络不可用的情况下采用 GPS 定位。

三、图片位置信息存储

图片存储位置信息通常有两种方案:

  1. 位置信息存储在 Media 数据库中,图库通过查询数据库获取到经纬度字段进行解析
  2. 位置信息存储在图片的 Exif 信息里面,通过 ExifInterface 接口解析出经纬度进行解析

3.1 存储 Media 数据库

ContentValues values = new ContentValues();
values.put(MediaStore.Images.ImageColumns.LATITUDE, latitude);
values.put(MediaStore.Images.ImageColumns.LONGITUDE,  longitude);
mContentResolver.insert(Images.Media.EXTERNAL_CONTENT_URI, values);

MediaStore 的内部类 Images 包含两个字段,分别是 LATITUDELONGITUDELATITUDE 用来存储纬度,LONGITUDE 用来存储经度,把获取到的经纬度存储到对应的字段即可。不过这个方案在 Android Q 平台后已经无效了:

/**
* The latitude where the image was captured.
*
* @deprecated location details are no longer indexed for privacy
*             reasons, and this value is now always {@code null}.
*             You can still manually obtain location metadata using
*             {@link ExifInterface#getLatLong(float[])}.
*/
@Deprecated
@Column(value = Cursor.FIELD_TYPE_FLOAT, readOnly = true)
public static final String LATITUDE = "latitude";

/**
* The longitude where the image was captured.
*
* @deprecated location details are no longer indexed for privacy
*             reasons, and this value is now always {@code null}.
*             You can still manually obtain location metadata using
*             {@link ExifInterface#getLatLong(float[])}.
*/
@Deprecated
@Column(value = Cursor.FIELD_TYPE_FLOAT, readOnly = true)
public static final String LONGITUDE = "longitude";

查阅 MediaStore 源码可以看到,LATITUDE 和 LONGITUDE 两个字段已经被加上了 @Deprecated 注解,也就是说谷歌已经不推荐开发者使用这两个字段了,看到这里可能还觉得有点希望,毕竟只是不推荐使用,如果使用的话应该也不会有什么问题吧,真正绝望的是 readOnly = true,也就是说字段可读不可写,最后的一点希望破灭了。难道没有别的办法了吗?应该不是,以谷歌的尿性,通常弃用一个旧方案的时候应该会提供一个新的方案,查看字段注释果不其然:

location details are no longer indexed for privacy
reasons, and this value is now always {@code null}.
You can still manually obtain location metadata using
{@link ExifInterface#getLatLong(float[])}.

也就是我们上面说的存储位置信息的第二个方案,可以通过 ExifInterface 接口存储位置信息到图片的 Exif 信息里面。

3.2 存储 Exif 信息

存储位置信息到图片的 Exif 里面有两种方法:

3.2.1 ExifInterface

ExifInterface exifInterface = new ExifInterface();
exifInterface.addGpsTags(latitude, longitude);
exifInterface.writeExif(request.mData, out);

3.2.2 CaptureRequest.JPEG_GPS_LOCATION

Location location = new Location("");
location.setLatitude(locationProxy.getCurLatitude());
location.setLongitude(locationProxy.getCurLongitude());
builder.set(CaptureRequest.JPEG_GPS_LOCATION, location);

四、视频位置信息存储

4.1 MediaRecorder 录制

Camera 应用一般都是采用 MediaRecorder 类录像,在这种场景下,只需要调用 MediaRecorder的 setLocation 方法就可以保存视频的位置信息:

mMediaRecorder.setLocation((float) spec.location.getLatitude(), (float) spec.location.getLongitude());

4.2 MediaCodec + AudioRecorder 录制

在某些场景下,Camera 会用到 MediaCodec 采集视频数据,AudioRecorder 采集音频数据,然后通过 MediaMuxer 进行音视频合成视频文件,这种场景下需要调用 MediaMuxer 类的 setLocation 方法来保存视频的位置信息:

public void setLocation(float latitude, float longitude) 

需要注意的是这个方法需要在 MediaMuxer 类的 start 方法之前调用,下面是 Google 文档的说明:

Set and store the geodata (latitude and longitude) in the output file. This method should be called before start().

五、参考文档

ExifInterface
MediaMuxer

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
Camera2是Android系统中用于相机功能的API。它提供了一套强大的接口,可以控制相机的各种参数,并支持拍照录像功能。 在使用Camera2进行拍照时,你需要以下步骤: 1. 获取CameraManager实例:通过调用`getSystemService(Context.CAMERA_SERVICE)`方法获取CameraManager的实例。 2. 获取相机ID:通过调用`getCameraIdList()`方法获取可用的相机ID列表,选择你要使用的相机ID。 3. 打开相机:通过调用`openCamera()`方法打开选定的相机。 4. 创建拍照请求:创建一个CaptureRequest.Builder对象,并设置相应参数,例如图像输出格式、图像尺寸等。 5. 创建拍照会话:通过调用`createCaptureSession()`方法创建一个CameraCaptureSession对象。 6. 启动拍照:通过调用`capture()`方法开始拍照,并传入拍照请求对象。 在使用Camera2进行录像时,你可以按照以下步骤操作: 1. 获取CameraManager实例:同样通过调用`getSystemService(Context.CAMERA_SERVICE)`方法获取CameraManager的实例。 2. 获取相机ID:同样通过调用`getCameraIdList()`方法获取可用的相机ID列表,选择你要使用的相机ID。 3. 打开相机:同样通过调用`openCamera()`方法打开选定的相机。 4. 创建录像请求:创建一个CaptureRequest.Builder对象,并设置相应参数,例如视频输出格式、视频尺寸、预览界面等。 5. 创建录像会话:通过调用`createCaptureSession()`方法创建一个CameraCaptureSession对象。 6. 启动录像:通过调用`setRepeatingRequest()`方法开始录像,并传入录像请求对象。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

酱油码农

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值