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

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

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

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

一 围栏简介

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

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

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


二 创建围栏api详解

1.流程图


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方法回到给客户端,你可以在这里进行自己的业务了。

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


进入围栏-图a

离开围栏-图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围栏部分就讲完了。

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

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,560评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,104评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,297评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,869评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,275评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,563评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,833评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,543评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,245评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,512评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,011评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,359评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,006评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,062评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,825评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,590评论 2 273
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,501评论 2 268

推荐阅读更多精彩内容