38

Is there a quick and efficient way to get altitude (elevation) by longitude and latitude on the Android platform?

approxiblue
  • 6,982
  • 16
  • 51
  • 59
Maksym Gontar
  • 22,765
  • 10
  • 78
  • 114

7 Answers7

39

My approach is to use USGS Elevation Query Web Service:

private double getAltitude(Double longitude, Double latitude) {
    double result = Double.NaN;
    HttpClient httpClient = new DefaultHttpClient();
    HttpContext localContext = new BasicHttpContext();
    String url = "http://gisdata.usgs.gov/"
            + "xmlwebservices2/elevation_service.asmx/"
            + "getElevation?X_Value=" + String.valueOf(longitude)
            + "&Y_Value=" + String.valueOf(latitude)
            + "&Elevation_Units=METERS&Source_Layer=-1&Elevation_Only=true";
    HttpGet httpGet = new HttpGet(url);
    try {
        HttpResponse response = httpClient.execute(httpGet, localContext);
        HttpEntity entity = response.getEntity();
        if (entity != null) {
            InputStream instream = entity.getContent();
            int r = -1;
            StringBuffer respStr = new StringBuffer();
            while ((r = instream.read()) != -1)
                respStr.append((char) r);
            String tagOpen = "<double>";
            String tagClose = "</double>";
            if (respStr.indexOf(tagOpen) != -1) {
                int start = respStr.indexOf(tagOpen) + tagOpen.length();
                int end = respStr.indexOf(tagClose);
                String value = respStr.substring(start, end);
                result = Double.parseDouble(value);
            }
            instream.close();
        }
    } catch (ClientProtocolException e) {} 
    catch (IOException e) {}
    return result;
}

And example of use (right in HelloMapView class):

public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        linearLayout = (LinearLayout) findViewById(R.id.zoomview);
        mapView = (MapView) findViewById(R.id.mapview);
        mZoom = (ZoomControls) mapView.getZoomControls();
        linearLayout.addView(mZoom);
        mapView.setOnTouchListener(new OnTouchListener() {
            public boolean onTouch(View v, MotionEvent event) {
                if (event.getAction() == 1) {
                    final GeoPoint p = mapView.getProjection().fromPixels(
                            (int) event.getX(), (int) event.getY());
                    final StringBuilder msg = new StringBuilder();
                    new Thread(new Runnable() {
                        public void run() {
                            final double lon = p.getLongitudeE6() / 1E6;
                            final double lat = p.getLatitudeE6() / 1E6;
                            final double alt = getAltitude(lon, lat);
                            msg.append("Lon: ");
                            msg.append(lon);
                            msg.append(" Lat: ");
                            msg.append(lat);
                            msg.append(" Alt: ");
                            msg.append(alt);
                        }
                    }).run();
                    Toast.makeText(getBaseContext(), msg, Toast.LENGTH_SHORT)
                            .show();
                }
                return false;
            }
        });
    }
Cœur
  • 37,241
  • 25
  • 195
  • 267
Maksym Gontar
  • 22,765
  • 10
  • 78
  • 114
  • As somewhat GIS interested I find this very interesting – JaanusSiim Jan 03 '10 at 19:58
  • 6
    To amplify on this: the reason you need to do something like that (use a service on the network) is twofold: one, the GPS isn't very good at altitude, vertical errors are around 150 ft at times, and two, any reasonably high-resolution world elevation model is enormous, much too big to install on the phone. If you were doing this on your own server as part of a web app or GIS, you could instead download the elevation model (from NASA) and query it directly; faster, but uses a lot of storage. – Andrew McGregor Jan 03 '10 at 20:48
  • 1
    To clarify, this actually grabs the elevation and NOT the altitude of a lat/long point. – Austyn Mahoney Aug 19 '10 at 16:52
  • 2
    To clarify even more: altitude is measured by a device, which could be flying on a plane, for example. Elevation refers to the ground and does not change. Of course, only elevation could be fetched from a database. – heltonbiker Aug 26 '11 at 02:00
  • 4
    Unless you guys are a lot taller than me, or drive in cars with ridiculous suspensions, altitude and elevation are virtually the same thing *in this context*. – Nate Jul 24 '12 at 13:13
  • 1
    gisdata.usgs.gov webservice does not work anymore. It redirects to nationalmap.gov site. But I've found no rest service doing the same there. – ARLabs Feb 23 '15 at 14:39
  • 1
    ARLabs, I think this is the replacement webservice: http://ned.usgs.gov/epqs/ eg. http://ned.usgs.gov/epqs/pqs.php?x=-95&y=38&units=Feet&output=xml – JDOaktown May 21 '15 at 18:55
24

You can also use the Google Elevation API. The online documentation for it is located at: https://developers.google.com/maps/documentation/elevation/

Please note the following from the above API page:

