概要
先日書かせていただいた記事に関しまして、位置情報を取得する際にLocationManagerを使用しました。
その際に速度の遅さが問題になりましたので、私が改善できた方法につきまして記事を書きます。
最初していた実装
private void callRequestLocationUpdates()
{
checkPermission();
mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 500, 1, listener);
}
Androidで位置情報を取得する際はLocationManager.requestLocationUpdates()を使用したのですが、最初は上記のような実装をしていました。
ところが、LocationManagerで位置情報を取得するのにはGPS以外の方法もあるらしく、それはrequestLocationUpdates()の第一引数で制御しているのだとわかりました。
第一引数は「プロパイダー」と呼ばれているようですが、参考に記載のdocsを参考にすると3個ほど「PROVIDER」とついた名前の定数が存在することが伺えました。
・GPS_PROVIDER
・NETWORK_PROVIDER
・PASSIVE_PROVIDER
requestLocationUpdates()の引数にPROVIDERは一つしか設定できないので、最初は上記の3つのうちからどれかを選ばなければならないと思っていたのですが、実はLocationManagerでは上記3つのPROVIDERでrequestLocationUpdates()を並列で走行させることも可能なんです。
改善した実装
requestLocationUpdates()の並列走行については参考に記載のサイトを参照させていただきました(Android開発 | 複数のプロバイダで並行して位置情報を取得する方法)。
そこには以下のような記述がありました。
requestLocationUpdatesdeに渡し測定を開始しますが、これを必要なprovider分だけ呼び出せば並行して測定が行われます。
さらに、以下のような記述もありました。
全部のプロバイダで同じリスナを使っていれば、removeUpdatesは一度呼び出せば全部のプロバイダの測定が停止します。
おー!これは!と思いました。
つまり、for文で回して全てのPROVIDERでもって並列処理をさせ、一番最初に位置情報を取得できたもので後続処理を行えばアプリ全体でより高速化が見込めると思いました!
そして、上記サイトを参考にさせていただき改善したコードが以下です。
private void callRequestLocationUpdates()
{
//複数プロパイダで処理を回すことで高速化を目指す
List<String> providers = mLocationManager.getProviders(true);
checkPermission();
for (String provider : providers) {
mLocationManager.requestLocationUpdates(provider, 500, 1, listener);
}
}
requestLocationUpdates()で位置情報が取得できた際には、LocationListener.onLocationChanged()が呼ばれますが、並列処理をしているため、後続処理が何回も呼ばれては困りますので、少し工夫して実装しています。
@Override
public synchronized void onLocationChanged(Location location) {
// 位置情報取得
lat = location.getLatitude();
lng = location.getLongitude();
if(getActiveFlg() == 0){
// 一番初めの処理でフラグを立てておき、2回目以降は実行されないようにする
setActiveFlg(1);
// 後続処理
doSomething(lat, lng);
}
}
これで一番最初に起動されたonLocationChanged()のみで後続処理が発火され、2回目以降は発火させなくできます。
synchronizedもつけておけば、setActiveFlg(1)の前に他のスレッドがif文に割り込んで来ることもないため安心です。
これによって最も最速で位置情報を取得できたPROVIDERでのみ後続処理を実施できるため、結果的に位置情報の取得を高速化することができました。
参考:
Android位置情報の取得
LocationManager
Android開発 | 複数のプロバイダで並行して位置情報を取得する方法