iOS: How to use location tracking during predefined time period while saving battery life? - ios

iOS: How to use location tracking during predefined time period while saving battery life?
I need to activate location tracking during predefined time periods (does not matter if app in background or foreground) and need to be sure that battery life is not impacted too much?
PS:
Please not that running location in background with tracking significant changes does not suits because it gives you location after 10 min and only when you passed reasonable amount of distance ... so during driving 40 km I got location only 3 times that will not allow me to catch user movement near some point. If running location more often ...that drains battery upto 40 percent per 6 hours...

I've researched all background modes in iOS very thoroughly recently.
The only deterministic way that will allow you to do that, without location background mode are silent pushes.
You send a silent push to the user and the user returns a location.
You could also use background fetch. But it's very non-deterministic. You can't predict if it indeed will wake up your app, or not.
EDIT:
Please note, that this will not wake up the app that was forcefully terminated.
However, the system does not automatically launch your app if the user
has force-quit it. In that situation, the user must relaunch your app
or restart the device before the system attempts to launch your app
automatically again.

Related

Can we get user current location when app is not running in iOS?

We would like to track user so we want user current location when app is not running also.
We are tracking user when app is in background or foreground mode but in some cases like battery drain, memory footprint issue etc, app going to auto kill so in that case we can not track user. We have used startMonitoringSignificantLocationChanges also but in this case we are getting user location once user moved around 500 meter or more from their current location. If user not move after app kill, we can not track. Is there any way to do this?
Certain types of apps, like turn-by-turn navigation apps, are allowed to run from the background, and can continue to monitor the user's location.
Normal apps cannot. If the system terminates your app you stop receiving location updates. As you say, you can use startMonitoringSignificantLocationChanges or geofencing to get updates when the device moves a significant distance, but I don't think there is another solution for an app store app.
("Kill mode" isn't really a meaningful term.)

iOS Location - Significant Location Change in iOS 8/9 can start standard location service?

Many questions concerning iOS Location tracking have been asked on here, but recently Apple has updated much of their functionality and so many of the answers are obsolete, my question is specifically targeting iOS 8 and 9.
I am interested in creating a location tracking application which will accurately track the user even when the app is closed. To do this, apple states:
If you leave the significant-change location service running and your
iOS app is subsequently suspended or terminated, the service
automatically wakes up your app when new location data arrives. At
wake-up time, the app is put into the background and you are given a
small amount of time (around 10 seconds) to manually restart location
services and process the location data.
So my understanding is, if you have all of the necesarry permission and plist keys present, the OS will wake up your app and allow you to do something for 10 seconds, or if it needs more time it can:
If an iOS app needs more time to process the location data, it can
request more background execution time using the
beginBackgroundTaskWithName:expirationHandler: method of the
UIApplication class.
Now, this says that if my app needs more time to process the location data, it may start a background task (with an expirationHandler) to handle that. When reading about background tasks, I read that background tasks can run for a maximum of 10 minutes
So my overall question is, when my app gets woken up when a significant location change has occurred, is it possible to start the standard location service and have it run in the background indefinitely? Is it possible to start another background task before the first one expires?
EDIT:
From the Apple Documentation it says:
because it wakes the system and your app at least every 15 minutes,
even if no location changes have occurred, and it runs continuously
until you stop it
So my idea is, if the user starts their phone from nothing and never opens the app, after at most 15 minutes (even if they are standing still), the OS will fire my app, in which case I could start a background process that I can start the GPS tracking in, and thus getting accurate GPS location. Would this logic work with the OS?
The main problem is that significant location changes cannot be used for
"accurately track" the user.
Significant means 1000m, since it is cell tower based, and not GPS based.
So your app is woke up when the user moves into the next GSM cell.
This is not acurate enough for acurate tracking.
finally this means you cannot acuratley track when the app is closed, this works only in running app or background running up.
"When reading about background tasks, I read that background tasks can
run for a maximum of 10 minutes"
No, thats not true. My app runs in background and records GPS locations until the battery is drained (8h+). (It does not use the significant location mode)

Initiate location capture at a particular time even if the app is in background or not running

Is there any way in latest iOS to initiate location capture at a particular time each day (say morning and evening ), even if the app is in background or not running.
You should read Background execution. Background jobs are actually not recommended:
An app might move to the background because the user launched a different app or because the user locked the device and is not using it right now. In both situations, the user is signaling that your app does not need to be doing any meaningful work right now. Continuing to run in such conditions will only drain the device’s battery and might lead the user to force quit your app altogether.
As for getting user location check this answer How can I get current location from user in iOS

CoreLocation stops working in background after certain amount of time

I am developing an iOS (7.0+) application for fitness (running) that uses the users GPS location, does a small calculation and transmits the data to a Bluetooth Low Energy (4.0) watch. This process needs to be happening in the background, even when the user locks their iOS device.
I have implemented the following background modes as well:
App communicates using CoreBluetooth
App registers for location updates
I have successfully been able to get everything to work well, except for after a certain amount of time (ex. 2 hours) when the device is locked, the iOS device stops updating the location because I can see that it is no longer sending updating GPS values to the Bluetooth watch. I then have to unlock the device, re-open the app and location services works as it should again.
Does anybody know how to keep location services running the whole time in the background (device locked) without it suddenly stopping the location updates after a certain amount of time? If possible, an efficient solution would be preferred that does not drain the battery too much more than it normal would for using GPS.
Most important: make sure you are setting pausesLocationUpdatesAutomatically to NO before you start the CLLocationManager (see docs).
To minimize battery usage you should also use deferred location updates (more details on SO). This allows the CPU to sleep and save battery while the GPS chip collects location updates for you. It periodically dumps them to the CPU. This may not be for you if you need to update the watch once a second, but if you can update it every 10 or 20 or 30 seconds it will save that many CPU wake ups.

Processing network calls from background. Is it allowed by Apple?

We are working in a groupon-like app where alerts are displayed to the user when he/she enters in the range of an offer.
The client insists on having alerts even when the app is in the background.
Due to the architecture of the system, the app gets the location of the client at intervals and checks with the server if there is any new alert. If so, the app does some processing in the local database and displays a notification.
APN cannot be used since changes in the server are out of reach for this project.
My question is whether Apple would accept it in AppleStore as I have read different opinions about it and Apple discourages its use as in this extract from iOS Developer Library
http://developer.apple.com/library/ios/#documentation/userexperience/conceptual/LocationAwarenessPG/CoreLocation/CoreLocation.html
At wake-up time, your app is put into the background and given a small amount of time to process the location data. Because your app is in the background, it should do minimal work and avoid any tasks (such as querying the network) that might prevent it from returning before the allocated time expires. If it does not, your app may be terminated
Thanks
How often does your app get location from the user? According to Apple's Background Execution and Multitasking, if you are getting the location updates on a regular schedule (I think it's less than 10 minutes), your app can still process in the background if you add location to UIBackgroundModes in your info.plist. With those CLLocation coordinates, you can then process your web service requests.
I personally have not done something like this, so I can't tell you for sure if Apple will reject your app or not. However, if everything is within the guideline and requirements set by Apple, I don't see why they would reject your app.
EDIT:
From the Apple doc:
An app that provides continuous location updates to the user (even
when in the background) can enable background location services by
including the UIBackgroundModes key (with the location value) in its
Info.plist file. The inclusion of this value in the UIBackgroundModes
key does not preclude the system from suspending the app, but it does
tell the system that it should wake up the app whenever there is new
location data to deliver. Thus, this key effectively lets the app run
in the background to process location updates whenever they occur.
I guess even if the app is suspended, it will wake up whenever there is a new location data to deliver.
I think you should reconsider your approach for this application. It sounds like you have decided to build a set of features which are not necessarily well informed by, or a good fit for, the characteristics of the devices the app will run on.
You write that "the app gets the location every n minutes" but that's not how iOS location services work. Querying location services for the current location occasionally is a good approach when your app is running in the foreground but that's not an option once it is suspended or terminated. Instead you need to subscribe to location events, at some level of accuracy, and your app will be notified when the device's location changes. There are no guarantees about the schedule on which you receive these events and it varies depending on the accuracy you request and the speed at which the device is moving.
Additionally, obtaining a location is an expensive operation and can quickly drain the device's battery. Burning through a user's available battery power in an hour or two is a very good way to get your app uninstalled quickly. Where possible you should be using the significant location change service to get low accuracy location updates with minimal power consumption. If you need more precision then consider using boundary crossing events for a defined region or at least reduce the accuracy your have requested as much as possible.
With all that out of the way you still need to work within the limited time your app has to run once started by a location update. That's probably not long enough to make a round trip to the server. If a network connection is already active and the device happens to have low latency you will probably get a response some of the time but I would expect to see the app terminated by the OS frequently. When that happens I don't know that you will continue to receive location updates which might otherwise re-launch the app.
Instead of downloading a list of alerts and displaying them locally a better solution might be to attempt to send your current location to the server via UDP when you see a significant location change. That way you can fire off a network request without waiting for a response. Only some of those requests will still succeed but at least your app won't be terminated. You can then process the locations you receive on the server and send push notifications when appropriate.
I realize that you don't seem to be able to make server side changes. In that case the best you might be able to do is pre-fetch alerts for the nearby region when the app runs (and if you ever manage to complete a round-trip while in the background). That way you could compare location updates to that list and not need to fire off a network request on every location update. Unfortunately it sounds like you might be backed into a corner here with no reliable solution available under your current constraints.

Resources