FusedLocationProvider gives wrong location sometimes - android

I am using FusedLocationProviderClient to get location updates in a foreground service. On testing and observing for few days, I found wrong locations which was far away from my actual location by around 4 kms similar to this, but the LocationResult had an accuracy of 24 meters. How is this even possible?
It can be eliminated if the accuracy was around 4 kms. This behavior does not occur very often but occurs atleast once in 4 among 10 devices. It becomes a problem when I calculate distance traveled.
I can tell it's not a cached location because I used to turn off and on Location Services everyday. (As per docs, turning off Location Services clears cache location.)
Any idea why it's giving wrong location and how to eliminate it? And also clearing cache locations without turning off Location Services?

FusedLocationProvider CAN give incorrect results like that when gps connectivity for device is down(or insufficient satellites are in "view" to provide accurate data). It will use the nearest cell tower/location data provided by the wifi router(google tracks this automatically) giving WILDLY incorrect results in places where google doesn't have a strong location mapping presence - which is anywhere outside an urban center.
You have imho two options:
Use the non googleplay based solution based on location service - this has an option for ignoring non-gps location data(wifi/cellular).
LocationManager locationManager = (LocationManager)
getApplicationContext().getSystemService(LOCATION_SERVICE);
Location location = locationManager.getLastKnownLocation(LocationManager.GPS_Provider);
You can even specify the number of satellites required for acceptable data so you can get REALLY accurate location data. You will lose information when the gps doesn't receive coordinates (like indoors), but in exchange will have less "noise" from incorrectly mapped location, as per your requirement.
Use a "snap to roads" API. There is a free version using open street map data called Project OSRM(Open Source Routing Machine) that provides a backend when hosted (locally or in cloud) using docker or building source yourself (details in link).
curl "http://127.0.0.1:5000/route/v1/driving/13.388860,52.517037;13.385983,52.496891?steps=true"
This request will return a location that is "snapped" to the nearest road. There are various options such as giving priority to highways etc. You can then discard the points that are not on the "path" that the user was previously on as rapidly shifting to a road 4km away and then coming back again is not likely.

Related

LocationProvider - Detecting highly inaccurate/incorrect locations

