I'm looking for a way to get a background location update every n minutes in my iOS application. I'm using iOS 4.3 and the solution should work for non-jailbroken iPhones.
I tried / considered following options:
CLLocationManager startUpdatingLocation/startMonitoringSignificantLocationChanges
: This works in the background as expected, based on the configured properties, but it seems not possible to force it to update the location every n minutesNSTimer
: Does work when the app is running in the foreground but doesn't seem to be designed for background tasks- Local notifications: Local notifications can be scheduled every n minutes, but it's not possible to execute some code to get the current location (without the user having to launch the app via the notification). This approach also doesn't seem to be a clean approach as this is not what notifications should be used for.
UIApplication:beginBackgroundTaskWithExpirationHandler
: As far as I understand, this should be used to finish some work in the background (also limited in time) when an app is moved to the background rather than implementing "long-running" background processes.
How can I implement these regular background location updates?
I did write an app using Location services, app must send location every 10s. And it worked very well.
Just use the "allowDeferredLocationUpdatesUntilTraveled:timeout" method, following Apple's doc.
What I did are:
Required: Register background mode for update Location.
1. Create
LocationManger
andstartUpdatingLocation
, withaccuracy
andfilteredDistance
as whatever you want:2. To keep app run forever using
allowDeferredLocationUpdatesUntilTraveled:timeout
method in background, you must restartupdatingLocation
with new parameter when app moves to background, like this:3. App gets updatedLocations as normal with
locationManager:didUpdateLocations:
callback:4. But you should handle the data in then
locationManager:didFinishDeferredUpdatesWithError:
callback for your purpose5. NOTE: I think we should reset parameters of
LocationManager
each time app switches between background/forground mode.Now that iOS6 is out the best way to have a forever running location services is...
Just tested it like that:
I started the app, go background and move in the car by some minutes. Then I go home for 1 hour and start moving again (without opening again the app). Locations started again. Then stopped for two hours and started again. Everything ok again...
DO NOT FORGET USING the new location services in iOS6
It seems that stopUpdatingLocation is what triggers the background watchdog timer, so I replaced it in didUpdateLocation with:
which appears to effectively power down the GPS. The selector for the background NSTimer then becomes:
All I'm doing is periodically toggling the accuracy to get a high-accuracy coordinate every few minutes and because the locationManager hasn't been stopped, backgroundTimeRemaining stays at its maximum value. This reduced battery consumption from ~10% per hour (with constant kCLLocationAccuracyBest in the background) to ~2% per hour on my device
To someone else having nightmare figure out this one. I have a simple solution.
Add timer by using :
Just don't forget to add "App registers for location updates" in info.plist.
Working Code(Entire Stepwise Code)
Step 1
Step 2
Add this code to AppDelegate.m
Step 3 Add This Code in to applicationDidEnterBackground method in AppDelegate.m
In iOS 9 and watchOS 2.0 there's a new method on CLLocationManager that lets you request the current location: CLLocationManager:requestLocation(). This completes immediately and then returns the location to the CLLocationManager delegate.
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.
However if you want to capture locations based on a change of X meters from the last location, just set the distanceFilter property of CLLocationManger and to X call startUpdatingLocation().