2013年9月1日日曜日

Geocoderクラスは確実に使えるとは限らない

Androidにはジオコーディング/逆ジオコーディング(地理座標から住所の逆引きなど)を行うことのできるandroid.location.Geocoderというクラスが用意されています。

Google APIs付きのSDKでビルドするだけで利用できるので、非常にお手軽なのですが、Geocoderはプロキシクラスで、実際の処理を行っているのはバックエンドで動作しているLocationManagerServiceとなります。

このLocationManagerServiceが何らかの理由で死ぬ(メモリや電源が極端に消耗するとシステムが自動的に殺すことがある)と、端末を再起動するまでGeocoderは使用不可能になります。この状況でもGeocoder.isPresent()はtrueを返すので、実行するまで成功するかどうか分かりません。

Service not AvailableというメッセージのIOExceptionで失敗した場合、大体これのせいです。

どうもLocationManagerServiceをServiceManagerに登録にする処理が、端末起動時のSystemServer起動時に一度だけ行われるらしく、LocationManagerServiceが死ぬ事態を想定していないのが原因っぽいのですが…。

自力で復帰させるコードを書くことは可能なんでしょうか。まあ仮にできたとしても、今後Androidの起動プロセスが不変だと保証することができない以上、やるべきではないんでしょうけども。

---

そんなわけで、確実性に欠けるGeocoderクラスは使わない方がいいと思います。

代替として、Web APIとして用意されているThe Google Geocoding APIを使うことができます。

このGeocoding API v3の呼び出しをJavaから行えるラッパーライブラリ、Java API for Google geocoder v3も提供されているのですが、やっていることは結局maps/api/geocode/jsonを叩いて結果のJSONをパースするだけなので、自前で軽量な実装を書いた方がいいと思います。

なお、APIの使用制限として、2500リクエスト/日という制限が書いてありますが、その他に1リクエスト/1~2秒程度の制限もあるようで、2件以上の住所データを同時に変換しようとすると失敗します。もし複数件の住所を処理する必要がある場合、ExecutorService等で制御する必要があります。

0 件のコメント:

コメントを投稿