Reputation: 970
I need to receive location updates even when the app is terminated by the user. Apps like life360 receive accurate location updates in all app states: terminated, background, and foreground. The following two documentations from Apple reinforce that it is possible to get location updates after the app has been terminated:
Strangely enough, I contacted apple directly because I have not been able to get location updates in a terminated state. This is the exact response:
It is expected behavior that an app will not be woken in the background by a Significant Location Change if the app had previously been force-quit by the user. Force quit is a drastic choice by the user to say that they do not want the app to run, often because it misbehaved in some unrecoverable manner.
The only location API that will relaunch an app after a force quit is Region Monitoring.
This begs the question, who is right? Is the documentation incorrect or out of date? How does life360 continuously track the location of my family despite being in a terminated state? Does Apple give special treatment to life360?
Upvotes: 3
Views: 980
Reputation: 167
I worked on an app similar to life 360 which used location tracking when the app was terminated or was in the background. This was a relatively simple feat. You have to set your location manager instance to track significant location changes as soon as your app is killed or pushed to the background. This will reduce the battery consumption and the accuracy but will help stop the battery drainage, otherwise iOS may not start your app even after significant location change has been detected. Here is the sample code as to how I achieved this
func applicationWillEnterForeground(_ application: UIApplication) {
LocationHelper.handleEnterForeground()
}
func applicationDidEnterBackground(_ application: UIApplication) {
LocationHelper.handleEnterBackground()
}
func applicationWillTerminate(_ application: UIApplication) {
LocationHelper.handleAppKilled()
}
In 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()
}
Upvotes: 1