In Significant change location service, I've used the method "startMonitoringSignificantLocationChanges" but it returns cached Location only, it doesn't return updated location information.
I've used Swift language.
Assuming you are keeping a strong reference to your location manager object, please ensure you are calling locationManager.requestAlwaysAuthorization() for startMonitoringSignificantLocationChanges to function well.
EDIT:
From Apple Documentation:
Regardless of which location service you use, location data is
reported to your app via the location manager’s associated delegate
object. Because it can take several seconds to return an initial
location, the location manager typically delivers the previously
cached location data immediately and then delivers more up-to-date
location data as it becomes available. Therefore it is always a good
idea to check the timestamp of any location object before taking any
actions. If both location services are enabled simultaneously, they
deliver events using the same set of delegate methods.
Wait for some time and ensure you make a physical location change for location manager to return back the right location. Note that Significant Location Changes mode is always slower than the regular one.
Related
to retrieve location of the user when the app is in the background i first do startMonitoringSignificantLocationChanges then when DidUpdateLocations is fired i do with a second CLLocationManager startUpdatingLocation to retrieve the exact geoposition (with an accuracy on 100m)
The problem is that the doc say:
Calling this method causes the location manager to obtain an initial
location fix (which may take several seconds). After that, the receiver generates update events primarily when the value in the distanceFilter property is exceeded.
So as i understand the first DidUpdateLocations will be called with a fix not really accurate, and with time other DidUpdateLocations will be called with more accurate location.
Now the problem is, when (and how?) did i need to stop the startUpdatingLocation ? i m in the background so i can't use any timer or think like this
Since you require a 100m accuracy, you can simply check the location horizontal accuracy property. If the condition is fulfilled you can stop the core location manager otherwise you keep tracking.
Be aware that usually the callback of significant monitoring changes keeps your app alive for a minimum amount of time.
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. (You must manually
restart location services in the background before any pending
location updates can be delivered, as described in Knowing When to
Start Location Services.) Because your app is in the background, it
must 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 will be terminated. 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.
I'm working with CLLocationManager class. I want to get location updates periodically. I had found two methods to get location in didUpdateLocations method, that are startUpdatingLocation() and startMonitoringSignificantLocationChanges(). If I have to track location updates in foreground mode also then which method should I use?
The most important difference between the 2 is this:
startMonitoringSignificantLocationChanges: it does not rely on the value in the distanceFilter property to generate events. The receiver generates update events only when a significant change in the user’s location is detected
startUpdatingLocation : the receiver generates update events primarily when the value in the distanceFilter property is exceeded
So, if you want more precision, go for startUpdatingLocation, at the expense of more battery consumption, but more precision of the location. It really depends on your goal, you should evaluate the tradeoff.
startMonitoringSignificantLocationChanges initiates the delivery of location events asynchronously, returning shortly after you call it. Location events are delivered to your delegate’s locationManager:didUpdateLocations: method. The first event to be delivered is usually the most recently cached location event (if any) but may be a newer event in some circumstances. After returning a current location fix, the receiver generates update events only when a significant change in the user’s location is detected. Apps can expect a notification as soon as the device moves 500 meters or more from its previous notification.
To sum up startMonitoringSignificantLocationChanges will provide you with location only when location changes by some significant amount which is roughly around 500 meters or after some fixed time say 5 minutes. Where as startUpdatingLocation will provide you with location based on distanceFilter property set. Default value of distanceFilter is kCLDistanceFilterNone which reports all the movements.
startUpdatingLocation returns immediately. Calling this method causes the location manager to obtain an initial location fix (which may take several seconds) and notify your delegate by calling its locationManager:didUpdateLocations: method. After that, the receiver generates update events primarily when the value in the distanceFilter property is exceeded. Updates may be delivered in other situations though. For example, the receiver may send another notification if the hardware gathers a more accurate location reading.
I have gone through many tutorials but not able to find the right solution. I am working on location base application where I need to fetch user's current location, it doesn't matter even if the application is running in foreground or in background. So when i kill or terminate the application is it possible to fetch user's current location?
Yes it is possible. You will have to use method startMonitoringSignificantLocationChanges. According to CLLocationManager documentation
If you start this service and your application is subsequently
terminated, the system automatically relaunches the application into
the background if a new event arrives. In such a case, the options
dictionary passed to the application:didFinishLaunchingWithOptions:
method of your application delegate contains the key
UIApplicationLaunchOptionsLocationKey to indicate that your
application was launched because of a location event. Upon relaunch,
you must still configure a location manager object and call this
method to continue receiving location events. When you restart
location services, the current event is delivered to your delegate
immediately. In addition, the location property of your location
manager object is populated with the most recent location object even
before you start location services.
As per iOS CLLocationManager API startmonitoringsignificantlocationchanges will inform my app when there is significant change e.g. 500 mtrs or more.
But i want in my app like my app will get notified only when user/device enters into new city. App should automatically open if its in closed state.
NOTE: its not map/navigation application, so i don't want to my app keep monitoring user's location data and at the end drain device's battery.
Please suggest some solution.
It will execute your application. (sorry that it's not a comment - but it's too long for comment).
See details below (from Apple Documentation)
To start region monitoring, configure the appropriate region object and pass it to the startMonitoringForRegion: method of your location manager. In iOS, registered regions persist between launches of your app. If a region boundary crossing occurs while your iOS app is not running, the system automatically wakes it up (or relaunches it) in the background so that it can process the event. In this case, the options dictionary passed to the application:didFinishLaunchingWithOptions: method of your app delegate contains the key UIApplicationLaunchOptionsLocationKey to indicate that your app was launched because of a location-related event. During the relaunch process, you must recreate your location manager object and assign a delegate capable of handling region-related events. After you do that, the system delivers the region notification for which your app was launched. All of the regions you configured previously are made available in the monitoredRegions property of any location manager objects you create.
I think you need method of CLLocationManager class:
- (void)startMonitoringForRegion:(CLRegion *)region
Parameters
region
The region object that defines the boundary to monitor. This parameter must not be nil.
Discussion
You must call this method once for each region you want to monitor. If an existing region with the same identifier is already being monitored by the app, the old region is replaced by the new one. The regions you add using this method are shared by all location manager objects in your app and stored in the monitoredRegions property.
Region events are delivered to the locationManager:didEnterRegion: and locationManager:didExitRegion: methods of your delegate. If there is an error, the location manager calls the locationManager:monitoringDidFailForRegion:withError: method of your delegate instead.
An app can register up to 20 regions at a time. In order to report region changes in a timely manner, the region monitoring service requires network connectivity.
I need to get exact location (as much accurate as possible) in background while making a call to a phone number (The call will be made from app). As far as I understand from documentation, I can listen to significant changes of location in background. I am wondering how accurate is a significant update and when will it trigger.
I need the location where the call is made because it will be an emergency call. And it's not a good idea to listen to location in foreground and then make a call because it will be an emergency situation - call will be made immediately.
Is there a solution to get accurate location of user in background? What do you recommend?
Edit: Location will be sent to server immediately.
As for the accuracy, you can get accurate location in the background, under those conditions:
Getting Location Events in the Background
If your application needs location updates delivered whether the application is in the foreground or background, there are multiple options for doing so. The preferred option is to use the significant location change service to wake your application at appropriate times to handle new events. However, if your application needs to use the standard location service, you can declare your application as needing background location services.
An application should request background location services only if the absence of those services would impair its ability to operate. In addition, any application that requests background location services should use those services to provide a tangible benefit to the user. For example, a turn-by-turn navigation application would be a likely candidate for background location services because of its need to track the user’s position and report when it is time to make the next turn.
As for getting location during phone call, I didn't use it myself, but navigation apps like 'waze' do inform turns and navigation events during a phone call so I guess what you ask is possible.
If I understand your needs, you have 2 options:
If you think that the user will be static then simply get the user location right before the call is made. Or better when your app is lunched to make the emergency call.
If the user is moving then you can 'ask' to get background location events. Even then you should consider using 'significant-change location service' as you don't need more then the user location. The standard 'location services' are used for navigation 'Turn by turn' services.
*LAST COMMENT *
If your app is an emergency app you shold read the "Tips for Conserving Battery Power" in the previous link. you don't want your user battery to empty while tracking his location.
Can't you like add that flag in your app plist file to request Location Service to be running in the background mode.
Then in your app, when the user presses the "call" button, you can do your normal CLLocationManager didUpdateToLocation, right before you perform the call.
In your didUpdateToLocation method, you can record the user's location either in a TXT file written to the application sandbox Library/Cache folder or you can use NSUserDefaults.
Note: I've written an app that records the user's GPS location as they drive even when the user presses the lock screen, so I am confident your app can write the GPS coordinate to a TXT file even when the app is minimized, as long as you start your location manager.