I am working on an iOS tracer. It must run and receive locations even if the app is not in foreground, i.e. I use the background mode "Location updates". However, it would be fine to safe battery if possible. Especially, there is no need to receive locations if the device does not move.
distanceFilter
on CLLocationManager
instance but it does not save power, it just reduces the number of location updates.pausesLocationUpdatesAutomatically
set to YES
(it is turned on by deafult) but if the app is in background and the location updates are paused, the app is suspended and does not wake up even if the device starts to move again.Is there a way to save battery when I need to get location in background? The flag pausesLocationUpdatesAutomatically
is very close to what I am looking for but suspending the app in background is a show stopper for me.
You need to enable Background Mode in your project settings under capabilities tab. Under background modes you will find a few modes that satisfy various purposes of running an app in 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.
Using "deferred location updates" as mentioned by Laky is probably the only possible way how to save power for an application that must run in the background and cannot be suspended. I just want to summarize what I have learnded when experimenting with this feature:
Pausing the app can be disallowed, i.e. the property pausesLocationUpdatesAutomatically
can be set to NO
on instance of CLLocationManager
and deferred location updates will work anyway.
When calling allowDeferredLocationUpdatesUntilTraveled: timeout:
some distance and some timeout must be specified as parameters. If you provide too low values, the feature will not take effect. Timeout of 80 seconds is too low, 90 seconds is OK. Distance of 90 meters is too low, 100 meters is OK. (tested on iPhone 5, iOS 8.4.1)
I am not sure if this feature takes effect if the app is just in background. I have not observe it so far. However, it can take effect if the screen is locked.
The feature does not take effect immediately after the screen is locked. You must wait a while. It was 30 - 150 seconds in my observations.
The system sometimes does not deliver location updates in batches anaway. My test app was running 13 hours in background with locked screen and 38% of this time it received locations one by one. Only the remaining 62% of the run time it received batches of locations (collection with at least two elements). The device did not move at all.
The feature will not take effect if the device is connected by docking cable to Mac and the app runs in debugger.
The feature is not supported by all devices, e.g. it is not supported by iPhone 4 or iPad 2.
I have made some measurements to test how much power is saved. I run an app on iPhone 5, iOS 8.4.1 in background with screen locked. The app just starts a CLLocationManager
and saves statistics about received location data (using NSUSerDefaults
) so that thy can be viewed on next app start. Wifi connection was disabled, cellular data enabled. Battery was fully chraged, no other app was running. The device did not move and it was laid on a place with GPS signal. With deferred location updates (with min. distance 900 meters and timeout 90 seconds), the battery was fully drained in 15.25 hours. Without deferred location updates, it took 13 hours.
What you looking for is this
- allowDeferredLocationUpdatesUntilTraveled:timeout:
If your app is in the background and the system is able to optimize its power usage, the location manager tells the GPS hardware to store new locations internally until the specified distance or timeout conditions are met. When one or both criteria are met, the location manager ends deferred locations by calling the locationManager:didFinishDeferredUpdatesWithError: method of its delegate and delivers the cached locations to the locationManager:didUpdateLocations: method.
ex;
[locationManager allowDeferredLocationUpdatesUntilTraveled:100.0f timeout:CLTimeIntervalMax];
So basically it will save some processing power by sending the location updates as an collection of location after specific time rather than firing the location update callback every time device register a movement.
And you can recieve the location update via the follwing callback method;
-(void)locationManager:(CLLocationManager *)manager didFinishDeferredUpdatesWithError:(NSError *)error
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