Android百度地图(五):百度地图鹰眼sdk监控进出地理围栏(区域)

转载、引用请标明出处
http://www.jianshu.com/p/db11ae2bad4f
本文出自zhh_happig的简书博客,谢谢

Android百度地图(一):百度地图定位sdk 类方法参数、定位原理详细介绍
Android百度地图(二):百度地图sdk显示位置点、图层绘制
Android百度地图(三):百度地图画运动轨迹及图层点击事件处理
Android百度地图(四):百度地图运动轨迹纠偏、去噪、绑路之百度鹰眼sdk服务
Android百度地图(六):百度地图POI检索,行政区边界、公交、线路规划查询,地理编码介绍

上篇文章介绍利用百度鹰眼sdk对运动轨迹做纠偏、去噪、绑路处理。本篇将介绍鹰眼sdk的另一个功能——围栏,围栏的主要功能:将根据轨迹点判断手机终端是否进出围栏,并实时推送报警。应用场景:如进入目的地提醒、监控对象离开指定活动范围出发警报等等。

一 围栏简介

围栏类型
圆形围栏:进出圆形范围则推送报警
多边形围栏:进出多边形围栏则推送报警
线型围栏:偏离或回到设定路线则推送报警
行政区围栏:传入行政区名称,创建以行政区边界为界的围栏,进出报警

除围栏形状的区分,还分为:
(1)客户端围栏:围栏的创建、计算和报警均在本地鹰眼SDK完成,无需联网即可完成围栏运算,注:目前客户端围栏只支持圆形围栏
(2)服务端围栏:围栏的创建、计算和报警的发起都在服务端完成,依赖于轨迹点上传至服务端才能进行围栏进算。

创建圆形围栏和多边形围栏在地图上显示的效果如下

《Android百度地图(五):百度地图鹰眼sdk监控进出地理围栏(区域)》

二 创建围栏api详解

1.流程图

《Android百度地图(五):百度地图鹰眼sdk监控进出地理围栏(区域)》

2.初始化客户端采集轨迹数据

请先申请apikey和serviceId,具体工程配置请见篇头百度地图(四)文章中描述

//以下都是伪代码
/**
* 初始化鹰眼sdk客户端,
*/
LBSTraceClient mClient = mClient = new LBSTraceClient(mContext);
//初始化鹰眼服务端,serviceId:服务端唯一id,entityName:监控的对象,可以是手机设备唯一标识
Trace mTrace = new Trace(serviceId, entityName);
mClient.startTrace(trackApp.mTrace, traceListener);//开始服务
trackApp.mClient.startGather(traceListener);//开启采集

//轨迹服务监听器
private OnTraceListener traceListener = new OnTraceListener() {
     /**
     * 推送消息回调接口
     * @param messageType 状态码
     * 0x01:配置下发,0x02:语音消息,0x03:服务端围栏报警消息,0x04:本地围栏报警消息    
     */
     @Override
     public void onPushCallback(byte messageType, PushMessage pushMessage) {
             if (messageType < 0x03 || messageType > 0x04) {
                    return;
             }
             /**
             * 获取报警推送消息
             */
             FenceAlarmPushInfo alarmPushInfo = pushMessage.getFenceAlarmPushInfo();
             alarmPushInfo.getFenceId();//获取围栏id
             alarmPushInfo.getMonitoredPerson();//获取监控对象标识
             alarmPushInfo.getFenceName();//获取围栏名称
             alarmPushInfo.getPrePoint();//获取上一个点经度信息
             AlarmPoint alarmPoin = alarmPushInfo.getCurrentPoint();//获取报警点经纬度等信息
             alarmPoin.getCreateTime();//获取此位置上传到服务端时间
             alarmPoin.getLocTime();//获取定位产生的原始时间

             if(alarmPushInfo.getMonitoredAction() == MonitoredAction.enter){//动作类型
                //进入围栏
             }else if(alarmPushInfo.getMonitoredAction() == MonitoredAction.exit){
                //离开围栏
             }
     }
     //......这里省略此接口的其他方法
};

更多轨迹采集api详解请阅读篇头百度地图(四)文章

3.创建围栏

/**
* 创建客户端圆形围栏,注:目前客户端围栏只支持圆形围栏
* tag - 这次请求的唯一标识
* serviceId -轨迹服务ID
* fenceName - 围栏名称
* entityName- 监控对象唯一标识,如果是手机,请用手机的唯一id
* center - 围栏圆心
* radius - 围栏半径
* denoise - 围栏去噪精度,gps定位和网络定位都存在精度误差,会造成围栏误报警;
            如设置denoise=30,则定位精度大于30米的轨迹点都不会参与围栏计算。
            平均精度参考:GPS定位精度均值为15米,WIFI定位精度均值为40米,基站定位精度均值为300米。
* coordType - 坐标类型
*/
CreateFenceRequest request = CreateFenceRequest.buildLocalCircleRequest(tag, serviceId, fenceName,
                                                  entityName, circleCenter, radius, denoise, CoordType.bd09ll);
