Android 12에서는 「대략」의 위치 정보를 선택할 수 있게 되지만, LocationManager에서는 위치 정보의 갱신을 받을 수 없는 것 같다

Android 12에서는 다음과 같이 런타임 권한 대화 상자나 설정 화면에서 '정확한' 위치 정보를 허용하지 않고 '대략'의 위치 정보만 허용할 수 있게 되는 것 같습니다.


권한 대화 상자
앱 설정






「대략」의 위치 정보가 허가된 상태, 정확한 위치 정보가 오프의 상태라고 하는 것은, ACCESS_FINE_LOCATION 는 허가되지 않고, ACCESS_COARSE_LOCATION 만이 허가된 상태가 되어 있습니다.
안드로이드 12까지는 ACCESS_FINE_LOCATION 전제로 나누어진 구현을 하고 있었을 경우는, ACCESS_FINE_LOCATION 만이 허가된 상태를 고려하도록 변경이 필요하네요.

ACCESS_COARSE_LOCATION에서 LocationManager에서 위치 정보 업데이트를받지 못합니까?



그런데, 이것만이라면 「유저의 선택사항이 늘어났다」로 끝입니다만, Android 4.2 무렵부터 ACCESS_FINE_LOCATION 만이 허가된 상태에서는 ACCESS_COARSE_LOCATIONACCESS_COARSE_LOCATION 소문을 들었습니다.

그래서 검증해 보겠습니다.
Log.e("XXXX", "ACCESS_COARSE_LOCATION: ${checkPermission(Manifest.permission.ACCESS_COARSE_LOCATION)}")
Log.e("XXXX", "ACCESS_FINE_LOCATION: ${checkPermission(Manifest.permission.ACCESS_FINE_LOCATION)}")

val manager: LocationManager = getSystemService()!!
manager.allProviders.forEach { provider ->
    Log.e("XXXX", "getLastKnownLocation: $provider ${manager.getLastKnownLocation(provider)}")
    manager.requestLocationUpdates(
        provider, 1, 1f, LocationListenerAdapter {
            Log.e("XXXX", "onLocationChanged: $provider $it")
        })
    LocationManagerCompat.getCurrentLocation(manager, provider, null, ContextCompat.getMainExecutor(this), {
        Log.e("XXXX", "getCurrentLocation: $provider $it")
    })
}

각 Provider에 대해 ACCESS_COARSE_LOCATION/LocationManager.requestLocationUpdates/onLocationChanged를 호출하여 결과를 표시합니다.
먼저 권한 상태를 확인합니다. 구현은 다음과 같습니다.
private fun checkPermission(permission: String): String =
    if (PermissionChecker.checkSelfPermission(this, permission) ==
        PermissionChecker.PERMISSION_GRANTED
    ) "GRANTED" else "DENIED"

검증 환경은 Android 12 Beta 5의 Pixel5입니다.

정확한 위치 정보가 허용된 상태



먼저 FINE_LOCATION이 허용된 상태에서 살펴보겠습니다.
ACCESS_COARSE_LOCATION: GRANTED
ACCESS_FINE_LOCATION: GRANTED
getLastKnownLocation: passive Location[fused 34.xxxxxx,135.xxxxxx hAcc=20.0 et=+1d22h2m57s39ms alt=37.860162605487275 vAcc=3.0]
getLastKnownLocation: network Location[network 34.xxxxxx,135.xxxxxx hAcc=20.0 et=+1d22h2m41s72ms alt=38.30000305175781 vAcc=1.3333334 {Bundle[mParcelledData.dataSize=68]}]
getLastKnownLocation: fused Location[fused 34.xxxxxx,135.xxxxxx hAcc=20.0 et=+1d22h2m57s39ms alt=37.860162605487275 vAcc=3.0]
getLastKnownLocation: gps null
onLocationChanged: passive Location[fused 34.xxxxxx,135.xxxxxx hAcc=20.0 et=+1d22h2m57s39ms alt=37.860162605487275 vAcc=3.0]
getCurrentLocation: passive Location[fused 34xxxxxx,135.xxxxxx hAcc=20.0 et=+1d22h2m57s39ms alt=37.860162605487275 vAcc=3.0]
getCurrentLocation: network Location[network 34.xxxxxx,135.xxxxxx hAcc=20.0 et=+1d22h2m41s72ms alt=38.30000305175781 vAcc=1.3333334 {Bundle[mParcelledData.dataSize=68]}]
getCurrentLocation: fused Location[fused 34.xxxxxx,135.xxxxxx hAcc=20.0 et=+1d22h2m57s39ms alt=37.860162605487275 vAcc=3.0]
onLocationChanged: fused Location[fused 34.xxxxxx,135.xxxxxx hAcc=20.0 et=+1d22h3m2s50ms alt=37.860162605487275 vAcc=3.0]
onLocationChanged: network Location[network 34.xxxxxx,135.xxxxxx hAcc=12.191 et=+1d22h3m3s604ms alt=38.30000305175781 vAcc=1.3333334 {Bundle[mParcelledData.dataSize=68]}]
getCurrentLocation: gps null
getLastKnownLocation 가 null 를 돌려주고 있습니다만, 각각 어떤 PROVIDER 가 위치 정보를 돌려주고 있습니다.requestLocationUpdates 로 위치 정보가 취해져 있기 때문에 getCurrentLocation 의 상태에서도 위치 정보를 취할 수 있을 것 같습니다.

