⬆️ ⬇️

Examples of working with the Google Map API using Java

Good afternoon, habrovchane.



I want to share some experience using Google Maps API Web Services.

In this article I will explain how to use services for geocoding, geo-decoding.

Just as you can find distances and routes between points. And, of course, I will touch upon the solution of the problem “where to go closer there or there."



To begin with, we will define third-party libraries, whose help we will need.



Instruments



Google Maps API Web Services can return messages using json and xml . Google recommends using json, I also prefer it, because it is smaller and clearer. To work with json, we will use the org.json library, it is not large and performs all the tasks that I need.

Additionally, we will use the guava library to work with collections.

And, of course, jdk 1.6.

')

To contact web services and get an answer in json, let's write the JsonReader class.



public class JsonReader { private static String readAll(final Reader rd) throws IOException { final StringBuilder sb = new StringBuilder(); int cp; while ((cp = rd.read()) != -1) { sb.append((char) cp); } return sb.toString(); } public static JSONObject read(final String url) throws IOException, JSONException { final InputStream is = new URL(url).openStream(); try { final BufferedReader rd = new BufferedReader(new InputStreamReader(is, Charset.forName("UTF-8"))); final String jsonText = readAll(rd); final JSONObject json = new JSONObject(jsonText); return json; } finally { is.close(); } } } 




