distanceBetween() returns inaccurate result? - android

I use distanceBetween() of Location class to calculate the distance between two points as follows:
private float getDistanceInMiles(GeoPoint p1, GeoPoint p2) {
double lat1 = ((double)p1.getLatitudeE6()) / 1e6;
double lng1 = ((double)p1.getLongitudeE6()) / 1e6;
double lat2 = ((double)p2.getLatitudeE6()) / 1e6;
double lng2 = ((double)p2.getLongitudeE6()) / 1e6;
float [] dist = new float[1];
Log.i("destination coordinates", "Latitude:" + lat2 + ", Longitude: " + lng2);
Location.distanceBetween(lat1, lng1, lat2, lng2, dist);
return dist[0] * 0.000621371192f;
}
Documentation says that distanceBetween() "Computes the approximate distance in meters between two locations, and optionally the initial and final bearings of the shortest path between them." However the difference between the result returned by distanceBetween() and real GPS device or Google Navigation app is pretty big. For example my method will return 6.2 miles while google maps shows 10 miles for the same location. I double check the coordinates of the starting point p1 and ending point p2 and they seems to be correct. Is that how distanceBetween() method works or Am I doing something wrong? And by the way Is there a way to use Google Place API to retrieve a distance as a JSON response?
Distance calculated by Google Maps: 6.1 miles
And the result of
Location.distanceBetween(41.742964, -87.995971, 41.811511, -87.967923, dist) is
4.947700

Google Navigation generally reports driving or walking distance along the set of steps in the directions list, not straight-line distance, which is what distanceBetween() reports.

