[Android] 위치 정보 파헤치기 (FusedLocationProvider vs LocationManager)

강승구·2023년 9월 26일

LocationManager의 문제점

안드로이드 디바이스의 위치를 획득하기 위해서는 API는 표준 라이브러리에 있는 LocationManager를 이용하여 LocationProvider 지정을 통해 getLastKnownLocation 함수를 이용해서 위치 획득이 가능하다.
LocationManaer는 두가지 방식으로 위치 정보를 획득한다.

  • GPS_PROVIER
    GNSS(Global Navigation Satellite System) 위성을 통해 위치정보를 파악한다. 그렇기 때문에 위성신호가 잡히지 않는 건물 내부에서는 위치정보 업데이트가 되지 않는다.

  • NETWORK_PROVIDER
    통신사 기지국의 Cell 타워와 근처 WiFi Access Point 정보를 통해 위치를 파악한다. Cell 타워나 WiFi AP의 위치정보는 Google에서 지속적으로 수집 및 업데이트를 하고 있다.

안드로이드 디바이스는 인터넷에 연결된 경우 구글의 서버에 주기적으로 위치정보와 인터넷 연결 정보를 업로드한다. 그리고 이렇게 수집된 정보들을 기반으로 구글 서버에서는 네트워크별로 위치 정보 테이블을 만들고 위치 정보를 알려준다.

예를 들어, Cell A 구역의 WiFi B에 연결한 기기들의 마지막 위치정보가 L1인 경우가 3건, L2인 경우가 2건인 경우, Network Provider는 "이 와이파이에 연결했던 기기의 마지막 위치 정보가 L1인 경우가 제일 많았으니까 L1일 것이다" 라며 위치정보를 L1으로 내려준다.

따라서 Network Provider의 경우 건물 내부에 있는 경우에도 위치정보를 제공해줄 수 있지만, GPS Provider의 경우 위성신호가 잡히지 않기 때문에 정보를 제공하지 못한다.

하지만 건물 밖으로 나가면 얘기가 달라집니다. 외부에서 GPS_PROVIDER는 위성 정보를 받아올 수 있기 때문에 높은 정확도로 움직임을 업데이트하지만 NETWORK_PROVIDER는 AP에서 AP로 순간이동을 하는 문제를 보인다.

또한 LocationProvider를 지정하는 부분이 실제 작업 시 여러 가지를 고려하다 보니 개발자 코드 양이 비대해진다.


FusedLocationProvider의 등장

FusedLocationProvider는 GPS와 NETWORK 위치 제공자의 간극을 매워주기 위해 출시되었다.

아래 그래프에서 파란색 선은 GPS_PROVIER의 성능을, 빨간색 선은 NETWORK_PROVIDER의 성능을, 주황색 그래프는 FusedLocationProvider의 성능을 나타낸다.

FusedLocationProvider는 내부와 외부에서 모두 높은 성능을 보이는 것을 알 수 있다.
그렇다면 FusedLocation은 어떻게 문제를 해결하였을까?

위 사진에서 큰 회색 원은 마지막으로 수집된 GPS 정보이고 파란색 줄은 사용자의 움직임을 추적한 선이다.
건물 내부에 들어갔다고 판단되면 FusedLocationProvider는 활용할 수 있는 모든 정보 (WiFi AP, 기타 하드웨어 센서)를 종합해 사용자가 있을 것으로 예상되는 위치를 계산한다.

위 사진에서 표시된 작은 점들이 계산된 위치이다. 점에 꼬리처럼 붙어있는 것은 예측되는 사용자의 방향이다. 그리고 이렇게 예측된 위치들의 밀도가 가장 높은 좌표를 최종 사용자 위치로 판단한다.

FusedLocationProvider가 위치를 계산하는 알고리즘은 매우 정밀하기 때문에 매우 높은 정확성을 보장한다.

또한 안드로이드 공식 문서에 따르면 Fused Location Provider은 다음과 같은 장점들이 존재한다.

  • Reduce Power (저전력)
  • Improve accuracy (정확도 향상)
  • Simplify the APIs (API 간소화)
  • Expose cool new features (새로운 기능)
  • make it available on most Android devices (대부분의 Android 기기에서 사용 가능)

사용법

1. dependency 추가

implementation("com.google.android.gms:play-services-location:21.0.1")

2. 위치 권한 획득

private fun requestLocationPermission(){
    ActivityCompat.requestPermissions(
        this,
        arrayOf(
            Manifest.permission.ACCESS_COARSE_LOCATION,
            Manifest.permission.ACCESS_FINE_LOCATION
        ),
        REQUEST_ACCESS_LOCATION_PERMISSION
    )
}

override fun onRequestPermissionsResult(
    requestCode: Int,
    permissions: Array<out String>,
    grantResults: IntArray
) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults)
    val locationPermissionGranted =
        requestCode == REQUEST_ACCESS_LOCATION_PERMISSION
                && grantResults[0] == PackageManager.PERMISSION_GRANTED

    if(locationPermissionGranted){
        // TODO
    }
}

companion object {
    private const val REQUEST_ACCESS_LOCATION_PERMISSION = 100
}

3. FusedLocationProvider 객체 초기화

private lateinit var fusedLocationProviderClient: FusedLocationProviderClient

private fun initFusedLocationProvider() {
	fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this)
}

4. 위치 정보 얻기

private var cancellationTokenSource: CancellationTokenSource? = null

if(locationPermissionGranted){
	cancellationTokenSource = CancellationTokenSource()
	fusedLocationProviderClient.getCurrentLocation(
		LocationRequest.PRIORITY_HIGH_ACCURACY,
		cancellationTokenSource!!.token
	).addOnSuccessListener {
		Log.d("location", it.altitude.toString())
		Log.d("location", it.longitude.toString())
	}
}

CancellationToken

CancellationToken은 위치 정보를 가져오는 작업을 취소하는데 사용되는 토큰이다. FusedLocationProvider를 사용하여 위치 정보를 요청할 때 CancellationToken을 매개변수로 전달할 수 있는데 이 CancellationToken은 작업이 너무 오래 걸리거나 사용자가 작업을 취소하려 할 때 작업을 중단하는데 사용할 수 있다.


참고

https://www.youtube.com/watch?v=MEjFW_tLrFQ

profile
강승구

0개의 댓글