0

当用户进入该区域时,我正在制作一个带有位置更新的 ibeacon 区域监控应用程序(应用程序不在前台)。此位置更新必须配置为 kCLLocationAccuracyBestForNavigation 准确度(因为我必须在使用时进行跟踪,而仍然在该区域内,订阅我的重大更改是不够的)。一切正常,但 20 秒后(有时 1 分钟以上)我停止接收位置更新。我将所有键都放在 info.plist 中以始终使用位置,我在功能部分中包含背景模式,并在背景中包含位置更新。

我用不同的配置配置 locationManager 并且总是停止我的位置更新。我正在使用 IOS 12 和 Iphone 7 进行测试。

我配置CLLocationManager的方式:

self.locationManager.desiredAccuracy
=kCLLocationAccuracyBestForNavigation
self.locationManager.activityType = .automotiveNavigation
self.locationManager.distanceFilter = kCLDistanceFilterNone;
self.locationManager.delegate = self
self.locationManager.allowsBackgroundLocationUpdates = true
self.locationManager.pausesLocationUpdatesAutomatically = false

开始位置更新(当用户进入 Ibeacon 区域时):

func beaconManager(_ manager: KTKBeaconManager, didEnter region: 
KTKBeaconRegion) {



    self.locationManager.startUpdatingLocation()


}

最后,在 didUpdate 位置,我调用了一个 Web 服务:

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

    //Call web service using alamofire

}

我寻求您的帮助,以了解我是否为我想要执行的目的正确执行了设置,以及任何让我知道为什么操作系统会终止我的进程以获取位置更新的线索

4

1 回答 1

2

在 iOS 的后台获取定期的位置更新是很棘手的。该操作系统旨在防止应用程序在后台持续运行以优化电池使用,并在一段时间后暂停它们,除非您有几件事完全正确。

你需要做三件事:

  1. 您必须始终从用户那里获得位置许可(正如您所说的那样)。

  2. 您必须将以下条目添加到您的 Info.plist。这将允许您的应用程序在后台无限期运行,但是如果您希望将您的应用程序提交到 App Store,此条目还将向审阅者声明它是一个后台位置应用程序,您需要说服他们它提供对用户的基于位置的好处,并且用户知道这种好处。

 <key>UIBackgroundModes</key>
 <array>
     <string>location</string>
 </array>
  1. 您必须维护一个后台线程以保持您的应用程序处于活动状态。你是否真的在这个后台线程中做任何事情都没有关系。只要让它处于活动状态,iOS 就不会暂停你的应用程序。
  var backgroundTask: UIBackgroundTaskIdentifier = UIBackgroundTaskIdentifier.invalid

  func extendBackgroundRunningTime() {
    if (backgroundTask != UIBackgroundTaskIdentifier.invalid) {
      // already started
      return
    }
    NSLog("Attempting to extend background running time")

    self.backgroundTask = UIApplication.shared.beginBackgroundTask(withName: "DummyTask", expirationHandler: {
      NSLog("Background task expired by iOS.  Cannot run again until a new beacon region event")
      UIApplication.shared.endBackgroundTask(self.backgroundTask)
      self.backgroundTask = UIBackgroundTaskIdentifier.invalid
    })

    DispatchQueue.global().async {
      while (true) {
        let backgroundTimeRemaining = UIApplication.shared.backgroundTimeRemaining
        // This will be a very large number if you have proper permissions
        // If not, it will generally count down from 10 seconds once you are in the
        // background until iOS suspends your app.
        NSLog("Thread background time remaining: \(backgroundTimeRemaining)")
        Thread.sleep(forTimeInterval: 1.0)
      }
    }
  }
于 2019-07-04T18:30:09.343 回答