대략적인 위치 정보만 허용된 상태



계속해서 GPS_PROVIDER 만이 허가된 상태로 실행해 봅니다.
ACCESS_COARSE_LOCATION: GRANTED
ACCESS_FINE_LOCATION: DENIED
getLastKnownLocation: passive Location[fused 34.xxxxxx,135.xxxxxx hAcc=2000.0 et=+1d22h8m57s325ms]
getLastKnownLocation: network Location[network 34.xxxxxx,135.xxxxxx hAcc=2000.0 et=+1d22h5m18s717ms]
getLastKnownLocation: fused Location[fused 34.xxxxxx,135.xxxxxx hAcc=2000.0 et=+1d22h8m57s325ms]
getLastKnownLocation: gps null
getCurrentLocation: passive null
getCurrentLocation: network null
getCurrentLocation: fused null
getCurrentLocation: gps null
NETWORK_PROVIDER 에서는 위치 정보가 취해지고 있습니다만, ACCESS_COARSE_LOCATION 에서는 모두 null, ACCESS_COARSE_LOCATION 에서는 getLastKnownLocation 가 호출되지 않습니다.

음, 무슨 일이야?

FusedLocationProviderClient의 경우



FusedLocationProviderClient가 등장하고 나서는, 이쪽이 추천되고 있는 일도 있어, 위치 정보는 사용하지만, LocationManager는 사용하고 있지 않다고 하는 앱도 많을까 생각합니다. (GoogleAPI를 사용할 수 없는 환경에서는 사용할 수 없습니다만)
FusedLocationProviderClient의 경우 동작은 어떻게됩니까? 확인해 보겠습니다.
Log.e("XXXX", "ACCESS_COARSE_LOCATION: ${checkPermission(Manifest.permission.ACCESS_COARSE_LOCATION)}")
Log.e("XXXX", "ACCESS_FINE_LOCATION: ${checkPermission(Manifest.permission.ACCESS_FINE_LOCATION)}")

val client = LocationServices.getFusedLocationProviderClient(this)
client.requestLocationUpdates(LocationRequest.create(), object : LocationCallback() {
    override fun onLocationResult(location: LocationResult) {
        Log.e("XXXX", "onLocationResult: $location")
    }
}, Looper.getMainLooper())
val task = client.getCurrentLocation(LocationRequest.PRIORITY_LOW_POWER, null)
task.addOnSuccessListener {
    Log.e("XXXX", "onSuccess: $it")
}

정확한 위치 정보가 허용된 상태



당연히 FINE_LOCATION이 허용되면 문제가 없습니다.
ACCESS_COARSE_LOCATION: GRANTED
ACCESS_FINE_LOCATION: GRANTED
onLocationResult: LocationResult[locations: [Location[fused 34.xxxxxx,135.xxxxxx hAcc=12.552 et=+1d22h20m3s986ms alt=37.799487734693756 vAcc=3.0 {Bundle[mParcelledData.dataSize=52]}]]]
onSuccess: Location[fused 34.xxxxxx,135.xxxxxx hAcc=12.552 et=+1d22h22m40s542ms alt=37.799487734693756 vAcc=3.0 {Bundle[mParcelledData.dataSize=52]}]

대략적인 위치 정보만 허용된 상태



FusedLocationProviderClient라면 COARSE_LOCATION만으로도 문제없이 얻을 수 있습니다.
ACCESS_COARSE_LOCATION: GRANTED
ACCESS_FINE_LOCATION: DENIED
onLocationResult: LocationResult[locations: [Location[fused 34.738739,135.394036 hAcc=2000.0 et=+1d22h19m14s26ms]]]
onSuccess: Location[fused 34.xxxxxx,135.xxxxxx hAcc=2000.0 et=+1d22h20m0s359ms]

요약


getCurrentLocation 만이 허가된 상태에서는 LocationManager 에서는 위치 정보의 갱신을 받을 수 없고, requestLocationUpdates 로 밖에 위치 정보를 취할 수 없습니다.
한편, FusedLocationProviderClient라면 문제 없게 위치 정보의 갱신을 받을 수 있는 것 같습니다.

FusedLocationProviderClient를 도입하면 문제가 없습니다. GoogleAPI를 사용할 수 없는 환경이라면 onLocationChanged를 잘 사용해야 할 것입니다.

다만, ACCESS_COARSE_LOCATION 가 콜되지 않는 것이 사양대로라고 하는 것은 아니다고 생각합니다만, Android 4.2로부터 움직이고 있지 않다고 하는 이야기가 사실이라면, 왜 아직 수정되지 않는지 모릅니다. 수수께끼입니다.

이상

좋은 웹페이지 즐겨찾기