iOS区域监控(地理围栏)

作者: joeal | 来源:发表于2019-06-12 10:11 被阅读0次

    iOS区域监控(地理围栏)

    区域监控,高德地图上叫地理围栏,两者都是同一个意思。此功能实现的是:首先创建一个区域(围栏),当用户设备进入或者离开此区域时,会有相应的代理方法响应,开发者可以做一些操作。并且最重要的一点是当开启了区域监控,即使用户杀死了APP还是可以监听到代理方法的响应,从而做一些操作。

    地理围栏.jpg

    位置权限:必须是始终运行访问地理位置权限,这样在杀死状态下才能通过区域监控唤醒APP获取位置信息。

    开始我接入的是高德SDK,但不知是何原因导致我杀死APP时地理围栏并没有唤醒APP。所以我换成了系统CoreLocation框架实现此功能。

    一、导入框架

    import CoreLocation
    

    二、初始化CLLocationManager

    locationManager = CLLocationManager()
    locationManager.delegate = self
    //必须满足始终允许地理位置访问
    locationManager.requestAlwaysAuthorization()
    locationManager.pausesLocationUpdatesAutomatically = false
    if #available(iOS 9.0, *) {
        locationManager.allowsBackgroundLocationUpdates = true
    } else {
        // Fallback on earlier versions
    }
    

    三、遵从代理CLLocationManagerDelegate

    // MARK: - 区域监控代理方法
    extension AppLocationManager {
        
        /// 进入区域
        func locationManager(_ manager: CLLocationManager, didEnterRegion region: CLRegion) {
            debugPrint("进入区域")
        }
        
        /// 离开区域
        func locationManager(_ manager: CLLocationManager, didExitRegion region: CLRegion) {
            debugPrint("离开区域")
        }
        
        /// 请求某个区域的状态
        func locationManager(_ manager: CLLocationManager, didDetermineState state: CLRegionState, for region: CLRegion) {
            //    CLRegionStateUnknown,   未知状态
            //    CLRegionStateInside, // 在区域内部
            //    CLRegionStateOutside // 区域外面
            var msg = ""
            if(state == .inside)
            {
                debugPrint("在区域内")
                msg = "在区域内"
            }else if (state == .outside)
            {
                debugPrint("在区域外")
                 msg = "在区域外"
            } else {
                debugPrint("未知区域")
                 msg = "未知区域"
            }
            //发送本地推送
            LocalNotificationManager.addNotification(msg: msg)
        }
        
        /// 监听区域失败
        func locationManager(_ manager: CLLocationManager, monitoringDidFailFor region: CLRegion?, withError error: Error) {
            // 经验: 一般在这里, 做移除最远的区域
            //    [manager stopMonitoringForRegion:最远区域]
            debugPrint(error)
        }
    }
    

    四、区域定位唤醒被杀死APP

    当用户设置始终允许访问地理位置权限时,即使APP被杀死了,当进入区域或者离开区域时都能唤醒APP,这时我们就可以在AppDelegate方法中func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool判断是否是区域定位唤醒的从而做一些操作。

    /// APP被唤醒机制
        func awakeForRegion(launchOptions: [UIApplication.LaunchOptionsKey: Any]?) {
            let flag = launchOptions?.keys.contains(UIApplication.LaunchOptionsKey.location) ?? false
            if flag {
                LocalNotificationManager.addNotification(msg: "被区域定位唤醒")
            }
            let isNotification = launchOptions?.keys.contains(UIApplication.LaunchOptionsKey.remoteNotification) ?? false
            if isNotification {
                LocalNotificationManager.addNotification(msg: "被通知推送唤醒")
            }
        }
    

    五、开启区域监控

    做好了以上步骤就可以实现区域监控代码了,区域监控顾名思义就是要划定一个区域,系统给我们提供了好几种划定区域的方法,我们选择最简单的一种--画圆。

    /// 开启区域定位
        func regionWatch() {
            if CLLocationManager.isMonitoringAvailable(for: CLCircularRegion.self) {
                guard let lat = AppLoginUserManager.default.dormLat, let lng = AppLoginUserManager.default.dormLng else {
                    return
                }
                guard lat > 0 && lng > 0 else { return }
                var center = CLLocationCoordinate2DMake(lat, lng)
    //            中国国测局地理坐标(GCJ-02) 转换成 世界标准地理坐标(WGS-84)
    //              这里是因为我们使用的是国内的坐标系统,但是iOS系统获取的是世界标注坐标系统所以我们需要转换一下
    //              如果你们后端提供的坐标也是世界标准的话就不需要转化了
    //              JZLocationConverter是一个第三方库:https://github.com/JackZhouCn/JZLocationConverter
                center = JZLocationConverter.gcj02(toWgs84: center)
                var radius: Double = 20
                
                if let r = AppLoginUserManager.default.locationRadius, r > 0 {
                    radius = r
                }
                    //判断半径是否超过系统的最大
                if radius > self.locationManager.maximumRegionMonitoringDistance {
                    radius = self.locationManager.maximumRegionMonitoringDistance
                }
                let region = CLCircularRegion(center: center, radius: radius, identifier: "NZ")
                //监听进入区域
                region.notifyOnEntry = true
                //监听离开区域
                region.notifyOnExit = true
                //开始区域监听
                locationManager.startMonitoring(for: region)
                locationManager.requestState(for: region)
            }
        }
    

    相关文章

      网友评论

        本文标题:iOS区域监控(地理围栏)

        本文链接:https://www.haomeiwen.com/subject/qnlkfctx.html