Usage Limits: Use of the Google Geocoding API is subject to a query limit of 2,500 geolocation requests per day. (User of Google Maps API Premier may perform up to 100,000 requests per day.) This limit is enforced to prevent abuse and/or repurposing of the Geocoding API, and this limit may be changed in the future without notice. Additionally, we enforce a request rate limit to prevent abuse of the service. If you exceed the 24-hour limit or otherwise abuse the service, the Geocoding API may stop working for you temporarily. If you continue to exceed this limit, your access to the Geocoding API may be blocked. Note: the Geocoding API may only be used in conjunction with a Google map; geocoding results without displaying them on a map is prohibited. For complete details on allowed usage, consult the Maps API Terms of Service License Restrictions.

Altering Max Gontar's code above for the Google API gives the following, with the returned elevation given in feet:

private double getElevationFromGoogleMaps(double longitude, double latitude) {
        double result = Double.NaN;
        HttpClient httpClient = new DefaultHttpClient();
        HttpContext localContext = new BasicHttpContext();
        String url = "http://maps.googleapis.com/maps/api/elevation/"
                + "xml?locations=" + String.valueOf(latitude)
                + "," + String.valueOf(longitude)
                + "&sensor=true";
        HttpGet httpGet = new HttpGet(url);
        try {
            HttpResponse response = httpClient.execute(httpGet, localContext);
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                InputStream instream = entity.getContent();
                int r = -1;
                StringBuffer respStr = new StringBuffer();
                while ((r = instream.read()) != -1)
                    respStr.append((char) r);
                String tagOpen = "<elevation>";
                String tagClose = "</elevation>";
                if (respStr.indexOf(tagOpen) != -1) {
                    int start = respStr.indexOf(tagOpen) + tagOpen.length();
                    int end = respStr.indexOf(tagClose);
                    String value = respStr.substring(start, end);
                    result = (double)(Double.parseDouble(value)*3.2808399); // convert from meters to feet
                }
                instream.close();
            }
        } catch (ClientProtocolException e) {} 
        catch (IOException e) {}

        return result;
    }
Community
  • 1
  • 1
dhael
  • 341
  • 2
  • 4
4

It's important to first differentiate altitude from elevation.

Altitude is the distance from a point down to the local surface; whether that be land or water. This measurement is mainly used for aviation.

Altitude can be obtained by using the Location.getAltitude() function.

Elevation is the distance from the local surface to the sea level; much more often used, and often mistakenly referred to as altitude.

With that said, for the US, USGS has provided a newer HTTP POST and GET queries that can return XML or JSON values for elevation in either feet or meters. For worldwide elevation, you could use the Google Elevation API.

Always Lucky
  • 334
  • 3
  • 7
3

If u are using android device which has GPS Recever then there is a method getAltitude() by using that u can get the altitude by elevation.

2

Try this one that I`v built: https://algorithmia.com/algorithms/Gaploid/Elevation

here is example for Java:

import com.algorithmia.*;
import com.algorithmia.algo.*;

String input = "{\"lat\": \"50.2111\", \"lon\": \"18.1233\"}";
AlgorithmiaClient client = Algorithmia.client("YOUR_API_KEY");
Algorithm algo = client.algo("algo://Gaploid/Elevation/0.3.0");
AlgoResponse result = algo.pipeJson(input);
System.out.println(result.asJson());
Gaploid
  • 89
  • 5
0

Google maps have the altitude, what you need is this code

altitude="";
var init = function() {
        var elevator = new google.maps.ElevationService;
        map.on('mousemove', function(event) {
            getLocationElevation(event.latlng, elevator);
            document.getElementsByClassName("altitudeClass")[0].innerHTML = "Altitude: "+ getAltitude();
            //console.debug(getAltitude());
        });
}

var getLocationElevation = function (location, elevator){
  // Initiate the location request
  elevator.getElevationForLocations({
    'locations': [location]
  }, function(results, status) {
    if (status === google.maps.ElevationStatus.OK) {
      // Retrieve the first result
      if (results[0]) {
        // Open the infowindow indicating the elevation at the clicked position.
        setAltitude(parseFloat(results[0].elevation).toFixed(2));
      } else {
        setAltitude('No results found');
      }
    } else {
      setAltitude('Elevation service failed due to: ' + status);
    }
  });
}
function setAltitude(a){
    altitude = a;
}
function getAltitude(){
    return altitude;
}
Petter Friberg
  • 21,252
  • 9
  • 60
  • 109
-1

The idea to use the Google Elevation API is good, but parsing XML using string functions is not. Also, HttpClient is deprecated now, as using insecure connections.

See here for a better solution: https://github.com/M66B/BackPackTrackII/blob/master/app/src/main/java/eu/faircode/backpacktrack2/GoogleElevationApi.java

M66B
  • 1,164
  • 1
  • 8
  • 16