/**
* 创建服务端圆形围栏
* 参数与客户端圆形围栏一样
*/
request = CreateFenceRequest.buildServerCircleRequest(tag, serviceId, fenceName,
                                                  entityName, circleCenter, radius, denoise, CoordType.bd09ll);

/**
* 创建服务端多边形围栏
* vertexes - 顶点坐标集合,List<com.baidu.trace.model.LatLng>
* 顶点可设置地图点击监听获取,mBaiduMap.setOnMapClickListener
*/
request = CreateFenceRequest.buildServerPolygonRequest(tag,serviceId, fenceName,
                               entityName, vertexes, denoise, CoordType.bd09ll);

/**
* 创建服务端线形围栏
* vertexes - 顶点坐标集合,List<com.baidu.trace.model.LatLng>
* offset - 偏离路线的垂直距离,偏离大于offset 报警
*/
request = CreateFenceRequest.buildServerPolylineRequest(tag,serviceId, fenceName, 
                               entityName, vertexes, offset, denoise, CoordType.bd09ll);

/**
* 创建服务端行政区围栏
* district:行政区名称,注意写全,如北京市西城区
*/
request = CreateFenceRequest.buildServerDistrictRequest(tag,serviceId, fenceName, entityName, 
                               district, denoise);

//发起创建围栏请求
mClient.createFence(request, fenceListener);

4.围栏操作的监听器

OnFenceListener fenceListener = new OnFenceListener() {
      
     @Override
     public void onCreateFenceCallback(CreateFenceResponse response) {
         //创建围栏响应结果,能获取围栏的一些信息
         if(StatusCodes.SUCCESS != response.getStatus()){
              return;
         }
         response.getTag();//请求标识
         response.getDistrict();//获取行政区名称
         response.getFenceId();//创建的围栏id
         response.getFenceShape();//围栏形状
         response.getFenceType();//围栏类型(本地围栏、服务端围栏)
         //...方法不一一列举了,比较简单
     }

     @Override
     public void onUpdateFenceCallback(UpdateFenceResponse response) {
         //更新围栏响应结果
         //...
     }

     @Override
     public void onDeleteFenceCallback(DeleteFenceResponse response) {
         //删除围栏响应结果
         response.getFenceIds();//获取删除的围栏id
         //...
     }

     @Override
     public void onFenceListCallback(FenceListResponse response) {
         //获取围栏列表响应结果
         response.getSize();//围栏个数
         List<FenceInfo> fenceInfos = response.getFenceInfos();//获取围栏信息列表
         for (FenceInfo fenceInfo : fenceInfos) {
            switch (fenceInfo.getFenceShape()) {//判断围栏形状
                case circle://圆形
                    CircleFence circleFence = fenceInfo.getCircleFence();
                    circleFence.getFenceId();
                    circleFence.getCenter();
                    circleFence.getRadius();
                    circleFence.getDenoise();//去噪精度
                    circleFence.getMonitoredPerson();//监控设备的唯一标识
                    //...获取圆心和半径就可以在地图上画圆形图层
                    break;
                case polygon://多边形
                    PolygonFence polygonFence = fenceInfo.getPolygonFence();
                    //获取多边形顶点集合
                    List<com.baidu.trace.model.LatLng> polygonVertexes = polygonFence.getVertexes();
                    //...获取顶点坐标可以在地图上画多边形图层
                    break;
                case polyline://线形
                    PolylineFence polylineFence = fenceInfo.getPolylineFence(); 
                    //获取线形顶点集合
                    List<com.baidu.trace.model.LatLng> polylineVertexes = polylineFence.getVertexes();
                    //...
                    break;
                case district:
                    DistrictFence districtFence = fenceInfo.getDistrictFence();
                    districtFence.getDistrict();//获取行政区名称
                    //...注:行政区围栏并能像多边形一样返回定点集合,行政区范围很大,点很多...,
                    //如果想获取行政区的边界点坐标结合,请使用baidumapapi_search_v4_3_1.jar中DistrictSearch类
                    break;
            }
        }
     }

    @Override
    public void onMonitoredStatusCallback(MonitoredStatusResponse response) {
        //查询监控对象状态响应结果
        List<MonitoredStatusInfo> monitoredStatusInfos = response.getMonitoredStatusInfos();
        for (MonitoredStatusInfo monitoredStatusInfo : monitoredStatusInfos){
             monitoredStatusInfo.getFenceId();
             MonitoredStatus status = monitoredStatusInfo.getMonitoredStatus();//获取状态
             switch (status){
                   case in:
                        //监控的设备在围栏内
                        break;
                   case out:
                        //监控的设备在围栏外
                        break;
                   case unknown:
                        //监控的设备状态未知
                        break;    
             }
        }
    }

    @Override
    public void onMonitoredStatusByLocationCallback(MonitoredStatusByLocationResponse response){
        //查询监控对象在指定位置的状态响应结果,api同onMonitoredStatusCallback
    }

    @Override
    public void onHistoryAlarmCallback(HistoryAlarmResponse response) {
        //查询围栏历史报警信息响应结果
        //获取报警信息列表,FenceAlarmInfo继承FenceAlarmPushInfo
        List<FenceAlarmInfo> fenceAlarmInfos = response.getFenceAlarmInfos();
    }
};

