像life360这样的应用程序如何在终止状态下获取位置更新?

问题描述

即使应用被用户终止,我也需要接收位置更新。诸如life360之类的应用程序会在所有应用程序状态(终止,后台和前景)中接收准确的位置更新。 Apple的以下两个文档强调了在应用终止后可以获取位置更新:

https://developer.apple.com/documentation/corelocation/getting_the_user_s_location/handling_location_events_in_the_background

https://developer.apple.com/documentation/corelocation/cllocationmanager/1423531-startmonitoringsignificantlocati

奇怪的是,由于无法在终止状态下获取位置更新,我直接与Apple联系。这是确切的答案:

应用的预期行为是不会在 如果应用程式先前曾有过重大位置变更的背景 被用户强行退出。强制戒烟是一个艰难的选择 用户说他们不想运行该应用程序,通常是因为它 以某种无法恢复的方式行为不当。

强制退出后唯一会重新启动应用程序的位置API是 区域监控。

这引出了一个问题,谁是对的?文档是否不正确或已过时?尽管处于终止状态,life360如何继续跟踪家人的位置?苹果会对life360给予特殊待遇吗?

解决方法

我开发了一款类似于 life 360​​ 的应用,该应用在应用终止或处于后台时使用位置跟踪。 这是一个相对简单的壮举。一旦您的应用程序被终止或推送到后台,您必须设置您的位置管理器实例以跟踪显着的位置变化。这将减少电池消耗和准确性,但将有助于停止电池消耗,否则即使检测到显着的位置变化,iOS 也可能无法启动您的应用程序。 这是我如何实现这一目标的示例代码

func applicationWillEnterForeground(_ application: UIApplication) {
    LocationHelper.handleEnterForeground()
}

func applicationDidEnterBackground(_ application: UIApplication) {
    LocationHelper.handleEnterBackground()
}

func applicationWillTerminate(_ application: UIApplication) {
    LocationHelper.handleAppKilled()
}

在 LocationManager.swift 中:

var locationManager = CLLocationManager()

override init() {
    super.init()
    locationManager.delegate = self
    locationManager.allowsBackgroundLocationUpdates = true
    locationManager.pausesLocationUpdatesAutomatically = true
    locationManager.activityType = .automotiveNavigation
    locationManager.desiredAccuracy = kCLLocationAccuracyBest
    locationManager.distanceFilter = 25
    
    if hasLocationPermission() {
        self.locationManager.startUpdatingLocation()
    } else {
        self.asklocationPermission()
    }
}

static func handleEnterForeground() {
    LocationHelper.shared = LocationHelper()
    LocationHelper.shared.locationManager.desiredAccuracy = kCLLocationAccuracyBest
    LocationHelper.shared.locationManager.startUpdatingLocation()
}

static func handleEnterBackground() {
    LocationHelper.shared = LocationHelper()
    LocationHelper.shared.locationManager.stopUpdatingLocation()
    LocationHelper.shared.locationManager.startMonitoringSignificantLocationChanges()
}

static func handleAppKilled() {
    LocationHelper.shared = LocationHelper()
    LocationHelper.shared.locationManager.stopUpdatingLocation()
    LocationHelper.shared.locationManager.startMonitoringSignificantLocationChanges()
}