For convenience, we will store the request parameters in the map, in order to get a path of the form key1 = value1 & key2 = value2 ... from the map, we will write a static method.



 private static String encodeParams(final Map<String, String> params) { final String paramsUrl = Joiner.on('&').join(//    key1=value1&key2=value2... Iterables.transform(params.entrySet(), new Function<Entry<String, String>, String>() { @Override public String apply(final Entry<String, String> input) { try { final StringBuffer buffer = new StringBuffer(); buffer.append(input.getKey());//    key=value buffer.append('='); buffer.append(URLEncoder.encode(input.getValue(), "utf-8"));//       HTML 4.01 return buffer.toString(); } catch (final UnsupportedEncodingException e) { throw new RuntimeException(e); } } })); return paramsUrl; } 




We decided on the tools, let's get to the point.



Geocoding and geo decoding



Geocoding is the process of converting addresses (such as 1600 Parkway Amphitheater, Mountain View, CA) into geographic coordinates (such as latitude 37.423021 and longitude -122.083739) that can be used to place markers or positioning a map. The Google Geocoding API service provides direct access to the geocoder via an HTTP request. Also, this service allows you to perform the reverse action (translation of coordinates into addresses). This process is called reverse geocoding.




Consider a request to the geocoding service, using the example of the address Russia, Moscow, Poklonnaya Street, 12.

The path to the maps.googleapis.com/maps/api/geocode/output?parameters service, the structure of the request and response is described in detail here and here .



 public static void main(final String[] args) throws IOException, JSONException { final String baseUrl = "http://maps.googleapis.com/maps/api/geocode/json";//   Geocoding API  HTTP final Map<String, String> params = Maps.newHashMap(); params.put("sensor", "false");//           params.put("address", ", ,  , 12");// ,    final String url = baseUrl + '?' + encodeParams(params);//     System.out.println(url);// ,          final JSONObject response = JsonReader.read(url);//          //               // //results[0]/geometry/location/lng  //results[0]/geometry/location/lat JSONObject location = response.getJSONArray("results").getJSONObject(0); location = location.getJSONObject("geometry"); location = location.getJSONObject("location"); final double lng = location.getDouble("lng");//  final double lat = location.getDouble("lat");//  System.out.println(String.format("%f,%f", lat, lng));//     } 




Console:

 http://maps.googleapis.com/maps/api/geocode/json?sensor=false&address=%D0%A0%D0%BE%D1%81 %D1% 81% D0% B8% D1% 8F % 9C% D0% BE% D1% 81% D0% BA% D0% B2% D0% B0% 2C +% D1% 83% D0% BB% D0% B8% D1% 86% D0% B0 +% D0% 9F% D0 % BE% D0% BA% D0% BB% D0% BE% D0% BD% D0% BD% D0% B0% D1% 8F% 2C + 12
 55.735893,37.527420




Now we perform the inverse operation, replacing in the address parameters with latlng



 public static void main(final String[] args) throws IOException, JSONException { final String baseUrl = "http://maps.googleapis.com/maps/api/geocode/json";//   Geocoding API  HTTP final Map<String, String> params = Maps.newHashMap(); params.put("language", "ru");//  ,      params.put("sensor", "false");//           //   /,        ,   //   ,     params.put("latlng", "55.735893,37.527420"); final String url = baseUrl + '?' + encodeParams(params);//     System.out.println(url);// ,          final JSONObject response = JsonReader.read(url);//          //  ,             // //results[0]/formatted_address final JSONObject location = response.getJSONArray("results").getJSONObject(0); final String formattedAddress = location.getString("formatted_address"); System.out.println(formattedAddress);//   } 




Console:

 http://maps.googleapis.com/maps/api/geocode/json?sensor=false&latlng=55.735893%2C37.527420&language=ru
 Poklonnaya st., 12, Moscow, Russia, 121170




Calculation of distances between points



To calculate the distance, it would be logical to get two points and calculate the total by the formula.



 private static final double EARTH_RADIUS = 6371.; //   public static void main(final String[] args) throws IOException, JSONException { final Point subwayStationPoint = getPoint(", ,  , 12"); final Point addressPoint = getPoint(", ,    "); //     final double dlng = deg2rad(subwayStationPoint.lng - addressPoint.lng); final double dlat = deg2rad(subwayStationPoint.lat - addressPoint.lat); final double a = sin(dlat / 2) * sin(dlat / 2) + cos(deg2rad(addressPoint.lat)) * cos(deg2rad(subwayStationPoint.lat)) * sin(dlng / 2) * sin(dlng / 2); final double c = 2 * atan2(sqrt(a), sqrt(1 - a)); System.out.println("distance: " + c * EARTH_RADIUS); //     } /** *  ,     * */ private static class Point { public double lat; public double lng; public Point(final double lng, final double lat) { this.lng = lng; this.lat = lat; } @Override public String toString() { return lat + "," + lng; } } /** *   * * @param address * @return * @throws IOException * @throws JSONException */ private static Point getPoint(final String address) throws IOException, JSONException { final String baseUrl = "http://maps.googleapis.com/maps/api/geocode/json";//   Geocoding API  HTTP final Map<String, String> params = Maps.newHashMap(); params.put("sensor", "false");// ,          //  params.put("address", address);// ,    final String url = baseUrl + '?' + encodeParams(params);//     System.out.println(url);//         final JSONObject response = JsonReader.read(url);//          //               // //results[0]/geometry/location/lng  //results[0]/geometry/location/lat JSONObject location = response.getJSONArray("results").getJSONObject(0); location = location.getJSONObject("geometry"); location = location.getJSONObject("location"); final double lng = location.getDouble("lng");//  final double lat = location.getDouble("lat");//  final Point point = new Point(lng, lat); System.out.println(address + " " + point); //       return point; } /** *       * * @param degree * @return */ private static double deg2rad(final double degree) { return degree * (Math.PI / 180); } 




Console:

 http://maps.googleapis.com/maps/api/geocode/json?sensor=false&address=%D0%A0%D0%BE%D1%81 %D1% 81% D0% B8% D1% 8F % 9C% D0% BE% D1% 81% D0% BA% D0% B2% D0% B0% 2C +% D1% 83% D0% BB% D0% B8% D1% 86% D0% B0 +% D0% 9F% D0 % BE% D0% BA% D0% BB% D0% BE% D0% BD% D0% BD% D0% B0% D1% 8F% 2C + 12
 Russia, Moscow, Poklonnaya Street, 12 55.7358925,37.5274195
 http://maps.googleapis.com/maps/api/geocode/json?sensor=false&address=%D0%A0%D0%BE%D1%81 %D1% 81% D0% B8% D1% 8F % 9C% D0% BE% D1% 81% D0% BA% D0% B2% D0% B0% 2C +% D1% 81% D1% 82% D0% B0% D0% BD% D1% 86% D0% B8% D1 % 8F +% D0% BC% D0% B5% D1% 82% D1% 80% D0% BE +% D0% 9F% D0% B0% D1% 80% D0% BA +% D0% 9F% D0% BE% D0% B1 % D0% B5% D0% B4% D1% 8B
 Russia, Moscow, metro station Park Pobedy 55.736217,37.516838
 distance: 0.6634200825814502




But this option will indicate the distance between points only in a straight line, not taking into account obstacles. Fortunately, Google offers a service for retrieving route data.



Calculating distances between points using routes



The Google Directions API is a service that calculates routes between points using an HTTP request. In the Directions service, the points of departure and destination can be indicated as text strings (for example, “Chicago, Illinois” or “Darwin, New South Wales, Australia”) or as coordinates of latitude and longitude. The Directions API service can return multiple routes as a sequence of waypoints.




The path to the maps.googleapis.com/maps/api/directions/output?parameters service, the structure of the request and response is described in detail here and here .

For example, we want to know how much time to go from Poklonnaya Street, 12 to Park Pobedy metro station:



 public static void main(final String[] args) throws IOException, JSONException { final String baseUrl = "http://maps.googleapis.com/maps/api/directions/json";//   Geocoding API  // HTTP final Map<String, String> params = Maps.newHashMap(); params.put("sensor", "false");// ,          params.put("language", "ru");//        params.put("mode", "walking");//  ,   driving, walking, bicycling params.put("origin", ", ,  , 12");//       //    params.put("destination", ", ,    ");//       //  //     final String url = baseUrl + '?' + encodeParams(params);//     System.out.println(url); //         final JSONObject response = JsonReader.read(url);//          //               // //results[0]/geometry/location/lng  //results[0]/geometry/location/lat JSONObject location = response.getJSONArray("routes").getJSONObject(0); location = location.getJSONArray("legs").getJSONObject(0); final String distance = location.getJSONObject("distance").getString("text"); final String duration = location.getJSONObject("duration").getString("text"); System.out.println(distance + "\n" + duration); } 




Console

 http://anonymouse.org/cgi-bin/anon-www.cgi/http://maps.googleapis.com/maps/api/directions/json?sensor=false&origin=%D0%A0%D0%BE%D1 % 81% D1% 81% D0% B8% D1% 8F% 2C +% D0% 9C% D0% BE% D1% 81% D0% BA% D0% B2% D0% B0% 2C +% D1% 83% D0% BB % D0% B8% D1% 86% D0% B0 +% D0% 94% D0% B5% D0% BD% D0% B8% D1% 81% D0% B0 +% D0% 94% D0% B0% D0% B2% D1 % 8B% D0% B4% D0% BE% D0% B2% D0% B0% 2C + 7 & language = ru & destination =% D0% A0% D0% BE% D1% 81% D1% 81% D0% B8% D1% 8F% 2C +% D0% 9C% D0% BE% D1% 81% D0% BA% D0% B2% D0% B0% 2C +% D1% 83% D0% BB% D0% B8% D1% 86% D0% B0 +% D0% 9A% D1% 83% D0% BB% D1% 8C% D0% BD% D0% B5% D0% B2% D0% B0 + 3 & mode = walking
 0.9 km
 10 min.




But what to do if we want to know which Park Pobedy metro station or Kutuzovskaya metro station is the nearest to go from Poklonnaya Street, 12

To solve this problem, we suggest using the Google Distance Matrix API service.



Calculate distance and travel time for a matrix of source and end points



The Google Distance Matrix API is a service that provides distance and time information for a matrix of source and end points. The information is based on the recommended route between the start and end points calculated using the Google Maps API, and is a string containing the values ​​of the duration and distance for each pair of points.




The path to the maps.googleapis.com/maps/api/distancematrix/output?parameters service, the structure of the request and response is described in detail here and here .



 public static void main(final String[] args) throws IOException, JSONException { final String baseUrl = "http://maps.googleapis.com/maps/api/distancematrix/json";//   Geocoding API  HTTP final Map<String, String> params = Maps.newHashMap(); params.put("sensor", "false");// ,          params.put("language", "ru");//   params.put("mode", "walking");//  ,   driving, walking, bicycling //      final String[] origins = { ", ,  , 12" }; params.put("origins", Joiner.on('|').join(origins)); //      final String[] destionations = { // ", ,    ", // ", ,   " // }; //       '|' params.put("destinations", Joiner.on('|').join(destionations)); final String url = baseUrl + '?' + encodeParams(params);//     System.out.println(url); //         final JSONObject response = JsonReader.read(url);//          final JSONObject location = response.getJSONArray("rows").getJSONObject(0); final JSONArray arrays = location.getJSONArray("elements");//      //         final JSONObject result = Ordering.from(new Comparator<JSONObject>() { @Override public int compare(final JSONObject o1, final JSONObject o2) { final Integer duration1 = getDurationValue(o1); final Integer duration2 = getDurationValue(o2); return duration1.compareTo(duration2);//      } /** *     * * @param obj * @return */ private int getDurationValue(final JSONObject obj) { try { return obj.getJSONObject("duration").getInt("value"); } catch (final JSONException e) { throw new RuntimeException(e); } } }).min(new AbstractIterator<JSONObject>() {//   JSONArray  ,     private int index = 0; @Override protected JSONObject computeNext() { try { JSONObject result; if (index < arrays.length()) { final String destionation = destionations[index]; result = arrays.getJSONObject(index++); result.put("address", destionation);//      ,      //   } else { result = endOfData(); } return result; } catch (final JSONException e) { throw new RuntimeException(e); } } }); final String distance = result.getJSONObject("distance").getString("text");//    final String duration = result.getJSONObject("duration").getString("text");//    final String address = result.getString("address");//  System.out.println(address + "\n" + distance + "\n" + duration); } 




Console

 http://maps.googleapis.com/maps/api/distancematrix/json?sensor=false&destinations=%D0%A0%D0%BE%D1%81% D1%81% 82D0BB% D1 % 9C% D0% BE% D1% 81% D0% BA% D0% B2% D0% B0% 2C +% D1% 81% D1% 82% D0% B0% D0% BD% D1% 86% D0% B8% D1 % 8F +% D0% BC% D0% B5% D1% 82% D1% 80% D0% BE +% D0% 9F% D0% B0% D1% 80% D0% BA +% D0% 9F% D0% BE% D0% B1 % D0% B5% D0% B4% D1% 8B% 7C% D0% A0% D0% BE% D1% 81% D1% 81% D0% B8% D1% 8F% 2C +% D0% 9C% D0% BE% D1 % 81% D0% BA% D0% B2% D0% B0% 2C +% D1% 81% D1% 82% D0% B0% D0% BD% D1% 86% D0% B8% D1% 8F +% D0% BC% D0 % B5% D1% 82% D1% 80% D0% BE +% D0% 9A% D1% 83% D1% 82% D1% 83% D0% B7% D0% BE% D0% B2% D1% 81% D0% BA % D0% B0% D1% 8F & origins =% D0% A0% D0% BE% D1% 81% D1% 81% D0% B8% D1% 8F% 2C +% D0% 9C% D0% BE% D1% 81% D0% BA% D0% B2% D0% B0% 2C +% D1% 83% D0% BB% D0% B8% D1% 86% D0% B0 +% D0% 9F% D0% BE% D0% BA% D0% BB% D0% BE% D0% BD% D0% BD% D0% B0% D1% 8F% 2C + 12 & language = en & mode = walking
 Russia, Moscow, metro station Kutuzovskaya
 0.8 km
 9 min


Having slightly improved the approach, you can find out which spouse is easier to call at the bank or go to the post office.



Restrictions on use



Google is one, and we all have a lot. It’s hard to imagine how many requests these services take every day. Whatever the burden of load, the corporation of good simply set limits on the use of its services.

Today, you can make no more than 2500 requests from one IP per day, and no more than 10 requests per second. If you work out your limit, the result of the query will be returned empty with the status OVER_QUERY_LIMIT.



In addition, the number of characters in the URL should not exceed 2048, so it’s best to use coordinates when plotting routes.



Links



developers.google.com/maps/documentation/geocoding/?hl=en

developers.google.com/maps/documentation/directions/?hl=en

developers.google.com/maps/documentation/distancematrix/?hl=en





UPD: Posted source github.com/nestor-by/map-api-samples

Source: https://habr.com/ru/post/148986/



All Articles