创建围栏成功后,服务端时刻计算最新采集的轨迹点与围栏的地理关系,一旦进出围栏报警信息会通过OnTraceListener.onPushCallback方法回到给客户端,你可以在这里进行自己的业务了。

判断轨迹点进入围栏、离开围栏,推送报警效果如下

《Android百度地图(五):百度地图鹰眼sdk监控进出地理围栏(区域)》 进入围栏-图a

《Android百度地图(五):百度地图鹰眼sdk监控进出地理围栏(区域)》 离开围栏-图b

如果你没有在地图上画图层的需求,完全不必像图a、图b那样,只需要创建围栏,开启采集数据,等待报警信息的回调就可以了。

三 围栏查询、删除等api详解

以下api方法中的参数详见3中描述,基本一样;围栏监听器同用一个fenceListener,参见4中描述。

5.更新围栏

/**
* 以更新服务端圆形围栏为例,其他围栏同理
* fenceId:围栏id
* 更新围栏传入新的参数即可,如圆形围栏传入新的半径和圆心坐标
*/
UpdateFenceRequest updateRequest = UpdateFenceRequest.buildServerCircleRequest(tag, serviceId, fenceId, 
                                              fenceName, entityName, center, radius, denoise, coordType);
//发起更新围栏请求
mClient.updateFence(updateRequest , fenceListener);

6.删除围栏

/**
* 以删除服务端围栏为例
* deleteFenceIds:要删除的服务端围栏编号列表,List<Long>
*/
DeleteFenceRequest deleteRequest = DeleteFenceRequest.buildServerRequest(tag,serviceId, entityName, deleteFenceIds);
//发起删除围栏请求
mClient.deleteFence(deleteRequest , fenceListener);

7.查询围栏列表

/**
* 以查询服务端围栏为例
* fenceIds:服务端围栏编号列表,List<Long>,如传入null,表示查询所有围栏
*/
FenceListRequest request = FenceListRequest.buildServerRequest(tag,serviceId, entityName, fenceIds,CoordType.bd09ll);
//发起查询围栏请求
mClient.queryFenceList(request, fenceListener);

8.查询指定监控对象状态

/**
* 查询监控对象是否在围栏内,以查询服务端为例
* fenceIds:服务端围栏编号列表,List<Long>
* entityName:监控对象标识
*/
MonitoredStatusRequest request = MonitoredStatusRequest.buildServerRequest(tag, serviceId,entityName, fenceIds);
//发起查询请求
mClient.queryMonitoredStatus(request, fenceListener);

9.查询指定监控对象在指定位置的状态

/**
* 查询监控对象在指定位置是否在围栏内,以查询服务端为例
* latLng:位置点
*/
MonitoredStatusByLocationRequest request = MonitoredStatusByLocationRequest .buildServerRequest(tag, serviceId, 
                                                         entityName, fenceIds, latLng, coordType);
//发起查询请求
mClient.queryMonitoredStatusByLocation(request, fenceListener);

10.查询围栏历史报警信息

/**
* 以查询服务端为例
* startTime:开始时间
* endTime:结束时间
*/
HistoryAlarmRequest request = HistoryAlarmRequest.buildServerRequest(tag, serviceId, startTime, 
                                            endTime, entityName, fenceIds, coordType)
//发起查询请求
mClient.queryFenceHistoryAlarmInfo(request, fenceListener);

好啦,到此,百度鹰眼sdk围栏部分就讲完了。

如果各位看官觉得文章不错,别忘了点个喜欢。
源码下载地址

以上文章内容,是本人工作中的总结,供大家参考,有误的地方还请指正。

    原文作者:zhh_happig
    原文地址: https://www.jianshu.com/p/db11ae2bad4f
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