About updating the GPS at the background - ios

I am testing some GPS algorithms with the battery life. I just wrote a very simple app using core-location framework and the app update the gps location every second.
I am wondering how can I change the time interval to update my location, like 10s, 1min, etc?
And when my app is at the background it's stop updating the GPS, do you know how to keep it updating at the background?

be aware that iOS usually does not allow background operations in most cases.
But at least there are three options to "permanently" determine the location:
As you wrote: determine location all the time when your app is not in background. (1)
determine location all the time - also in background. You need to update your Info.plist and add location as a required background service (required for location tracking, Google Latitiude for instance) (take a look at api)
get location updates only when the location changes significantly.
You are not able to change time intervals or something like that. You only have theses three options - and you can get location information only once when you need them, but that was not the intent of your question.

I am wondering how can I change the time interval to update my
location, like 10s, 1min, etc?
This is not possible and it would not make sense, because the GPS chip needs the same power if it a position is needed once a second or evry 10 seconds. Of course you can ignore positions if you dont like them (if they come to often).
The settings of desiredAccuracy influences the power:
kCLLocationAccuracyBestForNavigation: enabled GPS and Acceleration sensors
kCLLocationAccuracyBest: enables GPS but no Acceleration sensors (Cell Tower locating if needed)
kCLLocationAccuracyHundredMeters, kCLLocationAccuracyKilometer, kCLLocationAccuracyKilometer: more likely to use Cell Tower or Wifi locating if available.
That uses less power (more likely) but accuracy is lower.
And when my app is at the background it's stop updating the GPS, do
you know how to keep it updating at the background?
If your read Apple's LocationAwarnessGuide ypou find the info, how to set the correct key in Info.plist file.
Since ios 6 there is an additional variant, which should save more power:
There is the method: didUpdateLocations (note: plural!):
This will deliver all locations at once such that it ios does not need to keep your application living in background. Once the app enters foreground you will receive all positions at once.

Related

how to get the location with the CLLocationManager every 10 secondes?

I want to get the different locations of the users in order to display him the trips he did. But in order to save my user's battery, I want to get his location just every 10 seconds with my CLLocation manager.
I first thought about not implementing the 10 seconds interval and get the user's location every time he move with the didUpdateLocations of the CLLocationManager, but when I simulate a drive I get new location every second and I think this is really bad for the battery, am I right ?
Do not try to second guess the location manager. Your job is to set its properties appropriately, such as distanceFilter, desiredAccuracy and activityType. Apple will use every trick in the book to keep battery usage reasonable given your settings. As the docs tell you:
Core Location manages power aggressively by turning off hardware when it is not needed. For example, setting the desired accuracy for location events to one kilometer gives the location manager the flexibility to turn off GPS hardware and rely solely on the WiFi or cell radios, which can lead to significant power savings.
If the goal is track location in the background, there are special modes for that, which save even more.
Check location every 10 second a lot frequent, it will be drain user's battery too fast.
If you would save battery, you should learn apple guide about location manager.
You need use distanceFilter and desiredAccuracy
Base guide CLLocationManager
Energy Efficiency Guide for iOS Apps
Location Awareness Programming Guide - Tips for Conserving Battery Power
Update
Also you can check how fast user moving CLLocation have speed and adjust activityType

What strategy to adopt to monitor the user location in background?

