swift 百度地图加载与百度地图电子围栏加载

最近在写百度地图电子围栏加载,研究源码,也花了一些时间。

1、百度电子围栏整体思路

    1)用户创造实体,赋予监控权限

    2)对该实体创造电子围栏,有服务端和本地端两种方式,先创造实体,上传到的服务器中。在对实体创造电子围栏,服务器端的有多边形,圆形,本地端的只有圆形围栏。

    3)查询对于该实体的电子围栏操作,从代理返回值中在地图上画出围栏。

    4)检测实体运动轨迹,若超出范围,则报警。(创建实体,允许获得用户轨迹,百度后台返回的代理)

一、工程配置

    按照官网提示的即可,swift要加桥接而已。

二、

0、调用百度地图服务之前,都需要设置ak mcode信息,否则调用不到

[objc] view plain copy
  1. let sop: BTKServiceOption = BTKServiceOption(ak: "ksqN5xi5s2Kpc6jlqW6Km5zk524pDhmy", mcode"www.arvin.com.baiduMap", serviceID200447, keepAlivefalse)  
  2.         BTKAction.sharedInstance().initInfo(sop)   

ak 是在百度地图申请的,mcode是工程的Bundle id。

1、添加百度地图,因为我们用鹰眼围栏是需要在地图上画出图形来的。

 _mapView = BMKMapView(frame: CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height))

        self.view.addSubview(_mapView!)

按照百度地图官网或者其demo即可。

2、添加百度地图的第一步是首先需要创建实体,并给实体创建电子围栏,上传给百度地图服务器

[objc] view plain copy
  1. //设置地理围栏  
  2. func creatMapFrence() {  
  3.     //创建entity实体 entityDesc 字母数字下划线  
  4.     let request: BTKAddEntityRequest = BTKAddEntityRequest(entityName: "entityA", entityDesc"ThissaentityA", columnKey: nil, serviceID00000, tag1)  
  5.     BTKEntityAction.sharedInstance().addEntity(with: request, delegateself)  
  6. p;        //创建一个名称为“server_circle_fence” 的服务端圆形地理围栏,圆心坐标为东经116.3134度、北纬40.0478度,围栏半径为50米。它的监控对象为“entityA”,且当entityA这个终端实体的定位精度大于50米的轨迹点不参与此围栏的计算。  
  7.     //圆心40.055573298959558)Optional(116.30384089417596  
  8.     let center: CLLocationCoordinate2D = CLLocationCoordinate2D.init(latitude: 40.055573298959558, longitude116.30384089417596)  
  9.     //构造将要创建的新的围栏对象  
  10.     let fence: BTKServerCircleFence = BTKServerCircleFence(center: center, radius450.0, coordType.COORDTYPE_BD09LL, denoiseAccuracy50, fenceName"firstFenceName", monitoredObject"entityA")  
  11.     //构建请求对象  
  12.     let circleRequest: BTKCreateServerFenceRequest = BTKCreateServerFenceRequest.init(serverCircleFence: fence, serviceID00000, tag1)  
  13.     //发起请求  
  14.     BTKFenceAction.sharedInstance().createServerFence(with: circleRequest, delegateself)  
  15.     
  16. }  

完成之后,我们需要调用创建实体是否成功的代理,判断是否创建成功

