I have an app that uses CLLocationManager to request location updates. Monitoring is started when the app receives a notification from an external bluetooth device. The app listens for notifications from the device while it is both in the foreground and the background, and location updates are started successfully in both cases.
If monitoring is started while the app is in the foreground, I get location updates as per the distance filter I have configured on the location manager.
However if monitoring is started while the app is in the background, I still get location updates, but very infrequently. Does anyone know if this is expected behaviour, or if I have potentially configured something incorrectly?
The setup in the code is as follows:
fileprivate lazy var locationManager = CLLocationManager()
func initLocationManager(distanceFilter: CLLocationDistance = 270,
desiredAccuracy: CLLocationAccuracy = kCLLocationAccuracyNearestTenMeters,
activityType: CLActivityType = .automotiveNavigation) {
locationManager.requestAlwaysAuthorization()
locationManager.allowsBackgroundLocationUpdates = true
if canGetLocationUpdate() {
locationManager.desiredAccuracy = desiredAccuracy
locationManager.distanceFilter = distanceFilter
locationManager.activityType = activityType
locationManager.delegate = self
}
}
func startLocationMonitoring() {
if CLLocationManager.locationServicesEnabled() {
locationManager.startUpdatingLocation()
} else {
log.error("Unable to start location monitoring")
}
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
for location in locations {
log.debug("Got location \(location.coordinate) with speed \(location.speed) and accuracy \(location.horizontalAccuracy)")
}
}
And the following is in Info.plist:
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key><string>To allow the app...</string>
<key>NSLocationAlwaysUsageDescription</key><string>To allow the app...</string>
<key>NSLocationWhenInUseUsageDescription</key><string>To allow the app...</string>
...
<key>UIBackgroundModes</key>
<array>
<string>bluetooth-central</string>
<string>location</string>
</array>
You can use an NSTimer to request a location every minute with this method now and don't have to work with startUpdatingLocation and stopUpdatingLocation methods.
Access to location is considered in the foreground if it happens while the app is open and visible to the user. If the user closes the app, or hits the home button to return to their main screen, then the app's access to location is considered in the background.
Tell the system you want background updatesSet the allowsBackgroundLocationUpdates property of your location manager to true to enable background updates. Set the showsBackgroundLocationIndicator property to true if your app has Always access to let people know when you're using location services in the background.
First, go to your project's settings and choose the Capabilities tab. You need to enable the Background Modes capability, then check the box marked Background Fetch. This modifies your app's Info.
From apple docs
If your iOS app must keep monitoring location even while it’s in the background, use the standard location service and specify the location value of the UIBackgroundModes key to continue running in the background and receiving location updates. (In this situation, you should also make sure the location manager’s pausesLocationUpdatesAutomatically property is set to YES to help conserve power.) Examples of apps that might need this type of location updating are fitness or turn-by-turn navigation apps.
Seems like iOS restrict location updates in background to save device power.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With