Use of Standard location service for tracking traveled distance in a foreground/background app - iphone

I have to develop a kind of GPS navigation application that needs to constantly keep track of the position of the user, which is moving by car.
In the specific, I don't have to display the current location on a map but just to record its position with the best possible precision in order to calculate the total distance traveled.
Of course the application needs to continue its work in background if the user switch to another app, a phone call come in or something like that…
From the tests I have made and from what I have learned from this useful post (and from the documentation), it seems to me that the best choice in this case is the Standard location service, with the application configured with the UIBackgroundModes = location in the .plist file.
In this way it will continue to receive the location updates even if in background and it will never be suspended by the OS (this is actually true only if [locationManager startUpdatingLocation] has been called). This is also confirmed by this guys.
I have personally verified that is true simply by running the app with Instruments and the Memory monitor module where you can see the various flags about the app states, putting the app in background first with UIBackgroundModes set to location and startUpdatingLocation active, and after without it.
1) I'm now wondering what to do when the app is terminated when it is tracking the position. I don't want to loose any location updates so I need to wake up it again whenever a new update is available.
The documentation say:
Important: The applicationWillTerminate: method is not called if your
app is currently suspended.
But because in my case it will be never suspended (it will stay in background but not suspended), my logical conclusion is that applicationWillTerminate will be always called and so I could register for a Significant location update or Region monitoring inside of this method in order to be waked up and then restart the Standard location service.
Is applicationWillTerminate the right place to put this code?
2) An application working in background but not suspended could be terminated by the OS for no other reasons than a very low memory condition or for my app don't properly respond to a memory warning? (the user could also manually close it). I was concerned if applicationWillTerminate wouldn't be called in some way.
3) Could Apple not approve an app which constantly use the standard location services in background because of its quick battery drain?
Have you ever had approve problems for similar apps?

since you are asking many questions which you shoukd not do here, i cam give you only aswrs to a part of it.
if the app is terminated, then you cannot restart it anymore.
This is usually the case when the user terminates the app.
Dont worry Apple ( ios) will not terminate your app. your app will not use much memory, games with huge bitmap graphics are more likely to be termin.
evry gps app will drain the bat. that is not a reason for not aproving.
suspended means that app is not in background mode, it is sleeping. you will not receive Gps, so there is no need to call you on terminate. you have to save data before, see the apple docu on background modes and app life cycle.

Related

Using both startUpdatingLocation and startMonitoringSignificantChanges?

Is it advisable or any issues with calling both startUpdatingLocation and startMonitoringSignificantChanges vs. one or the other? I understand the benefits of the significant changes call re: battery life, but when using it am seeing inconsistency with it firing the didUpdateToLocation, sometimes doesn't fire at all even though I know I've setup locations where I know it should fire when I'm at the location but doesn't. I'm able to verify my results for my app vs. another app that does very similar behavior, including both mine and the other app running in the background (UIBackgroundModes does have the 'App registers for location updates' setting in the plist). If I try using just the significant changes, the results are not consistent. If I use both, I get accurate results + the added benefit (need) for getting notified if/when the app is terminated. I want to not kill the battery life by using the startUpdatingLocation, and have tried calling the stopUpdatingLocation and then subsequently calling the startMonitoringSignificantChanges in the applicationDidEnterBackground in order to help conserve battery life while in the background, but can't seem to understand why relying on the significant changes is not working consistently.
Apple suggests that you use -startUpdatingLocation while your app is in the foreground, and -startMonitoringSignificantChanges while in the background. Using both while the app is in the foreground is likely just a waste and more likely to be more work to handle the events than just monitoring -didUpdateToLocation. Upon backgrounding, you can switch off the GPS mode and switch to something more low powered. You have to assume that the user won't care as much for accuracy once you've been backgrounded or closed.

Stopping CoreLocation background updates

My app registers for background location updates (not Significant Change. I need more granularity than kilometers)
That part works fine. I just want to stop the updates after the app has been in the background for 60 minutes. The way I'm doing it right now is to call stopUpdatingLocation in my CLLocationManager delegate.
However, I am unsure if this will actually stop my app from receiving background location updates, or if it will, but will just ignore them. Ideally, I'd like to not have my app be responsible for battery drain except for a small period of time after user activity.
Apple's documentation tends to send me in circles on this one. Right when I think "Executing Code in the Background" is about to spill the answer, it directs me to "Location Awareness Programming Guide." Right when that one is about to get specific about this question, it sends me back to "Executing Code in the Background." :)
I'm not sure whether your app has total control over this, but the docs for stopUpdatingLocation do state the following ...
Disabling event delivery gives the receiver the option of disabling the appropriate hardware (and thereby saving power) when no clients need location data
Which would suggest that should your app be the only one requesting background location data, and you request it to stop the GPS receiver would disable the appropriate hardware to save on power, which I think it was you're looking for.
What I can suggest is that you enable Power logging in Settings -> Developer, then run your app for an hour or so to a point where you think GPS is disabled, run for another hour and then compare the power usage in Instruments. This should provide you with a much clearer picture.
Calling stopUpdatingLocation will indeed stop GPS and so on, but if you place this call inside locationManager:didUpdateToLocation:fromLocation of your CLLocationManager delegate, then it might never be called.
Keep in mind that this method is only executed whenever a more accurate position or a (according to the active distance filter) significantly different position is available. If the device does not move at all and if the circumstances affecting the accuracy also do not change, it may not be called for hours (I have verified it for several minutes myself) and GPS will also stay enabled for this long.
For apps that only work in the foreground, you can use an NSTimer of 60minutes, but for apps that run in the background, the closest to a working solution that I have found so far, is a scheduled UILocalNotification. But even that requires the user to confirm an alert, before the app is restarted and able to turn the GPS off.
Maybe beginBackgroundTaskWithExpirationHandler: is the key to a better solution, but I have not completely figured it out, yet.

