Android鹰眼轨迹追踪
先看下实现效果:
鹰眼是一套轨迹管理服务,接入该服务后,可追踪车辆/人员等运动物体,实现实时定位、轨迹追踪和轨迹存储查询等功能。基于鹰眼提供的接口和云端服务,可以迅速构建一套完全属于您自己的完整、精准且高性能的轨迹管理系统,可应用于车队管理、人员管理等领域。具体请查看官网介绍。
这篇文章就讲一下如何在Android App中实现轨迹追踪,既然要追踪轨迹,肯定得先获取这个设备的一系列轨迹点,这就需要我们在终端集成鹰眼服务。我们以Android手机为例,集成鹰眼轨迹SDK后,App将会按照我们设定的频率主动采集实时轨迹。
什么是Android鹰眼轨迹SDK?
鹰眼轨迹是一套基于Android 2.1及以上版本设备的应用程序接口, 可以通过该接口实现轨迹追踪功能:
- 轨迹追踪:按照设定的频率主动采集实时轨迹
- 轨迹存储:云端实现海量轨迹数据存储
- 轨迹查询:查询被追踪者实时位置、历史轨迹和里程
- 轨迹纠偏:云端对轨迹进行实时去噪、绑路、抽稀处理,解决轨迹偏移问题
- 地理围栏:当被追踪者进出一定范围(圆形、多边形、线型、行政区)的虚拟地理区域时,监控者可以接收到自动报警通知
- 图像存储:支持随轨迹上传、存储和查询图像文件
接入鹰眼服务
开发工具:Android Studio
一. 获取AK
使用百度鹰眼Android SDK,需要先获取服务**(AK),申请地址:http://lbsyun.baidu.com/apiconsole/key,申请时需要用到开发版SHA1值和发布版SHA1值,详细教程可查看:Android获取SHA1(开发版和发布版)
二. 创建鹰眼服务
1. 创建服务
进入鹰眼轨迹管理平台,点击"创建服务"按钮,在弹窗中填写信息后完成服务创建。
2. 获取 service_id
创建服务成功后即可列表左侧的"系统 ID(service_id)",如:217548,即为访问该service的唯一标识,在后续的接口调用中均要使用。
三. 接入鹰眼服务
1. 配置库文件
SDK下载地址:http://lbsyun.baidu.com/index.php?title=android-yingyan/sdkandev-download
下载的压缩包解压后将jar包和so文件复制到项目lib目录下,并在app build.gradle的android标签中加入如下代码并Sync Now。
sourceSets {
main {
jniLibs.srcDirs = ['libs']
}
}
2. 设置AndroidManifest.xml
<service
android:name="com.baidu.trace.LBSTraceService"
android:enabled="true"
android:process=":remote"/>
<meta-data
android:name="com.baidu.lbsapi.API_KEY"
android:value="上面申请的ak值" />
3. 加入相关权限
<!-- 这个权限用于进行网络定位-->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<!-- 这个权限用于访问GPS定位-->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<!-- 用于访问wifi网络信息,wifi信息会用于进行网络定位-->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<!-- 获取运营商信息,用于支持提供运营商信息相关的接口-->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<!-- 这个权限用于获取wifi的获取权限,wifi信息会用来进行网络定位-->
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
<!-- 写入扩展存储,向扩展卡写入数据,用于写入对象存储BOS数据-->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<!-- 访问网络,网络定位需要上网-->
<uses-permission android:name="android.permission.INTERNET" />
<!-- Android O之后开启前台服务需要申请该权限 -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<!-- Android Q之后,后台定位需要申请该权限 -->
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<!-- 以下不是鹰眼SDK需要的基础权限,可选 -->
<!-- 用于加快GPS首次定位,可选权限,非必须-->
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS"/>
<!-- 用于Android M及以上系统,申请加入忽略电池优化白名单,可选权限,非必须-->
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/>
4. 初始化轨迹服务
// 轨迹服务ID
long serviceId = 0;
// 设备标识
String entityName = "myTrace";
// 是否需要对象存储服务,默认为:false,关闭对象存储服务。注:鹰眼 Android SDK v3.0以上版本支持随轨迹上传图像等对象数据,若需使用此功能,该参数需设为 true,且需导入bos-android-sdk-1.0.2.jar。
boolean isNeedObjectStorage = false;
// 初始化轨迹服务
Trace mTrace = new Trace(serviceId, entityName, isNeedObjectStorage);
// 初始化轨迹服务客户端
LBSTraceClient mTraceClient = new LBSTraceClient(getApplicationContext());
5. 设置定位和回传周期
鹰眼轨迹数据传输采取定期打包回传的方式,以节省流量。开发者可以自定义定位频率和打包回传频率,频率可设置范围为:2~300秒。例如:定位频率为5s,打包回传频率为10s,则2次定位后打包回传一次。
// 定位周期(单位:秒)
int gatherInterval = 5;
// 打包回传周期(单位:秒)
int packInterval = 10;
// 设置定位和打包周期
mTraceClient.setInterval(gatherInterval, packInterval);
6. 初始化监听器
// 初始化轨迹服务监听器
OnTraceListener mTraceListener = new OnTraceListener() {
/**
* 绑定服务回调接口
* @param i 状态码
* @param s 消息 0:成功 1:失败
*/
@Override
public void onBindServiceCallback(int i, String s) {
Log.e(TAG,"绑定服务回调");
Log.e(TAG,i+"");
Log.e(TAG,s+"");
}
/**
* 开启服务回调接口
* @param status 状态码
* @param message 消息
* <pre>0:成功 </pre>
* <pre>10000:请求发送失败</pre>
* <pre>10001:服务开启失败</pre>
* <pre>10002:参数错误</pre>
* <pre>10003:网络连接失败</pre>
* <pre>10004:网络未开启</pre>
* <pre>10005:服务正在开启</pre>
* <pre>10006:服务已开启</pre>
*/
@Override
public void onStartTraceCallback(int status, String message) {
Log.e(TAG,"开启服务回调");
Log.e(TAG,status+"");
Log.e(TAG,message+"");
}
/**
* 停止服务回调接口
* @param status 状态码
* @param message 消息
* <pre>0:成功</pre>
* <pre>11000:请求发送失败</pre>
* <pre>11001:服务停止失败</pre>
* <pre>11002:服务未开启</pre>
* <pre>11003:服务正在停止</pre>
*/
@Override
public void onStopTraceCallback(int status, String message) {
Log.e(TAG,"停止服务回调");
Log.e(TAG,status+"");
Log.e(TAG,message+"");
}
/**
* 开启采集回调接口
* @param status 状态码
* @param message 消息
* <pre>0:成功</pre>
* <pre>12000:请求发送失败</pre>
* <pre>12001:采集开启失败</pre>
* <pre>12002:服务未开启</pre>
*/
@Override
public void onStartGatherCallback(int status, String message) {
Log.e(TAG,"开启采集回调");
Log.e(TAG,status+"");
Log.e(TAG,message+"");
}
/**
* 停止采集回调接口
* @param status 状态码
* @param message 消息
* <pre>0:成功</pre>
* <pre>13000:请求发送失败</pre>
* <pre>13001:采集停止失败</pre>
* <pre>13002:服务未开启</pre>
*/
@Override
public void onStopGatherCallback(int status, String message) {
Log.e(TAG,"停止采集回调");
Log.e(TAG,status+"");
Log.e(TAG,message+"");
}
/**
* 推送消息回调接口
*
* @param messageNo 状态码
* @param message 消息
* <pre>0x01:配置下发</pre>
* <pre>0x02:语音消息</pre>
* <pre>0x03:服务端围栏报警消息</pre>
* <pre>0x04:本地围栏报警消息</pre>
* <pre>0x05~0x40:系统预留</pre>
* <pre>0x41~0xFF:开发者自定义</pre>
*/
@Override
public void onPushCallback(byte messageNo, PushMessage message) {
Log.e(TAG,"推送消息回调");
Log.e(TAG,messageNo+"");
Log.e(TAG,message+"");
}
@Override
public void onInitBOSCallback(int i, String s) {
}
};
7. 开启轨迹追踪
开启轨迹追踪需要进行以下两步操作:
(1)开启鹰眼服务,启动鹰眼 service
// 开启服务
mTraceClient.startTrace(mTrace, mTraceListener);
(2)开启轨迹采集,启动轨迹追踪。
// 开启采集
mTraceClient.startGather(mTraceListener);
至此,正式开启轨迹追踪。
8. 结束轨迹追踪
结束轨迹追踪时,可以有两种选择:
(1)停止轨迹服务:此方法将同时停止轨迹服务和轨迹采集,完全结束鹰眼轨迹服务。若需再次启动轨迹追踪,需重新启动服务和轨迹采集,示例代码如下:
// 停止服务
mTraceClient.stopTrace(mTrace, mTraceListener);
(2)停止轨迹采集:此方法将停止轨迹采集,但不停止轨迹服务(即,不再采集轨迹点了,但鹰眼 service 还存活)。
// 停止采集
mTraceClient.stopGather(mTraceListener);
>接入鹰眼服务按照官方文档很容易实现,在实际项目中其实经常需要后台运行,所以可以将这些逻辑放到 service 中来实现,然后做相应的服务保活,让其在后台进行轨迹采集。而像轨迹服务、轨迹服务客户端这些对象或变量可以放到 application 中,以方便在整个应用中使用。
四、自定义属性上传
1. 轨迹点自定义属性数据上传
顾名思义,轨迹点自定义属性数据上传就是针对每一个轨迹点增加上传的自定义属性字段,轨迹中的每个位置点可拥有一系列开发者自定义的描述字段,如汽车的电量、发动机转速等,用以记录行程中的实时状态信息。
为实现自定义属性数据上传,开发者须重写OnCustomAttributeListener监听器中的onTrackAttributeCallback()接口,调用 LBSTraceClient.setOnCustomAttributeListener()方法设置自定义属性监听器,并按照设置的定位周期更新onTrackAttributeCallback()的返回值,示例如下:
// 为实现自定义属性数据上传,须重写OnCustomAttributeListener监听器中的onTrackAttributeCallback()接口
mTraceClient.setOnCustomAttributeListener(new OnCustomAttributeListener() {
@Override
public Map<String, String> onTrackAttributeCallback() {
Map<String, String> map = new HashMap<String, String>();
map.put("key1", "value1");
map.put("key2", "value2");
return map;
}
//l - 回调时定位点的时间戳(毫秒)
@Override
public Map<String, String> onTrackAttributeCallback(long l) {
return null;
}
});
SDK每采集一次轨迹,便会自动回调onTrackAttributeCallback()接口,获取属性值并写入当前轨迹点的属性字段中。onTrackAttributeCallback()的返回值是Map<String, String>类型,每个对象都是一个<key,value>对,其中key为自定义字段名称,value为值。
2. 自定义entity属性上传
这里先说明一下,上面的轨迹点自定义属性上传指的是每一个轨迹点增加上传的自定义属性字段。我们目前每一个设备有一个设备标识,也就是在初始化轨迹服务传入的 entityName ,那如果我们还需要上传当前这个entity的其他属性,比如用户姓名、年龄或性别等该如何做呢?
方式一:通过调用 addEntity() 方法主动添加
这种方式等于我们主动添加一个entity,也就不需要我们在初始化轨迹服务传入 entityName ,addEntity()方法需要传入两个参数,具体使用方式可以看鹰眼SDK的API文档,示例如下:
AddEntityRequest request = new AddEntityRequest();
request.setServiceId(serviceId);
request.setEntityName(entityName);
Map<String, String> columns = new HashMap<String, String>();
columns.put("USER_ID", "1001");
columns.put("USER_SEX", "男");
columns.put("ACC_NBR", "1234567890");
request.setColumns(columns);
mTraceClient.addEntity(request, new OnEntityListener() {
@Override
public void onAddEntityCallback(AddEntityResponse addEntityResponse) {
super.onAddEntityCallback(addEntityResponse);
}
});
方式二:通过调用 updateEntity() 方法指定自定义属性
如果我们在初始化轨迹服务传入了entityName ,服务端将会自动创建以entityName命名的entity。由于服务端自动创建的entity不包含自定义属性的值,若需要指定entity自定义属性,需要再调用updateEntity()方法,通过columnKey字段指定自定义属性的值。
示例如下:
//自定义entity属性上传
UpdateEntityRequest updateEntityRequest = new UpdateEntityRequest();
updateEntityRequest.setServiceId(serviceId);
updateEntityRequest.setEntityName(entityName);
Map<String, String> columns = new HashMap<String, String>();
columns.put("USER_ID", "1001");
columns.put("USER_SEX", "男");
columns.put("ACC_NBR", "1234567890");
updateEntityRequest.setColumns(columns);
mTraceClient.updateEntity(updateEntityRequest, new OnEntityListener() {
@Override
public void onAddEntityCallback(AddEntityResponse addEntityResponse) {
super.onAddEntityCallback(addEntityResponse);
}
});
最后附上Demo地址,GitHub:https://github.com/yangxch/YingYan
原创不易,转载请注明出处。
上一篇: 关于四波段影像的显示问题