To get the last know geolocation, I have:
CLLocationManager * locationManager = [[CLLocationManager alloc] init];
CLLocation * lastKnownLocation = [locationManager location];
Does the lastKnownLocation reflect the last location my app has been called back with or does it reflect a global iOS system level last location (which other app or the iOS might have queried for)?
I am doing this instead of actively querying for user's location so I don't waste the user's battery.
If user has not given permission to access location, obviously lastKnownLocation should be nil. My question is specifically for the case where user has given my app permission to access location.
Generally you should not simply rely on the existing (if any) value returned from location unless you check its accuracy and time stamp (compared to your requirements). It's better to start startUpdatingLocation until you get a location which does match your accuracy requirements and then either stopUpdatingLocation or switch to stopMonitoringSignificantLocationChanges (if available).
The location returned from location is very dependent upon history, so you can't definitely say one way or the other that it will be. You always need to verify the accuracy for your purposes.
I know this is an old question but for the sake of being complete and maybe others ending up here:
The CLLocationManager class has the location property which returns (according to official Apple docs):
The most recently retrieved user location.
This method will return nil when no location is known.
Related
I'm working on a navigation application, everything working in terminated, background and fore ground state.
But in one scenario of terminated state startMonitoringSignificantLocationChanges is not handling itself.
The issue is
when i start the startMonitoringSignificantLocationChanges and killed the app, then I'm getting location event like after 0.5-1km because of that it draws straight line from my initial position to the first location event I get.But when the location event starts coming then everything work smoothly
Same issue occur again when in the middle of travelling I open the application to check my route status and then kill the application, again location events start coming after 0.5-1km and a straight line was drawn.
The code is straight
significantLocationManager = CLLocationManager()
significantLocationManager?.allowsBackgroundLocationUpdates = true
significantLocationManager?.pausesLocationUpdatesAutomatically = false
significantLocationManager?.requestAlwaysAuthorization()
and call the tracking when user needs by
significantLocationManager?.startMonitoringSignificantLocationChanges()
Rest I have handled the incoming location event in the app delegate to save in db.
So question is how should I handle this scenario in which straight line is drawn ?
From Apple documentation:
Apps can expect a notification as soon as the device moves 500 meters or more from its previous notification. It should not expect notifications more frequently than once every five minutes. If the device is able to retrieve data from the network, the location manager is much more likely to deliver notifications in a timely manner.
If you need to receive location updates as soon as possible I'd recommend to use startUpdatingLocation() with desired distanceFilter of CLLocationManager.
You can use Location update in background mode. From Apple documentation:
When you start the significant-change location service, a recently
cached value may be reported to your delegate immediately. As new
location data is obtained, the location manager calls your delegate's
locationManager(_:didUpdateLocations:) method with the updated values.
The locations parameter always contains at least one location and may
contain more than one. Locations are always reported in the order in
which they were determined, so the most recent location is always the
last item in the array, as shown in Listing 2.
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let lastLocation = locations.last!
// Do something with the location.
}
Here you will get the last cached location in your device, and it should be very precise if you have location service turned on in your device of course.
Another thing to know is this. Note form Apple:
The significant-change location service requires authorization. For
more information Requesting Authorization for Location Services.
My app features a map and when the user long presses on it, I need the current phone location to appear on the map. As #Chen advised it looks like getCurrentLocation() is the proper method to use in my case. Please note that I don't want to use a LocationListener because I want the user to have control on when they want to update their location.
Moreover I chose this manual location update because #Shai-Almog discouraged location polling. So after reading this post I first set the timeout to 20 s as written below to get the current phone location :
Dialog ip = new InfiniteProgress().showInifiniteBlocking();
Location currentLocation = locationManager.getCurrentLocationSync(
ParametresGeneraux.LOCATION_TIMEOUT_MILLI);
// We try to get something
if (currentLocation == null) {
currentLocation = locationManager.getLastKnownLocation();
}
ip.dispose();
But it was not sufficient and the last known location was "always" provided (I did not count maybe 5 times in a row) although the little location icon appeared in the toolbar. So I set it to 40 s but the actual current location did not come either after this twice as big amount of time (only the last known location which is > 2km away was provided).
However if I start Google Maps on Android (KitKat), the location is instantaneously accurate. And then if I go back to my app and press the map the current location is found. Actually I found a post dealing with a difference in accuracy between Google Maps and Android API but it was pertaining to Shangai / China, not the EU (France).
Consequently my question is twofold :
first how can there be such a huge difference on the same device between Google Maps and Codename One ?
then if I don't set a timeout to getCurrentLocation() how can I interrupt the location searching when the user is fed up waiting ?
Any help appreciated,
BR
Instant location will work if the Google Maps location services is turned on. If you enabled or disabled one of the android.playService build hints you must also enable android.playService.location=true to get the fast location service used by maps.
I am trying to fetch location data in an iOS application using Core Location framework. I am using below code snippet to initiate the location manager.
CLLocationManager *locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
locationManager.distanceFilter = 5;
I understand that I can change the accuracy of the location data using desiredAccuracy parameter. But how does actually core location work? Does it fetch using GPS antennas or WiFi or cell towers? Can I ask the location manager to fetch only using GPS or only WiFi or only Cell tower?
As rmaddy mentioned, you do not have control over how the location is determined. In other words, you cannot ask the app/device to use one of GPS/CellTower/Wifi.
However you can, through the type of location update, tell the App whether to "favor" GPS or Cell Tower.
If you do:
[locationManager startUpdatingLocation];
Then the app will definitely use GPS + maybe wifi and/or cell tower.
if you do:
[locationManager startMonitoringSignificantLocationChanges];
Then the app will definitely use cell tower and provide a location update when you move from one cell tower to the next. This should reduce your GPS usage and battery usage. Having said that, I am not sure if in this case, GPS usage is completely eliminated.
Hope this sheds some light.
Update
See Apple's link:
CLLocationManager Class Reference
But in general you can always get one update (will arrive through the delegate method) and then use:
[locationManager stopMonitoringSignificantLocationChanges];
You will have to do a bit more work and check the timestamp of the location to make sure the update is not one of the old cached one.
You can't force CL to use GPS or Wifi or cell but you can set desiredAccuracy so that it will probably do what you want.
If you set desiredAccuracy to 500 or higher it will use Wifi or Cellular if available, and leave the GPS off. If you set desiredAccuracy to 300 or less it will have to use GPS.
GPS signal is lost when App is resumed from long time suspend mode.
And/or after user goes into a building where GPS is weak and then resumes the App.
The blue dot disappears and the map is centered at lat:0 long:0 ( which is somewhere in
the ocean near Nigeria-Africa )
If you launch another GPS app at that point in time, such as Apple Maps,
you DO see the blue dot, even if not so accurate.
The only way a user can fix it - is by killing my app completely and start it again.
It happens on both iOS 5.x and iOS 6.x.
Before going into details, I would really like to ask:
Does anyone encounter this problem ??
Its very annoying but, I couldn't find anyone complaining about this
anywhere on the web - very weird.
I'm using normal CLLocation with showUserLocation=YES,
Nothing magical, no special accuracy tuning or whatever, just simple default
implementation.
I have already tried restarting every possible component when App is resumed;
showUserLocation=NO;
showUserLocation=YES;
or
[locationManager stopUpdatingLocation];
[locationManager startUpdatingLocation];
or
even releasing locationManager and initialize it again doesn't help!
( also tried restarting it with a delay using dispatch_after )
Is there any programmatic way to force RESET the GPS signal or CLLocation in ios ?
Will appreciate any relevant discussion!
I Think you default Location is set "None" so this type of issue created.
Go to
Edite Scheme..
|
|
"Run YourProjectName" / Left Hand Side
|
|
Select "Option" Tab
|
|
Default Location
|
|
Choose any Location such like , "London England"
When you say that you've tried stopping/starting the CLLocationManager object, are you saying that the call-back you get in your delegate gives you a 0,0 coordinate, or are you trying to access the location directly using the location property in CLLocationManager?
I work on a location based app and one thing I can tell you is that you cannot count of directly getting the location of a CLLocationManager object. The only reliable way to get location information is to rely on the callback of the CLLocationManager class by implementing
-(void) locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
The way I handle CLLocationManager in my app (now I'm not saying this is optimal or ideal for your use case but it does allow us to provide a solid location-based experience to the user on app launch/resume)
Wrap the CLLocationManager into a location management class (usually using a singleton) - I think this can be a subclass of CLLocationManager but in my case it's just a subclass of NSObject with a CLLocationManager object as a property
Store the last known valid location in this singleton, and then write it to disk (NSUserDefaults or another location - need to re-check if you're allowed to store user location in NSUserDefaults but we've done it in our app and doesn't seem to affect the approval process)
Re-implement a way to get the current location in your custom class - basically check if CLLocationManager is returning 0,0 and if it is, return your cached position instead
Not strictly necessary but if you have multiple views/pages that need to use the location, implementing the observer model works well (since your singleton is now CLLocationManager's delegate, you need to have a way to pass this information on to your view controllers).
With the above, on my map page (or wherever I'm displaying user location) - I basically update the map with the cached location once (in viewDidLoad) and then I allow one update to the map through the delegate-callback. Once that call-back is received, I then set showsUserLocation to YES (if the call-back isn't called, then you don't have a valid location yet and so setting showsUserLocation at that point doesn't do anything).
I hope this helps and feel free to let me know if you have any further questions!
I have something like this:
CLLocationManager *locManager = [[CLLocationManager alloc] init];
locManager.delegate = self;
locManager.desiredAccuracy = kCLLocationAccuracyBest;
[locManager startUpdatingLocation];
But I need to get below the latitude and longitude user. Obviously, trying to obtain locManager.coordinate just below the startUpdatingLocation my application crashes.
How can I make a condition to perform a process after the user allows sharing of location and it has been found?
Thanks in advance.
After calling startUpdatingLocation it can take some time until you get a location. The system first checks if location services are enabled for the app and asks the user to allow location services. The GPS hardware first needs to be turned on. It takes some time until it can fix the position.
So you should update the UI to show the user that there is something going on in the background. Consider using a UIActivityIndicatorView and maybe set userInteractionEnabled of the view to NO. Also it is a good practice to give the user the option to cancel the operation.
In your delegate you must implement these 2 methods:
– locationManager:didUpdateToLocation:fromLocation:
– locationManager:didFailWithError:
Here you can remove the UIActivityIndicatorView and reenable user interaction.
In case of success you can use the coordinate of the CLLocationManager to do whatever you want. In case of failure show an error alert.
Call stopUpdatingLocation when you don't need location services anymore to save battery.