I have implemented a locationlistener in my app which uses the Network Provider.
This all works fine because i want a location quickly and with GPS Provider it takes ages.
But I've come to a point in my app where location has to be accurate (max 5-10meters).
I was wondering if it's possible to use the GPS provider with the Network Provider at the same time and then get the best result of both?
And is it also possible to let me know when the GPS provider provided me with an GPS Location?
So basically:
LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, this);
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
Will this work with the same overridden onLocationChanged() ?
And how can I see if the GPS has gotten a Location?
Thanks,
You can certainly use the same listener for multiple providers. It may be better to use locationmanager.getProviders with a Criteria object then sort by accuracy or just listen to all of them. Not much practical difference though.
The onLocationChanged callback gives you a Location object, which has a getProvider() method you can use to determine where it came from. It also has a getAccuracy() method, so you could also sort your recent fixes by accuracy.
Ideally, if you are not concerned on the battery usage, then it perfectly fine to use both providers. As Daren explained, you can filters the coordinates by using getProvider() and getAccuracy().
http://blog.shinetech.com/2011/10/14/a-good-look-at-android-location-data/
Ideally, if u are using the same listener for multiple providers there are 2 issues to it.
1.) You are requesting location from multiple providers thus more continuous use Battery. - This can be mitigate depending on your use case. You can unregister the listener once u have received a good location (i.e. - not require a continuous location updates for long).
2.) Making your listener synchronized - And this is important, for code to be more stable - You do not know how these listeners would be called. If internally Android calculate the location from different provider on a different thread than ur listener maybe called on the same main thread from 2 different call points. Same listener object is called.
Related
I'm building an app that should be able to report the users exact location. There is only a need for a single location, i.e. I don't need to track the device continuously.
I want the location to be as accurate as possible, and it's okay to wait a short while for the location to be determined (max 1-2 minutes).
I've been looking at FusedLocationProviderClient.getLastLocation(), but since I want the location to be as accurate and updated as possible it doesn't fit my needs.
So I started looking at using FusedLocationProviderClient.requestLocationUpdates() instead, and it seems like a better choice.
But I'm not sure how to best configure my LocationRequest to get as good accuracy as possible. For instance, would it be better to use setNumUpdates() so that I only receive a single update and use that as my location, or should I receive multiple updates in hopes of getting better accuracy (GPS locking to more satellites for example)? I'm thinking that if I use the second approach, I could look at the value of getAccuracy() from each location update and only keep the one with the highest accuracy. The downside is that if the device is moving and I keep receiving updates for a minute or so, the first location could have the highest accuracy, but since it's a minute old it's not accurate any more.
As stated above, I need just a single highly accurate location and it's okay for the app to wait 1-2 minutes for it if needed. What would be the best approach in this kind of scenario?
First, make sure the accurate location is turned on. look at Settings.Secure.LOCATION_MODE_HIGH_ACCURACY It has a noticeable advantage over only using GPS. Then listen for the location for a while and calculate the result you get to find out the best location. You can also detect if the user is moving if the number differs a lot or by using Activity Recognition API. It shouldn't be very hard to write this calculate function to get the best result.
I'm not sure about this but I really don't think waiting more than a few seconds gives you an advantage. to be sure you can simply alter this time and watch the result.
You might want to use LocationManager. In my experience FusedLocation will indeed appear to lock faster but may not be as accurate overall, or at least for a while. I have an app that also requires pretty accurate coordinates. My default is to use a LocationManager based approach but users can switch to a FusedLocation provider if they want faster locking (like when indoors).
This is a good overview https://developer.android.com/guide/topics/location/strategies
For the provider when requesting updates I'd use LocationManager.GPS_PROVIDER. It will take longer to lock since it will wait for satellites and not use Wifi or other towers. But you said that's OK. Something along these lines
LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, YourLocationListener);
Once you start getting location updates via your listener's onLocationChanged() you can start to inspect the location for accuracy, movement from last location change, etc. to try and evaluate if the GPS receiver is still settling in on a location. Once you are satisfied with the quality of the fix you can stop receiving location updates (locationManager.removeUpdates(YourLocationListener)) and then run your logic that needs the location. The link I provided has good info about this too.
From android documentation LocationManager.getLastKnownLocation():
Returns a Location indicating the data from the last known location
fix obtained from the given provider.
Note that this location could be out-of-date, for example if the device was turned off and moved to another location.
How often provider updates device location ? How its works ?
The reason why I asking is that I dont want to use locationListener,
I just need to get current geo location on button click, and thats it.
Can I just do like this ?
final LocationManager mlocManager = (LocationManager) getActivity()
.getSystemService(Context.LOCATION_SERVICE);
final Location currentGeoLocation = mlocManager
.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
How often provider updates device location ? How its works ?
It depends, and you may never know. If a device has good reception then updates about the user's location will fire rapidly.
Can I just do like this ?
Not really. If that is firing too soon then you will not get any location back. If the user doesn't have great reception then it could take 10 seconds before you have a reasonable idea of the user's location. I think you'll have to approach this slightly differently. I'm afraid I must recommend locationListeners :P
if you absolutely can't wait for a location you can try getLastKnownLocation(), but you need to be prepared to have a NULL result.
getLastKnownLocation() is just a cache of the last location from the provider you specified. In some cases there won't be one at all, like when the phone just rebooted. Even when there is a cached location it may not be accurate.
I have found plenty of examples of creating a location listener where you supply a particular provider, like so:
LocationManager lm =
(LocationManager) getSystemService(Context.LOCATION_SERVICE);
LocationListener ll = new mylocationlistener();
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, ll);
However, I don't need a precise location, but I'll take the best available. Is there a way to create a listener that works for the best available at the given time without creating a listener for each provider?
e.g. Use GPS if it is available, if not, Network, etc. Also, this is a widget, so I don't want to check what is available, then create a listener for that, since the widget will be up for a long duration and may live through enabling/disabling providers.
Thanks for the help
Have you considered using the PASSIVE_PROVIDER? That combined with getLastKnownLocation() might get you most of the way to what you want... You would call getLastKnownLocation() initially to establish a location if one was already known to the device, then the PASSIVE_PROVIDER would listen for updates from any location provider (i.e., location requests triggered from any other application on the device).
There would still be the possible scenario of no other application requesting location, so you'd likely want to trigger at least a single initial location fix using GPS_PROVIDER or NETWORK_PROVIDER.
I have noticed that applications like GPS Status get a fix pretty quickly. When I try to get a fix within my own application it takes more time. Does anybody know why is this happening? Do they use a hidden part of the API to force the GPS to connect faster?
Here's what I use
LocationManager loc = (LocationManager) context
.getSystemService(Context.LOCATION_SERVICE);
loc.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0,
listener);
I want the GPS to give results as frequent as possible because I need it for an AR app :)
Although I putting settings like 1000 ms and 1 m for the update frequency with no perceivable difference in speed of fix.
Could be one of several approaches:
Using LocationManager.getLastKnownLocation (which, given how many apps use location data, should generally be 'close enough' if not dead accurate.)
Using LocationManager.NETWORK_PROVIDER instead of LocationManager.GPS_PROVIDER to get an immediate rough fix, then refining with GPS (if available).
Running a service in the background that periodically gets the latest position and caches it (basically the same as LocationManager.getLastKnownLocation, but doing it yourself)
Here's my strategy : check this StackOverflow answer.
I'm using
myLocation = mLocationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
to retrieve the current location at the start-up of my application.
As the Android documentation states, this location can be "out-of-date", since the method returns the location when the GPS was used the last time.
How can I actively request the current location from the GPS? I thought about using LocationListener, however that might be a bit of an overkill, since I only need the location once (at the start of my app).
Any ideas?
Your initial intuition is correct - you need to use a LocationListener to request updates. Given that you require only a single position, you can unregister the LocationListener after the first value returns.
In practice though, it's probably wise to listen for a little bit longer. Location Based Services (particularly GPS) have a tendency to 'jump around' a bit when they first get their fix. Your best bet is to listen for a set amount of time, or a set number of updates, or until a certain level of accuracy has been achieved (the Location Listener will return the accuracy of the position returned).