【问题标题】:iOS Swift Background Location MonitoringiOS Swift 后台位置监控
【发布时间】:2019-02-11 10:41:09
【问题描述】:

我正在编写一个支持后台定位的应用。该应用程序需要跟踪用户在送货路线上穿过城镇时的位置点。

我使用 CLLocationManager 中的 startUpdatingLocation(),一切正常,直到应用程序在后台运行大约 15 分钟。

然后应用程序似乎终止并且跟踪结束。

我知道这种连续跟踪(即 MapMyRun)必须起作用,但我不知道如何工作。

编辑:LocationManager配置如下

self.locationManager?.desiredAccuracy = kCLLocationAccuracyBestForNavigation
self.locationManager?.distanceFilter = kCLDistanceFilterNone
self.locationManager?.allowsBackgroundLocationUpdates = true
self.locationManager?.pausesLocationUpdatesAutomatically = false
self.locationManager?.activityType = CLActivityType.automotiveNavigation
self.locationManager?.showsBackgroundLocationIndicator = true

【问题讨论】:

  • 欢迎来到 Stack Overflow。您应该编辑您的问题以显示相关代码(即您如何配置位置管理器),以便我们为您提供帮助。
  • info.plist 中指定了哪些背景模式?
  • @Paulw11 进行了编辑。在他们的应用程序上。这里看起来有点不稳定。
  • @AshleyMills 只是“位置”
  • 您需要将allowsBackgroundLocationUpdates设置为true

标签: ios iphone swift background-process


【解决方案1】:

为了让位置更新在后台运行,您需要为您的应用启用后台模式功能。

如果您不这样做,应用程序将在操作系统认为合适的 X 时间后在后台终止。

为此,请单击您的目标,转到功能选项卡,启用背景模式并勾选位置更新。详情见截图

尝试一下,如果仍然无法正常工作,我建议您将位置管理器代码上传到某处查看。

希望有帮助!

【讨论】:

  • 嗨 Jared,你确定你的应用在 15 分钟后不会在后台崩溃吗?您是否实施了任何可以跟踪的崩溃报告系统? Crashlytics 之类的东西可能会帮助您查看是否发生任何崩溃。如果您可以将整个代码发布到某个地方以查看和帮助,它也可能会有所帮助。最后一件事,检查您的应用是否由于在本地保存位置而消耗过多的 CPU 和内存,并因此被操作系统终止。
  • 我正在使用 TestFlight,但没有看到任何崩溃日志。如何知道 CPU 和内存使用率过高?
  • 您可以覆盖 didReceiveMemoryWarning 并将其记录在某处。还可以尝试将您的应用连接到 XCode 很长一段时间,看看您消耗了多少。我建议添加 Crashlytics 来跟踪崩溃报告,我发现它具有更好的洞察力和报告。
  • 我会看看那些。谢谢!
【解决方案2】:

iOS 在后台终止定位服务。 您需要在 iPhone 设置中手动设置。

To enable access, tap Settings > Location and select Always"

您可以显示警报以通知用户并转到设置。

func checkUsersLocationServicesAuthorization(){
        /// Check if user has authorized Total Plus to use Location Services
        if CLLocationManager.locationServicesEnabled() {
            switch CLLocationManager.authorizationStatus() {
            case .notDetermined:
                // Request when-in-use authorization initially
                // This is the first and the ONLY time you will be able to ask the user for permission
                self.locationManager.delegate = self
                locationManager.requestWhenInUseAuthorization()
                break

            case .restricted, .denied:
                // Disable location features
                let alert = UIAlertController(title: "Allow Location Access", message: "MyApp needs access to your location. Turn on Location Services in your device settings.", preferredStyle: UIAlertController.Style.alert)

                // Button to Open Settings
                alert.addAction(UIAlertAction(title: "Settings", style: UIAlertAction.Style.default, handler: { action in
                    guard let settingsUrl = URL(string: UIApplication.openSettingsURLString) else {
                        return
                    }
                    if UIApplication.shared.canOpenURL(settingsUrl) {
                        UIApplication.shared.open(settingsUrl, completionHandler: { (success) in
                            print("Settings opened: \(success)")
                        })
                    }
                }))
                alert.addAction(UIAlertAction(title: "Ok", style: UIAlertAction.Style.default, handler: nil))
                self.present(alert, animated: true, completion: nil)

                break

            case .authorizedWhenInUse, .authorizedAlways:
                // Enable features that require location services here.
                let alert = UIAlertController(title: "Allow Location Access", message: "Lookout does not have access to your location while in the background. To enable access, tap Settings > Location and select Always", preferredStyle: UIAlertController.Style.alert)

                // Button to Open Settings
                alert.addAction(UIAlertAction(title: "Settings", style: UIAlertAction.Style.default, handler: { action in
                    guard let settingsUrl = URL(string: UIApplication.openSettingsURLString) else {
                        return
                    }
                    if UIApplication.shared.canOpenURL(settingsUrl) {
                        UIApplication.shared.open(settingsUrl, completionHandler: { (success) in
                            print("Settings opened: \(success)")
                        })
                    }
                }))
                alert.addAction(UIAlertAction(title: "Not Now", style: UIAlertAction.Style.default, handler: nil))
                self.present(alert, animated: true, completion: nil)

                break
            }
        }
    }

为了更准确也可以调用这个方法

func startLocationService(){
    locationManager.startUpdatingLocation()
    locationManager.startMonitoringSignificantLocationChanges()
    locationManager.pausesLocationUpdatesAutomatically = false
    locationManager.allowsBackgroundLocationUpdates = true
    locationManager.showsBackgroundLocationIndicator = true
}

别忘了在 Target 中启用背景模式 -> 签名和 能力

最后检查是在 info.plist 中添加权限

感谢您为后台实时定位所做的一切

【讨论】:

    【解决方案3】:

    退房

    CLLocationManager.startMonitoringSignificantLocationChanges()
    

    The Apple documentation here

    【讨论】:

    • 重要位置监控的问题是我需要非常详细的信息。仅每 500 米左右捕获一次。
    • 答案的想法是您的应用程序仍然在后台运行,因此您可以继续监控位置。我们在 iOS 9 中这样做,每半分钟左右检查一次用户的位置,并且该应用程序已在 AppStore 中运行。不确定最近是否发生了变化。
    【解决方案4】:

    您的应用在后台获取的位置更新完全由 iOS 处理,不受您的应用控制。

    根据 Apple 关于后台定位服务的文档:

    启用此模式不会阻止系统暂停 应用程序,但它确实告诉系统它应该唤醒应用程序 每当有新的位置数据要交付时。因此,这个键 有效地让应用程序在后台运行以处理位置 随时更新。

    更多信息请参考Background Execution

    【讨论】:

    • 一定有办法。谷歌地图之类的应用不会像我看到的那样被终止。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-09
    • 2014-04-29
    • 2016-09-30
    • 2018-07-13
    • 2017-03-13
    • 1970-01-01
    相关资源
    最近更新 更多