やしのブログ

無能底辺院生やらせていただいてます

Androidで位置情報の取得

アプリに位置情報を利用した機能を実装しようと思い、Androidでの現在位置の取得について調べた.
ブログやら記事やら見てもどれが最新なのかいまいちわからなかったので今回は公式のトレーニングに従って実装してみた.

developer.android.com

この方法はGoogle Play Servicesを利用した方法でサービスが保持している直近の位置情報を取得することができる.
保持している情報というわけで過去の情報となるわけだがほとんどの場合で現在地と一致するらしい.

準備

Google Play Servicesを利用するとのことなのでGoogle Play Servicesのコンポーネントをプロジェクトに導入する必要がある.
Set Up Google Play Services  |  Google APIs for Android  |  Google Developers
導入の方法に関してはここを参考にした.
Google Play Servicesで1つのライブラリになっているのかと思いきやサービスごとに分かれているらしい.
今回は位置情報サービスにアクセスするのでそれっぽいGoogle Location and Activity Recognitionを選んで導入.
appの方のbuild.gradleのdependenciesに以下を追記.
バージョンに関しては上記のサイトのリストが最新バージョンになっている(らしい)のでこれをコピペした.

    implementation 'com.google.android.gms:play-services-location:11.8.0'

追記後にsyncを行うことでGoogle Location and Activity Recognitionのモジュールが導入される.

権限

位置情報にアクセスするためには権限が居るのでAndroidManifest.xmlにその旨を記述する.
権限には以下の2種類がある.

  • ACCESS_COARSE_LOCATION
    • 都市レベル(?)の精度で取得する(たぶん市町村レベル)
  • ACCESS_FINE_LOCATION
    • 高精度で位置情報を取得

ここで選択した精度がAPIによって返される位置情報の精度を決定する…らしいのだが高精度の位置情報を取得しようとしてACCESS_FINE_LOCATIONだけを書いて実行したらいくら待ってもコールバックが呼ばれない事態に陥った.
試しにACCESS_COARSE_LOCATIONとACCESS_FINE_LOCATIONを併記したら高精度で位置情報を取得できたので併記する必要があるらしい.
というわけで高精度で位置情報を取得する場合は以下のようになった.
市町村レベルでよければACCESS_FINE_LOCATIONの方を消せばよい.

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

実装

まずはこれで初期化を行う.

FusedLocationProviderClient mFusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this);

そして位置情報の取得を行う.
結果はコールバックで帰ってくるので登録を行う.

mFusedLocationProviderClient.getLastLocation().addOnSuccessListener(new OnSuccessListener<Location>() {
    @Override
    public void onSuccess(Location location) {
        if(location==null){
            Log.d("Result","location is null");
        }else{
             Log.d("Result","("+location.getLongitude()+","+location.getLatitude()+")");
        }
    }
});

この例では緯度と経度をログに出力している.
また,環境によってはnullが帰ってくることもあるらしいのでチェックを行う.

ここまでのコードで位置情報の取得はできるのだがパーミッションのチェックを行わないとAndroid Studioから怒られるので(ビルドもできない?)getLastLocation()を呼ぶ前に以下のようなコードを挿入する必要がある.

if(ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.ACCESS_COARSE_LOCATION)!= PackageManager.PERMISSION_GRANTED){
    return;
}

これで位置情報を取得できる.

以下が実装した例.
github.com

Last Locationということもあり待ち時間なく取得できる.
位置情報の取得というと時間がかかるイメージがあったけどこれなら使いやすいかも.

追記

自分の持ってる端末のバージョンがAndroid5.1だから問題なかったけどパーミッションまわりで許可を求めるダイアログが必要らしい.