iOS 4 application lifecycle behavior of standard location service running in background

I'm working on a location tracking application that uses both the standard location service and significant change location service in the background (my app is registered for background location updates in iOS 4+) as applicable. Thanks to this question I have a solid understanding of how significant change comes back from the background state and relaunches from a terminated state. However, I'm still not clear on how the standard location service behaves in these instances. Could anyone break down the exact behavior of the standard location service running in the background?
Specifically:
How does the standard location service behave when you leave it running and the app suspends into the background? From my own testing, I've seen that it will continue waking up to receive callbacks on locationManager:didUpdateToLocation:fromLocation: (I have it send the location out a socket and I can see it on the network). Is there a time or memory limit for this callback to process?
Does the standard location service continue to run even when my app is terminated? That is, will it ever relaunch with application:didFinishLaunchingWithOptions: with UIApplicationLaunchOptionsLocationKey the way the significant change service does? I assume it the CLLocationManager would also need to be restarted in this case, as the significant change service does.
Thanks.
Answer to both 1 & 2, If you have registered your app as using background location then your app does not get terminated and continues to run in the background until you do this:
[locationManager stopUpdatingLocation];
So, there is no time or memory limit however there is a battery limit. If your battery is low, all apps using gps will be closed. Since your app is not terminated in normal circumstances, either it is not required to or it does not relaunch (after being terminated coz of battery) with UIApplicationLaunchOptionsLocationKey
Standard and significant services are different in this manner that significant wakes up the app whenevr there is a location update but standard makes app run continuously and hence drain battery.
Before you choose what service to use consider reading the Location-Awareness Programming guide.

iPhone: stopMonitoringSignificantLocationChanges when app quits

I want to stopMonitoringSignificantLocationChanges when the user is killing the app from the multitask bar (switch bar) like the Waze GPS App does.
(i also want to cancel all LocalNotifications)
the problem is, that after an application get's suspended, applicationWillTerminate doesn't get called.
The way Waze does it is by running the NORMAL LOCATION SERVICE in background, not the "significant location service".
a special option that can be set in the plist file.
there is no way to close the Low Power mode of location services - "Significant location service" when the user kills the app, because it was not intended to be used this way.
I guess I will simply have to follow apple's standards using significant location service.
did you have a look at this post: Behaviour for significant change location API when terminated/suspended?
Lots of interesting things in it.
In particular, you should stopMonitoringSignificantLocationChanges on entering background and register for significant location changes with a Service

applicationWillResignActive impact on application?

I am writing an application that records a users position at regular intervals whilst walking. I am using an NSTimers to schedule "startUpdatingLocation" followed by calling "stopUpdatingLocation" shortly afterwards to save as much battery as possible.
I want the user to be able to start the application and lock the phone thereby putting the application in an inactive state. My question is when this happens my application (when running via Xcode) seems to continue as normal, but I am curious if there are any differences in the way the application runs in this state as apposed to when the application is running as active?
From the docs it only mentions "applicationWillResignActive" with regards to the application passing through that state on its way to the background. I am more interested in how an application behaves when a used locks the UI and puts the phone away, I just want to make sure its going to keep doing what it should be doing or do I need to take extra measures?
When you app hits applicationWillResignActive it can continue to receive location updates if you use the UIBackgroundModes option in your apps info.plist.
Add the location key.
It is important that you do not use a timer in the background as timers will run but hold their "fire" until the app becomes active again. Thus you will only get one read when the user comes back to the app. The GPS location accuracy level is what will drive how much the battery is affected.
In your app description in the App Store, Apples requires:
Continued use of GPS running in the
background can dramatically decrease
battery life.
You app will not be allowed to go live until the above text is in the description for the user to read.
You should definitely be testing this on a device. The simulator doesn't auto-lock, for instance.
applicationWillResignActive is called when the user presses the home button, when another app fires a notification the user accepts (including when a call comes in), and when the device locks.
Look into the multitasking documentation, and what it has to say about background location updates.
My suggestion is that you conserve the user's battery by:
- starting a timer, which when fired, starts location updates (and stops the timer)
- when you get an adequately-accurate position record, stop location updates and restart the timer
- if location updates fail, restart the timer for a longer period. Maybe they're underground.
The most efficient approach is using significant location update service while your application is in the background or the screen is locked on your app. You might get one update every ten minutes or so.
Remember also, the user can disable your app's location services permissions. Especially these days...