I want to track the user location in background, in the purpose to show him an alert when he is close to one of his friend.
So i start with CLLocationManager. As far as i know their is only one reliable way to let the app know about the location update even if the user reboot the Iphone or kill the app: startMonitoringSignificantLocationChanges. But the problem is that even inside a city with many wifi, startMonitoringSignificantLocationChanges fire the DidUpdateLocations when the user move around 1km and that is really too much for my need
on the other way startUpdatingLocation is firing DidUpdateLocations at good interval (even too much because even when the user do not move it's fire quite often DidUpdateLocations). But startUpdatingLocation not survive to iphone reboot or app being killed by the user. Also I suspect that even with an accuracy of 100m, startUpdatingLocation use lot of battery consumption.
So the question: What strategy i can use in my app to track efficiently without draining too much the battery the user location at full time? I need an accuracy of around 100m and if possible an interval between 2.5 - 5 min for each track (i didn't find any option to specify a delay to wait before to catch a new location)
Actually i think to do something like this :
2 locationManager, 1 GPS and 1 Significant Changes
when app start I do with significantChangesLocationManager: startMonitoringSignificantLocationChanges and startMonitoringVisits
I also call GPSLocationManager startUpdatingLocation to retrieve the accurate user position. I set up PausesLocationUpdatesAutomatically(true) so that the GPSLocationManager will stop by himself soon or late
on DidUpdateLocations raise by the GPSLocationManager I start monitoring region enter/exit (100m radius around the obtained latitude/longiture) with significantChangesLocationManager
What do you think of such strategy ?
Even though you will receive more triggers than you need, as you already said, you can use startMonitoringSignificantLocationChanges. It is implemented in a very energy efficient way. It allows the app to be terminated and only be woken up again when iOS thinks the device has moved significantly. Another advantage would be that your app doesn't need the location background mode, which could raise questions during an app review.
The startUpdatingLocation let's the app continuously update the location of the device, even though you only receive a couple didUpdateLocations: events. Also, iOS cannot shutdown the app while updating is active, so it consumes a lot of battery.
You can also consider geofencing, with an exit geofence around the current location. However, significant location updates will be more reliable. Exit geofences won't trigger anymore once you're already out of a geofence, which could happen when the phone is turned off inside a geofence and turned back on outside. This solution has the same advantage of not needing a background mode.
As far as I understand your use case, startMonitoringSignificantLocationChanges sounds as the best option. You won't have control over the exact time interval and distance it triggers, but it is very energy efficient and easy to use.
As mentioned in comments, here are some approach I had to do in order to get the expected result in our app.
Significant Location Updates - is good to wake your app up once it gets finished by some reason that you can't control, so even if you lose some points, it will get back in some seconds/minutes.
This is not good if you need a good accuracy, as you cannot control the distance / time or whatever, iOS will update locations when mobile antenna is changed, wifi connection, turn air plane mode off and on but will not give a sequence of gps points.
Start Location Updates - Best accuracy but battery drainer. So you can't just turn it on let it go. You must implement some controls over it.
Background tasks - The only way I've found to keep my app alive.
The way you can combine is:
Have 2 location managers isolated, one for significant location change and one for start updating location;
Start your app with both turned on;
Inside your didUpdateLocations you can create your logic to start and stop your background tasks;
Create methods to start and pause your location manager and create your timers to control that;
inside your bg task you will start or pause your update locations, but never stop it, just if for example, your user logs out and you want to stop location;
keep significant location update location manager alive forever, if for some reason iOS decide to kill your app when in bg, it will ensure that in a given moment your app will come back to life;
For battery live, try do not use kCLLocationAccuracyBestForNavigation for accuracy as when it starts it eat a LOT of resources, most of time, kCLLocationAccuracyBest is more then enough and if you can use kCLLocationAccuracyNearestTenMeters;
Your didUpdateLocations will give you mostly a bunch of points, try to get only those with good horizontalAccuracy, around 20 meters for us was good enough, so let it work and once you have a point with good accuracy, you can pause it again.
Below you have some links that helped me a lot to implement our solution, none of those have a "as is" solution, as I said, I had to mix all of them and test a lot to understand its behaviour and make the necessary adjustments.
https://github.com/voyage11/Location
http://mobileoop.com/background-location-update-programming-for-ios-7
http://zaachi.com/2013/09/30/ios-locationmanager-location-update-in-my-own-interval-with-application-in-the-background.html
In addition to Mark's answer I would like you to explore pausesLocationUpdatesAutomatically which can help you save battery from draining when user has stopped Apple Documentation
Allowing the location manager to pause updates can improve battery life on the target device without sacrificing location data. When this property is set to true, the location manager pauses updates (and powers down the appropriate hardware) at times when the location data is unlikely to change. For example, if the user stops for food while using a navigation app, the location manager might pause updates for a period of time. You can help the determination of when to pause location updates by assigning a value to the activityType property.

How to avoid battery drainage if the app is using GPS even when the app is in background

I have to build an app that will have the following features :-
A way to add users and their data in a database. (which will be parse)
The app will access the location updates of the user (say after every 10 minutes or when the user has moved a significant distance). This will be done even when the app is in background. These locations will then be updated to the parse database as and when the new locations are received.
I am a beginner, so any suggestion to how i should approach this will be appreciated. Most importantly, i have the following problems :-
The app will also run in the background and will regularly use GPS. This will drain a lot of battery. How can i avoid this? (The precision of the locations are important)
The app will regularly update these locations to the parse database and will have to make regular API requests which will add to the cost. How can i minimise this?
From your description what you want is "significant location change" monitoring, which is built in to CLLocationManager. Instead of running continuous location updates, you tell the location manager to send you "significant" changes in location, i.e. when the user has moved some undocumented "significant" amount. It's specifically designed to minimize battery drain, so you don't need to bother disabling and reenabling it. Instead iOS makes sure you're using as little battery as possible to get the updates.
The CLLocationManager discuss the approach in some detail, but the basics are:
Once you've created your location manager, tell it to start significant location updates:
locationManager.startMonitoringSignificantLocationChanges()
Location changes are provided to the delegate via the same locationManager(manager:didUpdateLocations:) method used for continuous location updates.
iOS will wake your app up to let it process location updates.
You'll want to periodically update your location rather than leave GPS on continuously. Here's a tutorial covering CLLocationManager you may find helpful.
Without specific code, I can't give you a specific answer, but generally speaking you'll want to periodically turn on CLLocationManager, get your location, and turn it off again until the next update. You can also configure the accuracy of CLLocationManager--the more specific your location, the more battery power is required.
Here's another tutorial on CLLocationManager to take a peek at, too.

Why are SLC updates always 5 minutes?

Both on the simulator and the device, my delegate for LocationManager is getting didUpdateToLocation:fromLocation: exactly every 5 minutes while traveling while monitoring SLC. Why is this?
According to the CLLocationManager Class Reference:
For applications that do not need a regular stream of location events,
consider using the startMonitoringSignificantLocationChanges method to
start the delivery of events instead. This method is more appropriate
for the majority of applications that just need an initial user
location fix and need updates only when the user moves a significant
distance. This interface delivers new events only when it detects
changes to the device’s associated cell towers, resulting in less
frequent updates and significantly lower power usage.
My guess is that when your app is running in the background, iOS only "wakes" the app every 5 minutes to check whether you have made a Significant Location Change, in order to conserve battery life
There might be some useful information for you also in this previous question.

Registering for significant-change location versus startMonitoringForRegion:desiredAccuracy:

Registering for significant change location the app only receives coarse location updates (if the device moves from cell to cell), however according to this post
If background applications can't launch automatically how does Cardcase launch on a location change?
its also possible to use startMonitoringForRegion:desiredAccuracy: and have the app woken up when a location change occurs.
Presumably the desiredAccuracy can be pretty fine, so does this imply its a back-door way of registering for significant changes to location but with a fine grain?
Is it permissable by the app store therefore?
In my testing I have observed that the region monitoring is sometimes not very accurate, i.e If I drive past a region I might not get any indication of having entered or exited the region. (under the hood it might be using something similar to significant location change)
Also the desiredAccuracy here is really the buffer (in meters) around the region where notifications should not be generated , this is to prevent multiple notifications if you are at the edge of a region.
Not really. You have to specify a specific region, and you only get sent notifications when the region is entered/exited.
It's the same mechanism that the Reminders app uses for sending reminders, they create a region around the location, for instance work, and register for region notifications.
While it might theoretically be possible to create lots of little regions next to each other, it's not really intended for that and will probably cause problems down the line.

Resources