Javaを使用してGoogle Map APIを操作する例

こんにちは、ハブロフスクの住民。



Google Maps API Webサービスを使用して、少し経験を共有したいです。

この記事では、ジオコーディング、ジオデコードのためのサービスの使用方法を説明します。

ポイント間の距離とルートを見つけることができるように。 そしてもちろん、「どこでもっと近くに行くか」という問題の解決策に触れます。



まず、サードパーティのライブラリを決定しますが、その助けが必要です。



ツール



Google Maps API Webサービスは、 jsonxmlを使用してメッセージを返すことができます。 Googleはjsonを使用することをお勧めします。jsonはより小さく、より理解しやすいため、私も気に入っています。 jsonを使用するには、 org.jsonライブラリを使用します。これは大きくなく、必要なすべてのタスクを実行します。

さらに、 グアバライブラリを使用してコレクションを操作します。

まあ、もちろん、jdk 1.6。



Webサービスに連絡してjsonで応答を取得するには、 JsonReaderクラスを作成します。



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(); } } }
      
      







便宜上、リクエストパラメータをマップに保存し、最終的にマップからkey1 = value1&key2 = value2 ...という形式のパスを取得するために、静的メソッドを記述します。



 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; }
      
      







ツールを決定しました。要点を説明しましょう。



ジオコーディングとジオデコード



ジオコーディングは、住所(カリフォルニア州マウンテンビューの1600 Amphitheatre Parkwayなど)を地理的座標(緯度37.423021や経度-122.0883739など)に変換するプロセスであり、マーカーの配置や地図の配置に使用できます。 Google Geocoding APIサービスは、HTTPリクエストを介してジオコーダーへの直接アクセスを提供します。 また、このサービスでは、反対のアクション(座標のアドレスへの変換)を実行できます。 このプロセスは逆ジオコーディングと呼ばれます。




住所ロシア、モスクワ、ポクロンナヤ通り12の例を使用して、ジオコーディングサービスへのリクエストを検討します。

maps.googleapis.com/maps/api/geocode/output?parametersサービスへのパス、リクエストとレスポンスの構造については、 こちらこちらで詳しく説明されて ます



 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));//     }
      
      







コンソール:

 http://maps.googleapis.com/maps/api/geocode/json?sensor=false&address=%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
 55.735893,37.527420




次に、逆の操作を実行して、パラメーターのアドレス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);//   }
      
      







コンソール:

 http://maps.googleapis.com/maps/api/geocode/json?sensor=false&latlng=55.735893%2C37.527420&language=en
ポクロンナヤ通り、12、モスクワ、ロシア、121170




ポイント間の距離の計算



距離を計算するには、2つのポイントを取得し、式に従って合計を計算するのが論理的です。



 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); }
      
      







コンソール:

 http://maps.googleapis.com/maps/api/geocode/json?sensor=false&address=%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
ロシア、モスクワ、ポクロンナヤ通り、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%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%9F%D0%B0%D1%80%D0%BA +%D0%9F%D0%BE%D0%B1 %D0%B5%D0%B4%D1%8B
ロシア、モスクワ、地下鉄駅ビクトリーパーク55.736217,37.516838
距離:0.6634200825814502




ただし、このオプションは、障害物を考慮せずに、直線上のポイントのみの距離を示します。 幸いなことに、Googleは道順を取得するためのサービスを提供しています。



ルートを使用したポイント間の距離の計算



Google Directions APIは、HTTPリクエストを使用してポイント間のルートを計算するサービスです。 ルートでは、出発地と目的地をテキスト文字列(たとえば、イリノイ州シカゴ、オーストラリア、ニューサウスウェールズ州ダーウィンなど)または緯度と経度の座標として指定できます。 Directions APIは、複数のルートを一連のウェイポイントとして返すことができます。




maps.googleapis.com/maps/api/directions/output?parametersサービスへのパス、リクエストとレスポンスの構造については、 ここここで詳しく説明されて ます

たとえば、Poklonnaya Street 12からPark Pobedy地下鉄駅までの所要時間を知りたいとします。



 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); }
      
      







コンソール

 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分




しかし、どの地下鉄駅ビクトリーパークまたは地下鉄駅クトゥゾフスカヤがポクロンナヤ通り12に近いかを知りたい場合はどうすればよいですか?

この問題を解決するには、Google Distance Matrix APIサービスを使用することをお勧めします。



開始点と終了点のマトリックスの距離と移動時間の計算



Google Distance Matrix APIは、開始点と終了点のマトリックスの距離と移動時間の情報を提供するサービスです。 情報は、Google Maps APIを使用して計算された開始点と終了点間の推奨ルートに基づいて提供され、各ポイントペアの期間と距離の値を含む文字列です。




maps.googleapis.com/maps/api/distancematrix/output?parametersサービスへのパス、リクエストとレスポンスの構造は、 こちらこちらで詳しく説明されて ます



 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); }
      
      







コンソール

 http://maps.googleapis.com/maps/api/distancematrix/json?sensor=false&destinations=%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%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&言語= en&モード=ウォーキング
ロシア、モスクワ、地下鉄クトゥゾフスカヤ駅
 0.8キロ
 9分


アプローチがわずかに改善されたため、銀行で電話をするか郵便局に行くほうが簡単な配偶者を見つけることができます。



使用制限



Googleだけですが、私たち全員がたくさんいます。 これらのサービスが毎日いくつのリクエストを受け入れるか想像するのは難しいです。 負荷を心配しないために、善良な企業はそのサービスの使用に制限を設定するだけです。

現在、1日に1つのIPから最大2500リクエスト、1秒間に最大10リクエストを行うことができます。 制限を解消すると、クエリ結果はステータスOVER_QUERY_LIMITで空で返されます。



さらに、URLの文字数は2048を超えてはなりません。したがって、ルートをプロットするときは座標を使用するのが最適です。



参照資料



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:ソースgithub.com/nestor-by/map-api-samplesを投稿しました



All Articles