到達地点の地域名を表示しました。

これは、緯度経度情報から地名を求める「逆ジオコーディング(住所の逆検索)」
という方法を行っています。
逆ジオコーディング(住所の逆検索):
https://developers.google.com/maps/documentation/geocoding/?hl=ja#ReverseGeocoding
忘れない内に備忘メモ。
■Google Geocoding API を使う
サンプルURLを見ます↓
http://maps.googleapis.com/maps/api/geocode/json?latlng=40.714224,-73.961452&sensor=false
ブラウザで見ると、JSON形式のデータが表示されます。
ということで、
(1)Android端末からGoogle Geocoding APIにHTTP通信(GET)でアクセス
(2)返ってきた値(JSON形式)をパースして、地域名を取得
(3)ゲーム画面に表示
という流れになります。
少し検証。
-----------------------------------------------------------------
(1)Android端末からGoogle Geocoding APIにHTTP通信(GET)でアクセス
APIに使ったパラメーターは、以下の4つ。
・緯度(必須)
・経度(必須)
・結果を返す言語
・センサーの有無(必須)
URLにすると、この通り。
http://maps.googleapis.com/maps/api/geocode/json?latlng=40.714224,-73.961452&sensor=true&language=ja
実装するときは、各パラメーターをプログラム側で変えられるようにすればOK。
-----------------------------------------------------------------
(2)返ってきた値(JSON形式)をパースして、地域名を取得
まずは、GETで取得した値を文字列に変換するところから↓
InputStreamをStringに変換する:
http://d.hatena.ne.jp/gungnir_odin/20091129/1259333223
次は、パースできる形にするために文字列をJSONObjectに変換。
それから欲しいデータを読み取ります↓
Android で JSON を使おう 〜 前編〜: ※後編も
http://d.hatena.ne.jp/androidprogram/20100621/1277075384
JSONデータの中には、色々な情報が入っています。
その中で、番地まで詳細な情報じゃなくて、ある程度地域がわかるレベルでの地域情報が欲しい。
そんなときは、下記の優先順位で使用するデータを決定。
【第1候補】locality → 区市町村
【第2候補】administrative_area_level_1 → 都道府県
【第3候補】country → 国
※日本の場合
Google Maps API Version3 日本語ドキュメント(非公式)
https://sites.google.com/site/gmapsapi3/Home/services
実装では、上記3つを読み取ります。
-----------------------------------------------------------------
(3)ゲーム画面に表示
読み取ったデータを表示するだけなのですが、文字列の先頭と末尾の半角スペースが
表示されなくて少しハマりました。
そのときに調べたこと。
strings.xmlにスペースを含む値を設定したい:
https://groups.google.com/group/android-group-japan/browse_thread/thread/c76134754664f85f?pli=1
-----------------------------------------------------------------
上記を踏まえて実装しました。
必要最低限を抜粋していますので、import宣言やエラー処理は含んでいません。
-----------------------------------------------------------------こうやって振り返れば数十行なのですが、調べたりテストするのに時間が結構かかりました。
private final static int TIMEOUT= 1000; // タイムアウト時間
private void GetRevGeo(float lat, float lng) {
// 端末の設定言語を取得
String langParam = "en";
if (Locale.JAPAN.equals(Locale.getDefault())) {
langParam = "ja";
}
// URLにHTTP接続(GET)
HttpURLConnection http = null;
URL url = new URL("http://maps.googleapis.com/maps/api/geocode/json?latlng="
+ lat + "," + lng + "&sensor=true&language=" + langParam);
http = (HttpURLConnection)url.openConnection();
// タイムアウト時間(ミリ秒)を設定
http.setReadTimeout(TIMEOUT);
http.setConnectTimeout(TIMEOUT);
// 接続
http.setRequestMethod("GET");
http.connect();
// データを取得
InputStream in = null;
in = http.getInputStream();
// InputStream -> String
BufferedReader reader = new BufferedReader(new InputStreamReader(in, "UTF-8"));
StringBuffer buf = new StringBuffer();
String str;
while ((str = reader.readLine()) != null) {
buf.append(str);
buf.append("\n");
}
String src = buf.toString();
// 切断
http.disconnect();
// JSONオブジェクトの生成(root)
JSONObject rootObject = new JSONObject(src);
// "results"階層にある配列を取得
JSONArray resultsArray = rootObject.getJSONArray("results");
// 配列を用意
int countResults = resultsArray.length();
JSONObject[] componentObject = new JSONObject[countResults];
for (int i = 0; i < countResults; i++){
componentObject[i] = resultsArray.getJSONObject(i);
}
// さらに下階層から「country」「administrative_area_level_1」「locality」と
// 同階層の「formatted_address」を探して地域名を取得
String country = "";
String administrative_area_level_1 = "";
String locality = "";
for (int i = 0; i < componentObject.length; i++) {
JSONArray typesArray = componentObject[i].getJSONArray("types");
for (int j = 0; j < typesArray.length(); j++) {
String elem = typesArray.getString(j);
// 国
if (elem.equals("country")) {
country = componentObject[i].getString("formatted_address");
Log.d("debug", "country---------------------" + country);
}
// 都道府県
if (elem.equals("administrative_area_level_1")) {
administrative_area_level_1 = componentObject[i].getString("formatted_address");
Log.d("debug", "administrative_area_level_1---------------------" + administrative_area_level_1);
}
// 区市町村
if (elem.equals("locality")) {
locality = componentObject[i].getString("formatted_address");
Log.d("debug", "locality---------------------" + locality);
}
}
}
if (locality.length() > 0) {
// 区市町村を返す
return locality;
} else if (administrative_area_level_1.length() > 0) {
// 区市町村が取得できなかったら都道府県を返す
return administrative_area_level_1;
} else if (country.length() > 0) {
// 都道府県が取得できなかったら国を返す
return country;
}
// 何も取得できなかったらnullを返す
return null;
}
-----------------------------------------------------------------
パースのやり方も、もっと効率の良い方法があるはずなのですが
現状の力量ではこの方法しか思いつきませんでした。