CLLocationManager区域监控:检测挂起状态中的到达

时间:2017-09-25 05:12:35

标签: ios swift background cllocationmanager geofencing

我正在寻找一种方法,我可以跟踪用户已经到达指定的坐标集附近。当应用程序在后台时(最好在100米内),功能需要工作。另外,为了保存电池,理想情况下我不希望得到太多的坐标读数(也许每10分钟阅读一次不超过几个小时)。

我尝试过几种方法来完成此任务,但无法获得所需的结果:

后台计时器:

我在(App.delegate)

中添加了后台任务
func applicationDidEnterBackground(_ application: UIApplication)

执行重复的Timer.scheduledTimer以获取坐标和进程

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation])

检测用户是否在范围内。如果在短期内应用此方法,但只有在应用程序暂停后才能使用,大约需要3分钟。理想情况下,我不想经常这样做坐标。

区域监控:

我初始化了CLLocationManager,如下所示:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

    locationManager.delegate = self
    locationManager.allowsBackgroundLocationUpdates = true
    locationManager.pausesLocationUpdatesAutomatically = false
    locationManager.activityType = .otherNavigation
    locationManager.requestAlwaysAuthorization()
}

当应用程序进入后台时,LocationManager启动:

func applicationDidEnterBackground(_ application: UIApplication) {
    self.monitorRegionAtLocation(center: CLLocationCoordinate2D(latitude: x, longitude: y), identifier: id)
    locationManager.startUpdatingLocation()
}

区域监测守则:

func monitorRegionAtLocation(center: CLLocationCoordinate2D, identifier: String ) {
    // Make sure the app is authorized.
    if CLLocationManager.authorizationStatus() == .authorizedAlways {
        // Make sure region monitoring is supported.
        if CLLocationManager.isMonitoringAvailable(for: CLCircularRegion.self) {
            // Register the region.
            let maxDistance = 200.0
            let region = CLCircularRegion(center: center,
                                          radius: maxDistance, identifier: identifier)
            region.notifyOnEntry = true
            region.notifyOnExit = false

            locationManager.startMonitoring(for: region)
        }
    }
}

我为CLLocationManager添加了一个didEnterRegion函数块:

func locationManager(_ manager: CLLocationManager, didEnterRegion region: CLRegion) {
    if let region = region as? CLCircularRegion {
        let identifier = region.identifier
        print("FOUND: " + identifier)
    }
}

该代码似乎适用于检测进入某个区域,但是在后台时坐标不会更新。

其他信息

  • 我启用了位置更新和后台提取的后台模式
  • 我在Info.plist中提供了“位置始终使用说明”和“使用中的位置使用说明”的值
  • 应用设置显示针对位置的“始终”权限

我认为必须有更好的方法在后台运行这些检查,但我还没有发现任何检测后台其他动作的方法。

对此问题的任何指示都将不胜感激,如果您需要更多信息,请告诉我,我会尽我所能。

更新:

我已根据以下评论的建议修改了该方法,以使用区域监控。

2 个答案:

答案 0 :(得分:3)

任何位置更新/监控都需要对其位置管理器进行正确配置,以便能够最好地提供所需的位置更新。在进行后台位置更新时检查某些要点非常重要:

1。检查位置更新的背景模式,并启用后台提取

2。检查'位置始终使用说明'和'使用位置使用说明'应在Info.plist中提供

3。检查是否要在位置更新之间暂停 - 如果是,则需要提供活动类型,以便位置管理员可以确定暂停位置更新的最佳方式

4。检查是否要应用距离过滤器 - 您希望用户(设备)移动一些最小数量的位置管理器以发送更新的位置

5。检查您是否需要所需的精度 - 这可能导致某些精度类型的功耗

在您的代码中,我可以看到位置管理器配置了一些参数,但缺少准确性和背景模式的距离过滤器。

   locationManager.allowsBackgroundLocationUpdates = true
   locationManager.pausesLocationUpdatesAutomatically = false
   locationManager.activityType = .otherNavigation

另外,如果您在Apple doc中看到暂停位置更新属性,则说明:

  

对于具有使用中授权的应用,暂停到位置更新   结束访问位置更改,直到应用程序再次启动和   能够重新启动这些更新。如果您不希望更新位置   完全停止,请考虑禁用此属性并更改位置   当您的应用移动到时,准确度为kCLLocationAccuracyThreeKilometers   的背景。这样做可以让您继续接收位置   以电源友好的方式更新。

基本上它告诉你,如果你想要禁用暂停,那么你必须保持准确度(kCLLocationAccuracyThreeKilometers)。我猜你的方法中缺少这个。

此外,您可以检查实际启动后台任务的this link,然后在后台任务中启动位置管理器监控。 希望它有所帮助。

答案 1 :(得分:0)

问题是“CLLocationManager区域监控:检测后台到达”。这是非常可能的,但是在被杀之后检测任何东西都是不可能的(来自iOS 7)。

每当用户向您的app app切换器轻扫时,iOS会将其视为用户不希望该应用在后台运行,因此所有回叫都会停止。

This answerthis answerthis answer也说同样的话。但是Apple doc有点令人困惑。

我个人的观察是即使在杀戮模式下也会调用app,但很少。

关于获取位置,无论何时调用地理围栏的委托方法,您都可以轻松获得位置。

您的要求实际上并不需要背景模式。

不幸的是(幸运的是,对于iOS用户而言,他们节省了电量)我们实际上没有办法在应用程序被杀后1小时获取位置。