To get a distance from a Google Maps I have used Google Directions API
and JSON parser to retrieve the distance value:
private double getDistanceInfo(double lat1, double lng1, String destinationAddress) {
StringBuilder stringBuilder = new StringBuilder();
Double dist = 0.0;
try {
destinationAddress = destinationAddress.replaceAll(" ","%20");
String url = "http://maps.googleapis.com/maps/api/directions/json?origin=" + lat1 + "," + lng1 + "&destination=" + destinationAddress + "&mode=driving&sensor=false";
HttpPost httppost = new HttpPost(url);
HttpClient client = new DefaultHttpClient();
HttpResponse response;
stringBuilder = new StringBuilder();
response = client.execute(httppost);
HttpEntity entity = response.getEntity();
InputStream stream = entity.getContent();
int b;
while ((b = stream.read()) != -1) {
stringBuilder.append((char) b);
}
} catch (ClientProtocolException e) {
} catch (IOException e) {
}
JSONObject jsonObject = new JSONObject();
try {
jsonObject = new JSONObject(stringBuilder.toString());
JSONArray array = jsonObject.getJSONArray("routes");
JSONObject routes = array.getJSONObject(0);
JSONArray legs = routes.getJSONArray("legs");
JSONObject steps = legs.getJSONObject(0);
JSONObject distance = steps.getJSONObject("distance");
Log.i("Distance", distance.toString());
dist = Double.parseDouble(distance.getString("text").replaceAll("[^\\.0123456789]","") );
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return dist;
}

Related

Distance between 2 places on Android Map

I need to calculate distance between current location and the destination. I have the latitude and longitude of current and destination locations. I found the below code from SO and internet while searching. But the calculation give 1366 km while the google maps gives 1675 km between 2 locations. Can someone help how can I calculate accurate distance. The destinations are world wide including my current city locations.
//Distance in Kilometers
fun distanceInKms ( lat1: Double, long1: Double, lat2: Double, long2: Double) : Double
{
val degToRad= Math.PI / 180.0;
val phi1 = lat1 * degToRad;
val phi2 = lat2 * degToRad;
val lam1 = long1 * degToRad;
val lam2 = long2 * degToRad;
return 6371.01 * Math.acos( Math.sin(phi1) * Math.sin(phi2) + Math.cos(phi1) * Math.cos(phi2) * Math.cos(lam2 - lam1) );
}
Can someone help me out with this please?
Use the android.location.Location class, available since API level 1 in Android. It has a static distanceBetween method doing it all for you.
See:
http://developer.android.com/reference/android/location/Location.html
float[] results = new float[1];
android.location.Location.distanceBetween(startLatitude, startLongitude, endLatitude, endLongitude, results);
//distance in meters now in results[0]
Divide by 1000 to get it in kilometers (km).
you can use it , it get like google don't forgot to add internet permission
String getDistanceOnRoad(double latitude, double longitude,
double prelatitute, double prelongitude) {
String result_in_kms = "";
String url = "http://maps.google.com/maps/api/directions/xml? origin="
+ latitude + "," + longitude + "&destination=" + prelatitute
+ "," + prelongitude + "&mode=driving&sensor=false&units=metric";
String tag[] = { "text" };
HttpResponse response = null;
try {
HttpClient httpClient = new DefaultHttpClient();
HttpContext localContext = new BasicHttpContext();
HttpPost httpPost = new HttpPost(url);
response = httpClient.execute(httpPost, localContext);
InputStream is = response.getEntity().getContent();
DocumentBuilder builder = DocumentBuilderFactory.newInstance()
.newDocumentBuilder();
Document doc = builder.parse(is);
if (doc != null) {
NodeList nl;
ArrayList<String> args = new ArrayList<String>();
for (String s : tag) {
nl = doc.getElementsByTagName(s);
if (nl.getLength() > 0) {
Node node = nl.item(nl.getLength() - 1);
args.add(node.getTextContent());
} else {
args.add(" - ");
}
}
result_in_kms = String.format("%s", args.get(0));
}
} catch (Exception e) {
e.printStackTrace();
}
return result_in_kms;
}
this library have class to get time, distance and draw polyline between 2 places it work like google map
https://github.com/memo1231014/MUT-master
Example for the library
RouteInformations rInformation = new RouteInformations(new AsyncResponse() {
#Override
public void processFinish(RouteDetails arg0) {
// TODO Auto-generated method stub
try
{
map.addPolyline(arg0.getLineOptions()); //you can add the return line and add it to the map
//here you can get distance , duration it will return like you drive a car
MUT.fastDialog(Map.this,"Time and Distance","Distance : "+arg0.getDistance()+"\nDuration : "+arg0.getDuration());
}
catch(Exception e)
{
MUT.lToast(Map.this,"Can't draw line Try Again");
}
}
});
//you should pass the 2 lat and lang which you want to draw a aline or get distance or duration between them
RouteDetails routeDetails=new RouteDetails();
routeDetails.setLatLong1(from.getPosition());
routeDetails.setLatLong2(to.getPosition());
rInformation.execute(routeDetails);

Fetching Location Distance issue sending 0.0

I am using the following code the fetching the distance between difference latitude and longitude.Some time it works fine but some time it return the 0.0. I can't understand the reason why it happen. I have enable both GPS and Network
My code is..
public static String getDistanceOnRoad(String latitude, String longitude,
String prelatitute, String prelongitude) {
String result_in_kms = "";
float num_in_Km=0;
String url = "http://maps.google.com/maps/api/directions/xml?origin="
+ latitude + "," + longitude + "&destination=" + prelatitute
+ "," + prelongitude + "&sensor=false&units=metric";
String tag[] = { "text" };
HttpResponse response = null;
try {
HttpClient httpClient = new DefaultHttpClient();
HttpContext localContext = new BasicHttpContext();
HttpPost httpPost = new HttpPost(url);
response = httpClient.execute(httpPost, localContext);
InputStream is = response.getEntity().getContent();
DocumentBuilder builder = DocumentBuilderFactory.newInstance()
.newDocumentBuilder();
Document doc = builder.parse(is);
if (doc != null) {
NodeList nl;
ArrayList args = new ArrayList();
for (String s : tag) {
nl = doc.getElementsByTagName(s);
if (nl.getLength() > 0) {
Node node = nl.item(nl.getLength() - 1);
args.add(node.getTextContent());
} else {
args.add(" - ");
}
}
result_in_kms = String.format("%s", args.get(0));
//result come with 'm' and 'km' tag so remove this tag
String num=stripNonDigits(result_in_kms);
//if result in KM then does not devide by 1000
if(!isdisIn_M_or_KM(result_in_kms)){
num_in_Km=Float.valueOf(num)/1000;
}
else num_in_Km=Float.valueOf(num);
Log.i("", "");
}
} catch (Exception e) {
e.printStackTrace();
}
return String.valueOf(num_in_Km);
}
For Finding the distance using GPS, There is no Need of Network Connection. GPS will provide the Latitude and Longitude based on the the time interval you apply.
kindly refer the below link
Calculate distance between two latitude-longitude points? (Haversine formula)

How to get the latitude and longitude of an image in sdcard to my application?

From my application I can open gallery. Is there any way to get latitude and longitude of any selected image in gallery to my application?
You can actually use a "buildin" function:
ExifInterface exif = new ExifInterface(path);
float[] latLong = new float[2];
boolean hasLatLong = exif.getLatLong(latLong)
if (hasLatLong) {
System.out.println("Latitude: " + latLong[0]);
System.out.println("Longitude: " + latLong[1]);
}
Maybe is something new, but I think is much more convenient than the accepted answer.
You Should Go with ExifInterface class to read various EXIF metadata from Images:
Example :
ExifInterface exif = new ExifInterface(filepath);
exif.getAttribute(ExifInterface.TAG_GPS_LATITUDE);
exif.getAttribute(ExifInterface.TAG_GPS_LATITUDE_REF);
exif.getAttribute(ExifInterface.TAG_GPS_LONGITUDE);
exif.getAttribute(ExifInterface.TAG_GPS_LONGITUDE_REF);
Edited :
Now Here you will get lat-long as Below format.
lat = 30/1,12/1,34/1,
long=81/1,22/1,41/1
To Convert this into Real Values this Blog Helped Me.
we need to do conversion from degree, minute, second form to GeoPoint form.
By Below Way you can Do it.
String LATITUDE = exif.getAttribute(ExifInterface.TAG_GPS_LATITUDE);
String LATITUDE_REF = exif.getAttribute(ExifInterface.TAG_GPS_LATITUDE_REF);
String LONGITUDE = exif.getAttribute(ExifInterface.TAG_GPS_LONGITUDE);
String LONGITUDE_REF = exif.getAttribute(ExifInterface.TAG_GPS_LONGITUDE_REF);
// your Final lat Long Values
Float Latitude, Longitude;
if((LATITUDE !=null)
&& (LATITUDE_REF !=null)
&& (LONGITUDE != null)
&& (LONGITUDE_REF !=null))
{
if(LATITUDE_REF.equals("N")){
Latitude = convertToDegree(LATITUDE);
}
else{
Latitude = 0 - convertToDegree(LATITUDE);
}
if(LONGITUDE_REF.equals("E")){
Longitude = convertToDegree(LONGITUDE);
}
else{
Longitude = 0 - convertToDegree(LONGITUDE);
}
}
private Float convertToDegree(String stringDMS){
Float result = null;
String[] DMS = stringDMS.split(",", 3);
String[] stringD = DMS[0].split("/", 2);
Double D0 = new Double(stringD[0]);
Double D1 = new Double(stringD[1]);
Double FloatD = D0/D1;
String[] stringM = DMS[1].split("/", 2);
Double M0 = new Double(stringM[0]);
Double M1 = new Double(stringM[1]);
Double FloatM = M0/M1;
String[] stringS = DMS[2].split("/", 2);
Double S0 = new Double(stringS[0]);
Double S1 = new Double(stringS[1]);
Double FloatS = S0/S1;
result = new Float(FloatD + (FloatM/60) + (FloatS/3600));
return result;
};
#Override
public String toString() {
// TODO Auto-generated method stub
return (String.valueOf(Latitude)
+ ", "
+ String.valueOf(Longitude));
}
public int getLatitudeE6(){
return (int)(Latitude*1000000);
}
public int getLongitudeE6(){
return (int)(Longitude*1000000);
}
the exif.getLatLong(float[]) is now deprecated, you can use a better method which returns a double[] :
ExifInterface exifInterface = new ExifInterface(file);
double[] latlng = exifInterface.getLatLong();
if (latlng != null) {
Double currentLatitude = latlng[0];
Double currentLongitude = latlng[1];
Log.d("Debug", "Exif : latitude: " + currentLatitude + ", longitude: " + currentLongitude)
}
Happy coding.

Ho do i use google places to find a place in android

Just now I've purchased Google API Key. I've find the exact place by using google Places. The most important thing is I've to find the place programmatically which means that When I open my application it will display the place in a textview. Also i want to find the nearest places.
Can anyone please explain with a complete sample code (in java, not java script code)
You can use following code for Google places Api
Here i have search airports but you can search your own places and when you find
here getJsonResponse id your httpclient
String url = "https://maps.googleapis.com/maps/api/place/textsearch/json?query="**Place To Search**"&sensor=true&key=**Your Api Key**";
String res = getJsonRespose(url);
if (res != null && !res.equalsIgnoreCase("")) {
JSONObject jObject = new JSONObject(res);
// if (jObject.getString("status").equalsIgnoreCase("ok")) {
JSONArray jArray = jObject.getJSONArray("results");
if (jArray.length() > 0) {
for (int i = 0; i < jArray.length(); i++) {
AirportListData adata = new AirportListData();
JSONObject geo = jArray.getJSONObject(i);
JSONObject jLocation = geo.getJSONObject("geometry");
JSONObject jgetLocation = jLocation
.getJSONObject("location");
Address = geo.getString("formatted_address");
name = geo.getString("name");
adata.setAirportName(name);
lat = jgetLocation.getDouble("lat");
lng = jgetLocation.getDouble("lng");
adata.setLat(lat);
adata.setLng(lng);
double dis = getDistance(lat, lng);
adata.setAddress(Address);
adata.setDistnace(dis / 1000);
ardata.add(adata);
Log.e("address", "Distance" + (dis / 1000) + "Address"
+ Address + "name" + name + "lat" + lat + "lng"
+ lng);
}
}
}
When You got All places you can Call getDistance Method and find distance between your current place and places you got and after calculating that you got nearest place
public static double getDistance(double lat, double lng) {
try {
float[] result = new float[3];
// Log.e("lat long : ", c.getDouble(1) + " : " + c.getDouble(2) +
// " : " + latitude + " : " + longitude);
Location.distanceBetween(Constantdata.lat, Constantdata.lon, lat,
lng, result);
double distance = ((double) result[0]);
return distance;
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return 0.0;
}
Here Constantdata.lat and constant.lon is your current latitude and longitude and lat long is places latitude and logitude that you got

Map latitude and longitude is showing in sea in android?

From a json feed am getting all the latitude and longitude and adding all in mapview. Am gettin different markers.but all the points are showing in sea. this is my code. can anyone help me please
MapItemizedOverlay itemizedoverlay;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.map);
url = "http://dentonsweb.com/app/html/android/get.php?what=Hotels&lat=51.507222&lon=-0.1275&pg=0";
System.out.println("url is "+url);
Jsonfunctions jParser = new Jsonfunctions();
JSONObject json = jParser.getJSONFromUrl(url);
try {
// Getting Array of Contacts
results = json.getJSONArray(TAG_RESULTS);
// looping through All Contacts
for (int i = 0; i < results.length(); i++) {
JSONObject c = results.getJSONObject(i);
id = c.getString(TAG_ID);
name = c.getString(TAG_NAME);
System.out.println("name is " + name);
adress = c.getString(TAG_ADRRESS);
latitude = c.getString(TAG_LATITUDE);
latitudeAry.add(c.getString(TAG_LATITUDE).toString());
longitude = c.getString(TAG_lONGITUDE);
latitudeAry.add(c.getString(TAG_lONGITUDE).toString());
distance = c.getString(TAG_DISTANCE);
image = c.getString(TAG_IMAGE);
phone = c.getString(TAG_TELEPHONE);
telphonenumberAry
.add(c.getString(TAG_TELEPHONE).toString());
NameAry.add(c.getString(TAG_NAME).toString());
resourceAry.add(new ResourceClass(point,id, name, adress,image,
distance, latitude, longitude, phone));
System.out.println("arraooosdospodpsodps " + resourceAry);
}
} catch (JSONException e) {
e.printStackTrace();
}
mapView = (MapView) findViewById(R.id.mapView);
mapView.setBuiltInZoomControls(true);
mapView.setSatellite(false);
mc = mapView.getController();
listOfOverlays = mapView.getOverlays();
drawable = this.getResources().getDrawable(
R.drawable.pin);
itemizedoverlay = new MapItemizedOverlay(drawable,mapView);
for (int i = 0; i < resourceAry.size(); i++) {
// latitude = resourceAry.get(i).getLatitude();
System.out.println("latitude is " + latitude);
String latitude = resourceAry.get(i).getLatitude();
String longitude = resourceAry.get(i).getLongitude();
// longitude = resourceAry.get(i).getLongitude();
String name = resourceAry.get(i).getName();
System.out.println("Name is" + name);
String adress = resourceAry.get(i).getAdress();
if (!latitude.equals("") && !longitude.equals("")) {
Double latitude_next = Double.parseDouble(latitude);
Double longitude_next = Double.parseDouble(longitude);
point = new GeoPoint((int) (latitude_next * 1E6),
(int) (longitude_next * 1E6));
System.out.println("point is " + point);
overlayitem = new OverlayItem(point,resourceAry.get(i).getName(),resourceAry.get(i).getAdress());
// System.out.println( " spanned text: " +
// Html.fromHtml(Texte));
itemizedoverlay.addOverlay(overlayitem);
listOfOverlays.add(itemizedoverlay);
}
}
mc.animateTo(point);
mc.setZoom(13);
}
#Override
protected boolean isRouteDisplayed() {
// TODO Auto-generated method stub
return false;
}
}
#harish --
You get latitude & longitudes like 51.509998321533,-0.12999999523163
but in android geopoint accepts only int values.
now create a function which will take these values & restric them upto 6 decimal points & you will get result as you wanted
Function will be like
double roundTwoDecimals(double d){
DecimalFormat twoDForm = new DecimalFormat("#.######");
return Double.valueOf(twoDForm.format(d));
}
this way you will get double value & then multiply it with 10E6 & you will get int which you need to use in creating GeoPoints..
I am not suere if it makes a difference but the line
latitudeAry.add(c.getString(TAG_lONGITUDE).toString());
has a lowercase L in lONGITUDE

Categories

Resources