I've tried using distanceTo()
between two Location
objects, but AFAIK it isn't returning the correct values in all situations. Instead, I've written a custom method which returns what I think are the correct values.
float distanceBetween(Location l1, Location l2)
{
float lat1= (float)l1.getLatitude();
float lon1=(float)l1.getLongitude();
float lat2=(float)l2.getLatitude();
float lon2=(float)l2.getLongitude();
float R = 6371; // km
float dLat = (float)((lat2-lat1)*Math.PI/180);
float dLon = (float)((lon2-lon1)*Math.PI/180);
lat1 = (float)(lat1*Math.PI/180);
lat2 = (float)(lat2*Math.PI/180);
float a = (float)(Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.sin(dLon/2) * Math.sin(dLon/2) * Math.cos(lat1) * Math.cos(lat2));
float c = (float)(2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)));
float d = R * c * 1000;
return d;
}
Could anyone tell me what the difference is between my implementation and what distanceTo()
is returning?
I'm pretty certain that Location.distanceTo()
is correctly designed. It uses the WGS84 approach which is highly precise and accurate. I recently used Location.distanceTo()
for a number of test cases and it was never wrong.
You haven't explained why you think the method doesn't work properly. Its possible you may be getting wrong values because you haven't set the correct latitude and longitude values for a Location
object. Also, you can set up the source code of Android in your IDE and check the method for yourself. It is absolutely correct.
EDIT:
On that link you posted, there's an answer that concisely sums up the problem:
distanceTo()
works correctly. The error is on your side, most probable
algorithmic one, e.g if there is no GPS fix available, and the phone
takes a GSM cell based location, this of course can be off by 1000m.
For your app that probably wants to sum up the distance travelled,
take only GPS fixes, don't use another LocationProvider than GPS!
So the moral of the story is to make sure that you use only the GPS provider for distance calculations.
EDIT 2:
Google recommends using the Google Play Services Location API over the android.location
API. The new API is supposed to be more accurate.
References:
1. Making Your App Location-Aware.
As explained above by citing an old answer from me, distanceTo() works correctly.
I understand the advantage for a self implemented distanceTo method.
This makes your coode independent on libraries and is better portable, and
would always gives the same distance on different plattforms. (e.g when using test cases)
But then I recommned to use another formula:
In your code, the earth radius is not precise enough, you should take the WGS84 earth radius (in meters), that is the earth radius that the GPS receiver uses in its earth model. You easily find the WGS84 earth radius by searching internet.
Then you should use the haversine formula: This is known to work very well with small distances, too.