AndroidアプリでGPSから取得した位置情報から住所を取得するための方法を紹介します。これを「リバースジオコーディング」と呼ぶらしいです。私の場合は撮影した写真がどこら辺で撮られたかをExifとして保存するために使いました。

位置情報から住所を取得するサービス(API)を利用する

位置情報から住所を取得するためには何かしらのサービス(API)を利用する必要があります。下記にいくつか調べたAPIをまとめておきます。基本的には無料で利用できるところが殆どですが、1日のアクセス上限が設定されているところが殆どです。

API 料金
HeartRails Geo API 無料
クレジット表記が必要
Google Maps Geocoding API 1 日に 2,500 回のリクエストまで無料。
それ以降は有料。
Yahoo!ローカルサーチAPI 無料
50,000件/日の利用制限
国土交通省 位置参照情報サービス 無料
情報をダウンロードして利用
農研機構 簡易逆ジオコーディングサービス 無料
原則100,000/日まで

HeartRails Geo APIを利用したサンプルコード

今回はHeartRails Geo APIを利用したため、その時のサンプルコードを紹介します。特にアカウント登録などは不要で、HTTP GETリクエストでURLに緯度経度を含めて送信すると、XML形式で住所が返却されます。

返却される住所は指定した緯度経度から近い順に何件か含まれているため、ここでは一番近い住所を取得して掴用にしています。

public String getAddressName(double lon, double lat) {
  HttpURLConnection con = null;
  try {
    // URLの作成
    URL url = new URL("http://geoapi.heartrails.com/api/xml?method=searchByGeoLocation&x=135.0&y=35.0");
    // 接続用HttpURLConnectionオブジェクト作成
    con = (HttpURLConnection) url.openConnection();
    // リクエストメソッドの設定
    con.setRequestMethod("GET");
    // リダイレクトを自動で許可しない設定
    con.setInstanceFollowRedirects(false);
    // URL接続からデータを読み取る場合はtrue
    con.setDoInput(true);
    // 接続
    con.connect(); 

    // レスポンス(XML)の取得と解析
    InputStream in = con.getInputStream();
    String address = parseResXml(in);
    in.close();
    return address;

  } catch (MalformedURLException e) {
    ...
  } catch (IOException e) {
    ...
  }
  return null;
}

private String parseResXml(InputStream in) {
  try {
    XmlPullParser parser = Xml.newPullParser();
    parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
    parser.setInput(in, "UTF-8");

    HashMap<String, String> address = new HashMap<>();
    boolean isLast = false;

    // 位置が近い順に住所が配列で返却されるため最初の住所を取得する
    int eventType = parser.getEventType();
    while (eventType != XmlPullParser.END_DOCUMENT) {
      final String name = parser.getName();
      switch (eventType) {
        case XmlPullParser.START_TAG:
          if ("city".equals(name)) {
            address.put("city", parser.nextText());
          } else if ("town".equals(name)) {
            address.put("town", parser.nextText());
          } else if ("prefecture".equals(name)) {
            address.put("prefecture", parser.nextText());
          } else if ("postal".equals(name)) {
            address.put("postal", parser.nextText());
          }
          break;
        case XmlPullParser.END_TAG:
          if ("location".equals(name)) {
            isLast = true;
          }
          break;
      }
      if (isLast == true) {
        break;
      }
      eventType = parser.next();
    }
    String addressStr = address.get("prefecture") + address.get("city") + address.get("town");
    return addressStr;
  } catch (XmlPullParserException e) {
    ...
  } catch (IOException e) {
    ...
  }
  return null;
}