🗺️
FusedLocation - Androidで位置情報取得 -
概要
以前は LocationManager
を使っていたが、最近は Google Play Serviceの FusedLocation
を使うのが推奨されているらしい。
公式の説明を見ると、Providerどれ使うか?(GPS, wifi...)とバッテリー効率を考えて一番適した方法で位置情報を提供してくれる様子。
位置情報へのアクセスをリクエストする
アプリの権限をリクエストの基本 今一度確認
- 権限を必要とする機能をユーザーが操作し始めたら、その状況に応じた権限をリクエストすること
- ユーザーをブロックしないこと。権限に関連した説明を表示する UI フローは、常にキャンセルできるようにしてください
- 機能に必要な権限をユーザーが拒否または取り消した場合は、グレースフル デグラデーションを行いアプリの使用を続けられるようにすること
- システム動作を前提としないこと
権限の種類
-
ACCESS_FINE_LOCATION
- GPSやWi-Fi、モバイルデータなど、利用可能な位置情報プロバイダを使用し、できる限り正確な位置情報の特定を行います
-
ACCESS_COARSE_LOCATION
- Wi-Fiかモバイルルータ、あるいはその両方を使用し、都市の1区画程度の制度で位置情報の特定を行います
実装
まずは権限が付与されているかのチェック
private fun getLocationPermission() {
val permission = ContextCompat.checkSelfPermission(
this.applicationContext,
Manifest.permission.ACCESS_FINE_LOCATION
)
if (permission == PackageManager.PERMISSION_GRANTED) {
requestDeviceLocation()
} else if (permission == PackageManager.PERMISSION_DENIED) {
/* 以前ユーザーがリクエストを許可しなかった場合trueを返す
また「今後表示しない」を選択していた場合はfalseを返す */
if (ActivityCompat.shouldShowRequestPermissionRationale(
this,
Manifest.permission.ACCESS_FINE_LOCATION
)
) {
// ここでユーザーに説明用のUIを表示する
} else {
val requestPermissionLauncher =
registerForActivityResult(
ActivityResultContracts.RequestPermission()
) { isGranted: Boolean ->
if (isGranted) {
requestDeviceLocation()
} else {
Napier.w("Permission not granted")
}
}
requestPermissionLauncher.launch(
Manifest.permission.ACCESS_FINE_LOCATION
)
}
}
}
直近の位置情報を取得する
@SuppressLint("MissingPermission")
private fun requestDeviceLocation() {
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
try {
val locationResult = fusedLocationClient.lastLocation
locationResult.addOnCompleteListener { task ->
if (task.isSuccessful) {
val lastKnownLocation = task.result
if (lastKnownLocation != null) {
// lastKnownLocation.latitude と lastKnownLocation.longitude を使う
}
} else {
Napier.i("Request location updates")
locationCallback = object : LocationCallback() {
override fun onLocationResult(locationResult: LocationResult) {
locationResult.lastLocation.also {
// it.latitude と it.longitude を使う
}
}
}
startLocationUpdates()
requestingLocationUpdates = true
}
}
} catch (e: SecurityException) {
Napier.e("SecurityException", e)
}
}
@SuppressLint("MissingPermission")
private fun startLocationUpdates() {
locationCallback?.also {
fusedLocationClient.requestLocationUpdates(
LocationRequest.create().apply {
interval = 5000
priority = LocationRequest.PRIORITY_HIGH_ACCURACY
}, it, this.mainLooper
)
}
}
override fun onResume() {
super.onResume()
if (requestingLocationUpdates) {
startLocationUpdates()
}
}
override fun onPause() {
super.onPause()
locationCallback?.also {
fusedLocationClient.removeLocationUpdates(it)
}
}
Discussion