It's impossible to set desiredAccuracy for significant location change. I have tried and it returned default value 1414 for horizontalAccuracy. Does region change update method is better in terms of accuracy? Is it possible to set it and what is the maximum allowed accuracy for region change update?
There is no accuracy for -monitorForSignificantLocationChange. It is a built in monitor that is designed to be used for broad updates, low on accuracy (but can be accurate enough depending on the application), and great on battery life. It works on the same principal as the -monitorForRegion method. It will update when it thinks you have moved a significant bit (e.g. cell tower transition, new wifi connection, etc). It will also steal/borrow location from other apps that use location as well. So it can be pretty accurate considering how it gets your location.
If you need precise location in the background... you are going to have to sacrifice battery life. The only other alternative is to sacrifice some location accuracy. In my experience, the location returned via the significant change and region monitoring is pretty accurate.
Region monitoring can take accuracy settings. But it mainly just comes off your -locationManager settings. Once you enter the background, you are at the mercy of the system again. I'm not 100% sure if your -monitorForRegion will retain the set level of accuracy, my guess is no. Mainly due to the restrictions on battery life. Hope this helps.
Related
i'm implementing an app where i need to track user's location by the following:
track user's location while the app is in the background or closed
if the user's location is changed for about 2000 meters i should perform an API call.
my approach for this problem is the following:
the first time the user launches the app i start monitoring for a region using his current location
if the didExitRegion is triggered, i perform the API call and replace the current monitored region by a new region using the current location as the center of the new region.
this works fine when the app is in the foreground as the location that is returned from the location manager is accurate.
But if the app is in the background then the location manager will not return an accurate location since it's running for the first time and the first coordinates that are returned are not accurate.
the question is how can i get an accurate location of the user when the didExitRegion is triggered in the background?
thanks
I have not had a lot of luck with didExitRegion: firing reliably; it often fires much further away than the edge of my region.
I'd suggest you use CLLocationManager's -startMonitoringSignificantLocationChanges, if you just need an API call every 2km or so. If your accuracy/precision is important, just register location services as a necessary background state (UIBackgroundModes in your app plist; you may need to do this to use the significant change API from the background, too), and use the normal -startUpdatingLocation, with appropriate distanceFilter and desiredAccuracy field values on your CLLocationManager instance.
Several things happening here.
You mentioned that the region change trigger is a little variable. This is deliberate; to avoid high numbers of triggers being fired as you walk down the boundary between two regions, there is some stickiness to the triggering, in both time and position.
From the documentation (http://developer.apple.com/library/ios/#documentation/UserExperience/Conceptual/LocationAwarenessPG/CoreLocation/CoreLocation.html#//apple_ref/doc/uid/TP40009497-CH2-SW1)
The system does not report boundary crossings until the boundary plus a designated cushion distance is exceeded. You specify the desired cushion distance for a region when you register it using the startMonitoringForRegion:desiredAccuracy: method. This cushion value prevents the system from generating numerous entered and exited events in quick succession while the user is traveling close the edge of the boundary.
Getting an accurate position is no different from normal. You start up the location manager and wait until you get a location update with the desired accuracy. Shut down the manager and use the position.
Because you're running in the background, you only have ten minutes to do this, and you have to tell the OS that you're doing background processing using UIApplication's startBackgroundTaskWithExceptionHandler. Plenty of documentation on that elsewhere.
Hope that helps.
In my testing, I have found that the results of my tesing regionMonitoring on iPhone4S has been a little under par.
That being said, here's what's happening in my testing:
I try to test by setting an alert for the same location when I drive. Sometimes, the alert goes off right on the dime, but most of the time it does not. I have been wondering about the accuracy of this feature. The feature saves power, which is great, but what good is it if timely updates are not received by the device. It defeats the purpose. In this case the users are going to give bad reviews to the app - because they'll have to switch to startUpdatingLocation which is power hungry
Since I drive around for testing, and because the updates are not received - in time, I believe, the alert does not go off. Is my 50.0m radius too small? I can increase it - but the user will be alerted a little too soon!
The feature relies on user's device being passed by one cell-tower to the next. Therefore, is the user out of luck (for using this feature) if he/she happens to be in area where there are not enough cell towers?
Thoughts? Suggestions?
Regards....
50 meters is pretty aggressive even for GPS on a handheld. Try throwing up a wider net first, then switch to more aggressive location monitoring when you were say, within 500-1000m of the target location.
I need to monitor ~400 regions worldwide (some places in capitals with 1-3 km radius). However, there's a limit of monitored regions per app, so I cannot register them all at start. There's no concrete max number of regions in Apple docs, but some say that the safe max number of regions is 10 regions (here).
Apple docs state "To work around these limits, you should consider registering only those regions in the user’s immediate vicinity. As the user’s location changes, you can remove regions that are now farther way and add regions coming up on the user’s path". So, the questions is how and when to manage those regions?
The main callbacks are didEnterRegion and didExitRegion when using region monitoring. So at start, I though that everytime a user would enter some region, I would receive a notification where I could remove old regions, find relevant closest 10 regions and register them. But the problem will occur in cases when a user will not enter the closest region but will move more far away from them (for example fly with airplane from some place to the opposite place of the planet), and I will never get a change to update the list of monitored regions because didEnterRegion will never be called.
To work around this problem I'm thinking to add monitoring of significant changes because I should get callbacks (notifications) everytime one of the triangular cell towers change. So I could use those notifications to update a list of monitored regions quite frequently. That's it, what are your opinions on that?
The first thought that comes to mind is that if you have ten regions to work with, what you really want to do is set notifications on the 9 closest regions of interest and then one region that's not an actual region, but a meta-region around the current location. That way, you're more likely to receive a didExitRegion callback when the user moves away from the current location. At that point you deregister all 10 regions and repeat the process. (i.e. re-register 9 + meta region based on the new current location.)
As you propose, it also probably makes sense to get as many cracks at updating your ten regions as possible, so sure, adding a significant changes notification seems like a decent approach.
Another option, although probably frowned-upon, would be to tell the OS that your app is a VOIP application. This allows you to register for periodic wakeups. You could use these to update your regions. I don't know to what degree Apple audits the use of this facility, but it's something to try.
If I set my CLLocationManager's desired accuracy to be kCLLocationAccuracyKilometer (accurate within a kilometer) will the iPhone deliver a better position eventually, when it gets it ? Or will it stop at my desired accuracy. I can't find this in the documentation.
The idea is that I need a fast fix for the location, but then I would like to go more accurate. Will I have to code this myself, or is it done for me automatically ?
I don't know if the following is 100% correct, but I am pretty sure it works like this: the accuracy filters are primarily designed to save energy. So if you specify that kCLLocationAccuracyKilometer is enough for you and the OS is pretty certain that it can locate you accurately within 1 km using triangulation only, it won't even power up the battery-draining GPS unit. So regarding your first question, the location manager will stop as soon as it reaches your desired accuracy.
Regarding the second question: I don't think the accuracy filter has any influence on the time you receive your first location update. The OS often caches your last known location and will deliver that one almost instantly even if you have specified a very high accuracy. Subsequent location updates will get more and more precise.
You should be able to easily test for yourself if this is indeed the real behavior.
Set the best accuracy you need (but not more, because location services consume too much power). LocationManager will call didUpdateToLocation of your CLLocationManagerDelegate every time accuracy is improved. Stop updating location as soon as you can to prevent battery exhausting.
No, it will stop at the specified accuracy. If you request only kCLLocationAccuracyKilometer then the GPS receiver won't be powered on and it will get no better than WiFi or Cell tower triangulation. [The only exception would be if another app in the background (like TomTom nav) already has the GPS on for high accuracy fixes, then you might get the high (<300m) accuracy fixes too).
If you want better you have to request it and you might as well request it immediately, you'll get the fast fix (1000m accuracy) fix right away and in a minute or two you'll get the high accuracy GPS fix (well, it can take 30 seconds up to 10 min depending on several things). No special coding is required, just specify the accuracy you eventually want.
I am wondering how CLLocationManager's distanceFilter work. According to the docs,
The minimum distance (measured in meters) a device must move laterally before an update event is generated.
So has the phone already gathered the location, but distanceFilter just prevents my call back from getting notified?
I don't see how using the distanceFilter saves battery life, it seems like a Catch-22.
I believe quantumpotato's comment is close. Through Apple's own testing, whatever, they've determined what power level they have to use on the antenna to get readings within a certain accuracy.
As someone who has used this API, I agree with you, it's not perfect and it is somewhat misleading. Think of those flags as "desired levels" and depending on the type of app you want to make, you just need to pick one.