[objc] view plain copy
  1. //创建地理围栏返回代理  
  2.    func onCreateServerFence(_ response: Data!) {  
  3.        guard let array:[String: Any] = try! JSONSerialization.jsonObject(with: response, options: []) as? [String: Anyelse {//转化失败就返回  
  4.            return  
  5.        }  
  6.        print("创建地理围栏\(array)")  
  7.    }  

2、搜索我们可以在鹰眼代理BTKFenceDelegate 中查询我们所创建的实体

[objc] view plain copy
  1. //查询围栏  
  2.     func qureyMapFernce() {  
  3.         //构建请求对象  
  4.         let request = BTKQueryServerFenceRequest(monitoredObject: "entityA", fenceIDs: nil, outputCoordType.COORDTYPE_BD09LL, serviceID000000, tag1)  
  5.         //发送查询请求  
  6.         BTKFenceAction.sharedInstance().queryServerFence(with: request, delegateself)  
  7.           
  8.     }  

查询地理围栏并且在地图上画出地理围栏

[objc] view plain copy
  1.     func onQueryServerFence(_ response: Data!) {  
  2.         guard let array:[String: Any] = try! JSONSerialization.jsonObject(with: response, options: []) as? [String: Anyelse {//转化失败就返回  
  3.             return  
  4.         }  
  5.         print("查询地理围栏\(array)")  
  6.         let size: NSInteger = array["size"] as! NSInteger  
  7.         //在地图上展示这些围栏  
  8.         //获取size 在地理位置信息  
  9.         //使用Annotation代表圆形围栏的圆心  
  10.         let centerAnnotations: NSMutableArray = NSMutableArray(capacity: size)  
  11.         //使用填充圆行围栏的覆盖物  
  12.         let radiusOverlays: NSMutableArray = NSMutableArray(capacity: size)  
  13.         //存储所有围栏的圆心位置,是为了确定地图的显示范围  
  14.         let coordinates: NSMutableArray = NSMutableArray(capacity: size)  
  15.         let dicFence: [[String: Any]] = array["fences"] as! [[String : Any]]  
  16.           
  17.         for fence in dicFence {  
  18.             //筛选circle的圆  
  19.             let circle: String = fence["shape"] as! String  
  20.             if circle == "circle" {  
  21.                 //解析数据 经纬度  
  22.                 let fenceCenter: CLLocationCoordinate2D = CLLocationCoordinate2D(latitude: fence["latitude"] as! CLLocationDegrees, longitude: fence["longitude"] as! CLLocationDegrees)  
  23.                   
  24.                 let fenceRadius: Double = fence["radius"] as! Double  
  25.                 let fenceName: String = fence["fence_name"] as! String  
  26.                 let denoiseAccuracy: NSInteger = fence["denoise"] as! NSInteger  
  27.                 let monitoredObject: String = fence["monitored_person"] as! String  
  28.                   
  29.                 //存贮圆心位置 /*略有问题*/  
  30. //                let coordinateValue: NSValue = NSValue.init(bytes: &fenceCenter, objCType: "CLLocationCoordinate2D")  
  31.                   
  32.                 coordinates.add(fenceCenter)  
  33.                   
  34.                 //构造Annotaion  
  35.                 let annotation: BMKPointAnnotation = BMKPointAnnotation()  
  36.                 annotation.coordinate = fenceCenter  
  37.                 annotation.title = "预设名称\(fenceName)"  
  38.                 annotation.subtitle = "半径:\(fenceRadius),去噪精度 \(denoiseAccuracy)"  
  39.                 centerAnnotations.add(annotation)  //圆心数组  
  40.                   
  41.                 //围栏的覆盖范围  
  42.                 let coverageArea: BMKCircle = BMKCircle()  
  43.                 coverageArea.coordinate = fenceCenter  
  44.                 coverageArea.radius = fenceRadius  
  45.                   
  46.                 radiusOverlays.add(coverageArea)  
  47.                   
  48.                   
  49. //                let annoationKey: NSValue = NSValue.value(annotation, withObjCType: <#UnsafePointer<Int8>#>)  
  50.                 let annoationKey: NSValue = NSValue.init(nonretainedObject: annotation)  //转换NSDate  
  51.                   
  52.                 //存储标注到围栏的映射  
  53.                 let fenceObject: BTKServerCircleFence = BTKServerCircleFence(center: fenceCenter, radius: fenceRadius, coordType.COORDTYPE_BD09LL, denoiseAccuracy: UInt(denoiseAccuracy), fenceName: fenceName, monitoredObject: monitoredObject)  
  54.                 annotationMapToFenceObject.setObject(fenceObject, forKey: annoationKey)  
  55.                   
  56.                 //存储标注到围栏ID的映射  
  57.                 let fenceID: NSNumber = fence["fence_id"] as! NSNumber  
  58.                 annotationMapToFenceID.setObject(fenceID, forKey: annoationKey)  
  59.   
  60.             } else {  
  61.                   
  62.             }  
  63.         }  
  64. //        weak let weakSelf = self  
  65.         //在地图上展示围栏 //主队列 异步  
  66.         DispatchQueue.main.async {  
  67.             //清空原有的标注和覆盖物  
  68.             self._mapView?.removeOverlays(self._mapView?.overlays)  
  69.             self._mapView?.removeAnnotations(self._mapView?.annotations)  
  70.             //添加新的标注物和覆盖物  
  71.             self._mapView?.addAnnotations(centerAnnotations as! [Any])  
  72.             self._mapView?.addOverlays(radiusOverlays as! [Any])  
  73.             //设置地图的显示范围  
  74.             self.mapViewFitForCoordinates(points: coordinates)  
  75.         }  
  76.           
  77.     }  
[objc] view plain copy
  1. //设置地图的显示范围  
  2.     func mapViewFitForCoordinates(points: NSArray) {  
  3.         var minLat: Double = 90.0  
  4.         var maxLat: Double = -90.0  
  5.         var minLon: Double = 180.0  
  6.         var maxLon: Double = -180.0  
  7.         for i in 0..<points.count {  
  8.             let coord: CLLocationCoordinate2D = points[i] as! CLLocationCoordinate2D  
  9.             minLat = fmin(minLat, coord.latitude)  
  10.             maxLat = fmax(maxLat, coord.latitude)  
  11.             minLon = fmin(minLon, coord.longitude)  
  12.             maxLon = fmax(maxLon, coord.longitude)  
  13.         }  
  14.           
  15.         let center: CLLocationCoordinate2D = CLLocationCoordinate2DMake((minLat + maxLat) * 0.5, (minLon + maxLon) * 0.5)  
  16.         //设置经纬度范围  
  17.         let span = BMKCoordinateSpan(latitudeDelta: (maxLat - minLat) + 0.06, longitudeDelta: (maxLon - minLon) + 0.06)  
  18.           
  19.         var region = BMKCoordinateRegion()  
  20.         region.center = center  
  21.         region.span = span  
  22.           
  23.         self._mapView?.setRegion(region, animatedtrue)  
  24.     }  
  25.       
  26.       
  27.     //围栏的画图,需要实现这个代理,否则画不出来  
  28.     func mapView(_ mapView: BMKMapView!, viewFor overlay: BMKOverlay!) -> BMKOverlayView! {  
  29.         //判断是圆形  
  30.         if overlay is BMKCircle {  
  31.             let circleView = BMKCircleView.init(overlay: overlay)  
  32.             circleView?.fillColor = UIColor.init(red: 0, green0, blue1, alpha0.3)  
  33.             circleView?.strokeColor = UIColor.init(red: 0, green0, blue1, alpha0)  
  34.             return circleView  
  35.         } else {  
  36.             return nil  
  37.         }  
  38.           
  39.           
  40.           
  41.     }  

删除地理围栏

[objc] view plain copy
  1. //删除围栏  
  2.     func deleteMapFrence() {  
  3.         //请求构造对象  
  4.         let request: BTKDeleteServerFenceRequest = BTKDeleteServerFenceRequest(monitoredObject: "entityA", fenceIDs: nil, serviceID200447, tag22)  
  5.         //发起删除请求  
  6.         BTKFenceAction.sharedInstance().deleteServerFence(with: request, delegateself)  
  7.     }  

删除地理围栏代理

[objc] view plain copy
  1. //删除围栏  
  2.    func onDeleteServerFence(_ response: Data!) {  
  3.        guard let array:[String: Any] = try! JSONSerialization.jsonObject(with: response, options: []) as? [String: Anyelse {//转化失败就返回  
  4.            return  
  5.        }  
  6.        print("删除地理围栏\(array)")  
  7.    }  

更新地理围栏

[objc] view plain copy
  1. //更新围栏  
  2.     func updateMapFrence() {  
  3.         //新的圆心  
  4.         let center: CLLocationCoordinate2D = CLLocationCoordinate2DMake(40.1578116.2234)  
  5.         //新的圆形围栏  
  6.         let fence: BTKServerCircleFence = BTKServerCircleFence(center: center, radius60, coordType.COORDTYPE_BD09LL, denoiseAccuracy60, fenceName"server_fence_60", monitoredObject"entityB")  
  7.         //构建请求对象  
  8.         let request: BTKUpdateServerFenceRequest = BTKUpdateServerFenceRequest(serverCircleFence: fence, fenceID138, serviceID200447, tag1)  
  9.         //发起更新请求  
  10.         BTKFenceAction.sharedInstance().updateServerFence(with: request, delegateself)  
  11.   
  12.     }  

实时查询

[objc] view plain copy
  1.     //实时状态查询  
  2.     func querServerFenceStatus() {  
  3.         //实时状态查询  
  4.         //鹰眼iOS SDK支持查询指定监控对象的状态,监控对象即某个终端实体(,,),监控对象是指其相对其上的地理围栏的位置关系,是在圆形或  
  5.         //多边形围栏的内部还是外部,是否偏离了线性围栏等。  
  6.         let request: BTKQueryServerFenceStatusRequest = BTKQueryServerFenceStatusRequest(monitoredObject: "entityA", fenceIDs: nil, serviceID200447, tag25)  
  7.         //发起查询请求  
  8.         BTKFenceAction.sharedInstance().queryServerFenceStatus(with: request, delegateself)  
  9.           
  10. //        以下代码片段表示,假设“entityA”这个终端实体在东经120.44度,北纬40.11度的话,该终端实体和其上的fenceID为17、23、29的这几个服务端地理围栏的位置关系,只有这几个地理围栏的监控对象是“entityA”这个终端实体时才有意义,如果不知道有哪些地理围栏在监控“entityA”这个终端实体,则fenceIDs属性传入nil即可。  
  11.         let customLocation: CLLocationCoordinate2D = CLLocationCoordinate2DMake(40.11120.44)  
  12.         //地理围栏ID列表  
  13. //        NSArray *fenceIDs = ["",""]  
  14.         //构建请求对象  
  15.         let requestB: BTKQueryServerFenceStatusByCustomLocationRequest = BTKQueryServerFenceStatusByCustomLocationRequest(monitoredObject: "entityA", customLocation: customLocation, coordType.COORDTYPE_BD09LL, fenceIDs: nil, serviceID200447, tag28)  
  16.         //发起查询请求  
  17.         BTKFenceAction.sharedInstance().queryServerFenceStatusByCustomLocation(with: requestB, delegateself)  
  18.           
  19.     }  

若是获取报警信息,我们应用的是BTKTraceDelegate的代理

[objc] view plain copy
  1. //报警推送  
  2.     //当服务器围栏被触发之后,会通过长链接将报警信息推送给SDK,SDK会通过BTKActionDelete SDK会通过 BTKActionDelegate 协议的 -(void)onGetPushMessage:(BTKPushMessage *)message; 方法将报警信息推送给开发者。因此服务端围栏的报警推送要求网络畅通。当接收报警的手机断网或网络状态不好时,会导致报警推送失败,鹰眼服务端将在后续的10分钟之内每隔15s推送一次,直至收到成功响应。若10分钟之后仍未成功,将不再推送,但报警记录将存储在鹰眼服务端。为避免因此造成报警漏接收,开发者可定期使用历史报警查询接口同步报警信息。  
  3.     /*BTKTraceDelegate*/ //需要定义实体检测其轨迹  
  4.     func onGet(_ message: BTKPushMessage!) {  
  5.         //获得推送消息  
  6.         if (message.type != 0x03 && message.type != 0x04) {  
  7.             return;  
  8.         }  
  9.         let content: BTKPushMessageFenceAlarmContent = message.content as! BTKPushMessageFenceAlarmContent  
  10.         var fenceName: String = "「" + content.fenceName + "」"  
  11.         let monitoredObject = "「" + content.monitoredObject + "」"  
  12.         var action = ""  
  13.         if content.actionType == .FENCE_MONITORED_OBJECT_ACTION_TYPE_ENTER {  
  14.             action = "进入"  
  15.         } else {  
  16.             action = "离开"  
  17.         }  
  18.         let fenceType = ""  
  19.         if message.type == 0x03 {  
  20.             fenceName = "服务器围栏"  
  21.         } else {  
  22.             fenceName = "客户端围栏"  
  23.         }  
  24.           
  25.         //通过触发报警的轨迹点,解析出触发报警的时间  
  26.         let currentPoint: BTKFenceAlarmLocationPoint = content.currentPoint  
  27.         let dataFormatter: DateFormatter = DateFormatter()  
  28.         dataFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"  
  29.         let alarmDate: Date = Date(timeIntervalSince1970: TimeInterval(currentPoint.loctime))  
  30.         let alarmDateStr: String = dataFormatter.string(from: alarmDate)  
  31.           
  32.         let puchMessage: String = "终端" + monitoredObject + "在" + alarmDateStr + action + fenceType + fenceName  
  33.         //  
  34.         print("推送消息\(puchMessage)")  
  35.           
  36.         let deviceType: String = UIDevice.current.systemVersion  
  37.         let deviceTypeDouble: Double = Double(deviceType)!  
  38.           
  39.         if deviceTypeDouble >= 10.0 {  
  40.             // 发送本地通知UNNotificationRequest  
  41.             let notificationContent: UNMutableNotificationContent = UNMutableNotificationContent()  
  42.             notificationContent.title = "报警" + fenceType  
  43.             notificationContent.body = puchMessage  
  44.             notificationContent.sound = UNNotificationSound.default()  
  45.             let notificationTrigger: UNTimeIntervalNotificationTrigger = UNTimeIntervalNotificationTrigger(timeInterval: 0.1, repeatsfalse)  
  46.             let idd = "YYPushMessageNotificationIdentifier" + puchMessage  
  47.               
  48.             let request: UNNotificationRequest = UNNotificationRequest(identifier: idd, content: notificationContent, trigger: notificationTrigger)  
  49.             UNUserNotificationCenter.current().add(request) { (error) in  
  50.                 let errorMessage: NSError = error! as NSError  
  51.                 if errorMessage.description == "" {  
  52.                     print("地理围栏报警发送失败" + error.debugDescription)  
  53.                 } else {  
  54.                     print("消息发送成功")  
  55.                     UIApplication.shared.applicationIconBadgeNumber += 1  
  56.                 }  
  57.             }  
  58.               
  59.               
  60.               
  61.         } else {  
  62.               
  63.               
  64.         }      
  65.    }  











地图大数据云平台  http://www.favxu.com

三维地球云平台    http://www.hapxu.com

地图云平台交流合作 QQ:63747667

邮箱:hui1788@163.com


阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页