So I know you can use getAccuracy() to find the accuracy of a location but if you set up a cut off for the accuracy, can you prevent recording down one of those locations where it's hugely off mark of where the user is? Like if the user is still, most location updates cluster around his area but occasionally the location provider will hiccup and report the location as somewhere miles away.
Do these locations simply appear as "accurate" with getAccuracy? Or would they turn up as some insanely high getAccuracy() result? Programming a cut off point is easy enough but I was wondering if I would have to code extra checks such as if a location is way too different from the previous ones then it's a wayward one.
Accuracy is not the only deciding factor here. You should also look at the age of the location, and the provider if you get it (the Google Play Services location doesn't tell you, but the original Android LocationManager does).
In fact, Google has some useful sample code for maintaining a current best estimate. I have used a variation of this to filter out wild jumps in incoming location data. Essentially a location is not even reported if it doesn't pass this gate.

Receiving current location on Android

I've been working on an app that needs to be location-aware, and I've noticed that there are two (or more) methods of receiving location: with Google Play services (as seen here developer.android.com/training/location/retrieve-current.html#GetLocation) and with Location Manager, Providers etc. (as seen here http://www.vogella.com/tutorials/AndroidLocationAPI/article.html#locationapi_criteria).
What is the difference between these methods (if there is any)? Which one is more accurate?
edit: ok, I see that I sent the wrong link on the first thing. Won't this code (http://developer.android.com/training/location/receive-location-updates.html) give me location updates? Generally, what's the most accurate way to get my location?
The one with the GPS is accurate and that which is based on Network is not. Google Play Service use FUSE api to get the GPS location first, if the location is found (that's great), otherwise it will try to get location fix from Network Tower. In Short the one with GPS is accurate
The first method provides the details of LastKnownLocation. ie. the last location received from GPS or network provider when you or other apps accessed the location services. After that there are chances you moved a lot and it need not be your current location. So if You are planning to create an application that requires accurate location tracing, You should fetch the location as in the "Vogella" method. If the current location is unavailable, you can try using the last known location (As a plan B :-)).

Android LocationListener Switching from GPS to Network

I have a Service implementing LocationListener listening for both GPS and Network.
The application is dependant on a constant location-feed, but it seems when GPS has a hard time getting a locationfix network location doesnt step in.
manager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000 * 30,0, LocationReporterService.this);
manager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 1000 * 60 * 2,0, LocationReporterService.this);
Questions
How do I make sure that I always get a location?
How can I make sure that if I dont get a GPS-location, I get a Network-location?
Is it a known bug?
Should I have 2 services, GPSLocationService and NetworkLocationsService?
Is there a solution to this? :)
I agree with most of comments from AlexBottoni good answer, although in some points I can't suppot him.
Overview
First, just to check that you are doing it right...
You setup the same LocationListener for both providers. To indentify from where you are reciving the location you need to test it like this:
public void onLocationChanged(Location fix) {
if(fix.getProvider().equals(LocationManager.GPS_PROVIDER)){
//here Gps
} else if(fix.getProvider().equals(LocationManager.NETWORK_PROVIDER)){
//here Network
}
Also, you setup a different acquisition frequency. Gps is providing a new location every 30 seconds and Network every 2 minutes.
As you didn't impose a minimum distance, you should receive a new Location from each one of the providers (as long as they can get a fix) with the frequency requested. If you don't receive a fix, is because they weren't able to acquire one.
Also, it may takes a little longer then requested to get the fix (mainly with Gps), because it may take some time to shyncronize with satellites and fix a location.
Fallback
There is no builted-in fallback from one provider to the other. They are independet, as said by Alex. I'm using the following approach to implement fallback:
Register Gps listener and start a timer
On every GPS location, restart timer
If timer reachs end, register Network listener (Gps listener keeps registered)
If new Gps location arrives, unregister Network listener, restart timer
Preferable Provider
Although Gps may not be available everyhere, is far most precise then Network. In my town, I get 6 meters accuracy with GPS and 1 Km with Network :-(
Two services
Doesn't matter where you register the listener, activity or service, separate ot together, as long as you request them and the provider can get a fix, you will get the location (assuming no bugs in application :-))
Final Notes
Ensure you have the permissions need (ACCESS_FINE_LOCATION, INTERNET, etc).
Ensure that phone setup have Network Location enabled (usually default is disable)
Most Gps receivers support updating information about satellite location, which improves fix time. You can use GPS Satus from the market, to do it.
Regards.
This is really weird because, AFAIK, Android does not fall back to the second choice (network location provider) only if and when the first one (GPS) does not work. The two location providers are indipendent and should be sending location updates to you listeners indipendently to each other. Hence, the first one (GPS) should not be able to block the second one (network) in any case.
Regarding your questions:
How do I make sure that I always get a location?
You don't. There is no way to be sure. There are cases in which you cannot get any location fix just because no location reference is available. This is often the case in metro/underground stations. No GPS, no cellular antennas (not everybody lives in NYC or London...), no wi-fi hotspots so no way to determine your current position. Believe it or not, in the new hospital of my town, we have this situation at the moment because GPS constellation is not visible (indoor...), no wi-fi hotspots have been installed yet and the only available CellID antenna is just a few hundred meters away so you get the same signal everywhere, both outside and inside the building.
How can I make sure that if I dont get a GPS-location, I get a Network-location?
You cannot, either. It depends on the available networks. Anyway, you can check what you get from the location providers in your code and switch from one to the next until you get a usable location fix.
Is it a known bug?
No, it is not a bug. It is more a known limit of the existing technology.
Should I have 2 services, GPSLocationService and NetworkLocationsService?
It is something to try. As nick already said, this should not be a problem but a check should not hurt.
Is there a solution to this? :)
If your app is intended to be used mainly in a urban environment (a town), most likely you should use the network location engine as your main location engine. Nowadays, every village and town is covered by a large set on cellular phone antennas and by a large set of wi-fi hotspot so you are more likely to get a good location fix from the network location provider than from the GPS one. This is particularly true in towns with high buildings and narrow roads (that does not just mean NYC. Even here in Venice we have problems with the GPS). The network engine is also faster in getting a first fix and works indoor as well.
Fall back to GPS only if and when the network location engine does not work.

how to get the most accurate location using GPS and AGPS with given time in android?

I have a below requirement.
Find location of user from GPS and AGPS. (we are going to use Samsung Galaxy ACE mobile phone)
Note: For every transaction first location will be the reference location for the next activities.
Below are the constraint which has to be considered while solving this problem.
user should be within 10meter range of the reference location. meaning (Reference location - current location) <= 10meter (distance calculation by Locaiton class API).
Location has to found in the given period of time.
let say 20-25sec for finding each locaiton. the time can be extended to max 35sec.
My user is always be outside of the Shop while taking the reference location and then inside for all the other activities.
What I am doing
find the reference location with accuracy of 30m with 25sec of time. store this in static variable.
find the location for next actiivty and calculate the difference. if difference >=10m tell user to perform that activity again.
My Queries
Is this possible with such fine accuracy in the distance with given Time and place?
How google calculate this distance?
Does google finds the location with such accuracy? or what is the accuracy of Google Map using GPS? for e.g. at given particular time and location given by the Google MAP by GPS how much it is accurate? like if i am standing near to my BANK then what is difference between co-ordinates on the google map on the server and the co-ordinate given by google map through GPS on mobile phone.
I have did enough experiment on this problem and finally came here for help.
i did the observation by doing variation in timing, place, accuracy. still need to find one final solution. as we have to answer the client whether it is possible or not?
The GPS can provide most accurate match but only outdoors. It is possible to achieve such accuracy but not guaranteed.
There are formulates for finding distance between two points on a sphere. However, for rough approximations euclidean distance can be tried.
The location and its accuracy depends on client side GPS. Google just reads it.

Start location strategy

I am receiving periodically location updates via GPS, the problem is the time until the first location update occurs - it is just to long. When the user is within a building, this time gets even worser.
Therefore I am looking for some strategies to improve the startup time (at the moment I don't use getLastKnownLocation but I will). I started reading A Deep Dive Into Location to get some ideas and have some thoughts now I would like to discuss with you.
At first the blog post mentioned above goes through each location provider on the device and queries for the getLastKnownLocation, but only considers them when they are not to old and within an allowed accuracy.
Here comes my first question: I would expect to have the network based location immediately available, so I would request a new network based location, then I would get getLastKnownLocation from the GPS-provider and if the last GPS-location is within the circle formed by the point network based location and radius accuracy then I would take the GPS location, regardless how old it is. What do you think?
After checking the last known location I will start the GPS position tracking and because I only need it every 2 seconds and 10m change, I would use
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 2 * 1000, 10, this);
However I found a pattern (inside the presentation Being Epic: Best Practices for Android Development on slide 95 and 96 that at first he turns on coarse and fine locations (with 0,0 for time and distance changes) and then, when the first event is received, he switches to the really needed update frequency. So, does the first gps-update comes faster when the interval is set to 0?
In opposite to this pattern I would keep the coarse update until the first GPS update is received. What do you think?
Hope to get some interesting answers!
----------------Update----------------
I did some investigations: I turned on GPS and waited to get a fix. Then I turned GPS off and drove 50km (31 miles). Then I used the code from A Deep Dive Into Location to get all the getLastKnownLocation. I tried it twice, first with GPS turned off and second with GPS turned on, but without a fix:
1) with GPS turned off I got
- Provider: network, correct location with accuracy 680m
- Provider: passive (mProvider=network), same location as above, same time as above
- Provider: gps, location null
So I learned that when gps is turned off you get no getLastKnownLocation.
2) with GPS turned on I got
- Provider: network, correct location with accuracy 652m
- Provider: passive (mProvider=network), same location as above, same time as above
- Provider: gps, location as it was 2h earlier with accuracy 12m, time was also 2h earlier
Here I learned that old messages are not invalidated, even it is obvious that they are wrong.
In that case the algorithm works fine, because I moved in the time I turned the GPS off.
But what if I enter a house? In that case the 2h old GPS result would be very good, even it is outdated.
At the Google IO 2013 they showed in the session Beyond the Blue Dot: New Features in Android Location a new approach, see the video here.
The engineers at Google tried a lot of different strategies, the result is the "Fused location provider". Its quality is shown at 12:17 in the video.
Ketan Parmar has published a blog post how the fused location provider can be used in an example application.
Start up the location manager with the passive provider first
locationManager.requestLocationUpdates(LocationManager.PASSIVE_PROVIDER, AlarmManager.INTERVAL_FIFTEEN_MINUTES, 75, this);
then once you get a response from that you can switch to your gps hardware.
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);

Categories

Resources