動機
バックグラウンドで常に位置情報取得を行う必要が出てきて、探してみるもQiitaの記事は古いものばかり。
ほぼ公式のガイドを参考にしましたが、散らばっていて分かりづらい部分もあったので、ユースケース別にまとめてみます。
Case1. マップに表示するだけ
位置情報を使うアプリといえば大抵はこのユースケースでしょう。
その場合はMaps SDK for Androidを使うのがいいでしょう。現在地表示はSDK側で用意されており、SDK側が位置情報を取得、更新してくれるため、自身で現在地を取得することはないかと思います。
ただし、現在地の位置情報データ(緯度経度情報)を利用するためには、次のように自身で位置情報を取得する必要があります。1
Maps SDKにも現在地を取得する方法はありましたが、depricatedになっており、後述する方法に誘導されています。
Case2. 現在の位置情報を利用
Google Play services location APIを利用します。
Android frameworkのLocationManagerを利用する方法もありましたが、現在は非推奨になっています。
FusedLocationProviderClient
の lastLocation
で最新の位置情報を取ることができますが、古いことがあるので、自分で更新をかけて取得するべきでしょう。(端末が再起動した場合などはnullが返ってきてしまいます。)
ほぼ公式ガイド通りですが、以下簡単に現在地を更新し、取得する方法をみていきます。
1. 位置情報更新のリクエストを行う
更新頻度や、精度の設定を行います。電池消費にも関わるので、ここはアプリによってチューニングするところかと思います。
val locationRequest = LocationRequest.create()
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
.setInterval(LOCATION_REQUEST_INTERVAL)
2. 位置情報更新のコールバック作成
このコールバックを使って、現在地の Location
を取得します。
val locationCallback = object : LocationCallback() {
override fun onLocationResult(locationResult: LocationResult?) {
locationResult ?: return
location = locationResult.lastLocation
}
}
3. 現在地の更新情報をリクエストする
FusedLocationProviderClient
に上記で定義したリクエストと、コールバックを渡し、位置情報更新をリクエストします。
fun startLocationUpdates() {
// 定期的な位置情報の更新をリクエストする.
fusedLocationClient.requestLocationUpdates(locationRequest, locationCallback, null)
}
Case3. バックグラウンドでの位置情報取得
アプリの利用中にユーザがホームボタンを押したり、アプリが表にいないときがあります。
注意しないといけないのは、android8以上であれば、バックグラウンドの位置情報の制限を受けます。
ユーザがアプリを操作してる間だけ位置情報があれば良い、もしくは、位置情報の取得自体が遅延してもいいタイプのアプリを作るのであれば、あまり気にしなくても良いですが、ユーザがアプリを操作していない場合にも位置情報を定期的に取得する必要があるアプリもあるかと思います。
ナビアプリや、トラッキング系のアプリがこれにあたるでしょう。
この場合は フォアグラウンドサービス
で位置情報の更新を行います。2
[重要]android10だからといって、ACCESS_BACKGROUND_LOCATIONを求めなくてよい
android10からはより厳しくなっており、バックグラウンドで位置情報を取得する場合、 ACCESS_BACKGROUND_LOCATION
が必要と言われます。このパーミッションをユーザが許可しておらず、バックグラウンドで位置情報を取ってしまうと、システムから通知が表示されてしまいます。3
ここで ACCESS_BACKGROUND_LOCATION
をとりたくなるかと思いますが、推奨されていません。4
常時位置情報を取得する必要があれば、 フォアグラウンドサービス
を利用します。その際、マニフェストに android:foregroundServiceType="location"
を指定します。→リファレンス
まとめ
自身がどのように位置情報を使うか、ユースケースを考えることが重要です。
- マップに現在地を表示するだけ→map sdkだけで事足りるはず
- 位置情報(lat, long)に合わせたデータをapiなどから取得する→fusedLocation
- トラッキングなど、アプリが裏に行った時も常時位置情報が必要→フォアグラウンドサービス
参考
-
例えばユーザの現在地を元にサーバに問い合わせたり。 ↩
-
公式によるとフォアグラウンドサービスとは、アプリが表にいないといけないというわけではなく、通知を出す必要があり、ユーザが認識できるということで、フォアグラウンドという意味みたいです。 ↩
-
android10がリリースされて、バックグラウンドで位置情報を取っていたアプリが、軒並みこの通知で晒されてました。 ↩
-
どうしてもバックグランドサービスで位置情報を利用したい場合は、
ACCESS_BACKGROUND_LOCATION
をユーザに要求することはできます。ただし、システムから通知され、ユーザがオフにできてしまいます。位置情報の取得が短い期間でもフォアグランドサービスで起動すべきでしょう。 ↩