Y_Ding

사용자 위치 얻기 본문

TodayILearned/Android&Kotlin

사용자 위치 얻기

YJ_ILY 2023. 9. 14. 16:32
  • 지도를 이용해서 서비스를 제공하는 앱을 만들 경우 필요
  • 네이버맵, 다음맵 등 다양한 플랫폼에서 제공하는 맵을 사용
  • 맵을 사용하려면 내 단말을 통해 위치를 얻어와야 함
  • 위치를 얻으려면 권한이 필요

사용자의 위치를 추적하기 위한 3가지 권한

  • android.permission.ACCESS_COARSE_LOCATION :
    • 와이파이나 모바일 데이터를 사용해 기기의 위치에 접근하는 권한
    • 도시에서 1블록 정도의 오차 수준
  • android.permission.ACCESS_FINE_LOCATION :
    • 위성, 와이파이, 모바일 데이터 등 이용할 수 있는 위치 제공자를 사용해 최대한 정확한 위치에 접근하는 권한
    • 많이 사용하는 접근 권한
  • android.permission.ACCESS_BACKGROUND_LOCATION :
    • 안드로이드 10(API 레벨 29) 이상에서 백그라운드 상태에서 위치에 접근하는 권한

플랫폼 API의 위치 매니저를 이용해 사용자의 위치를 얻는 방법

  • LocationManager 라는 시스템 서비스 이용
  • LocationManager는 모든 스마트폰의 프레임워크 안에 들어있음
val manager = getSystemService(LOCATION_SERVICE) as LocationManager
  • 위치 제공자 지정하기 (위치를 어디서 받을지)
    • GPS, Network, Wifi, Passive(다른 앱에서 이용한 마지막 위치 정보 이용)

위치 정보를 받는 방법

  • 현재 기기에 어떤 위치 제공자가 있는지 알아보기 
val result = "All Providers :"
//allProviders 프로퍼티 이용해 현재 기기에 어떤 위치 제공자가 있는지 알 수 있음
val providers = manager.allProviders
for (provider in providers) {
	result += "$provider."
}
Log.d("maptest", result)

* 현재 기기에 어떤 위치 제공자가 있는지 알고싶다면?
		LocationManager의 allProviders 프로퍼티 이용
  • 지금 사용할 수 있는 위치 제공자를 알아보기 (getProviders() 함수)
result = "Enabled Providers :"
val enabledProviders = manager.getProviders(true)
for (provider in enabledProviders) {
	result += "$provider."
}
Log.d("maptest", result)
  • 위치 정보 얻기 (getLastKnownLocation() 함수)
// Permission이 있는지 먼저 체크
if (ContextCompat.checkSelfPermission(
                this,
                Manifest.permission.ACCESS_FINE_LOCATION
            ) == PackageManager.PERMISSION_GRANTED
        ) {
        // Permission이 획득이 되어있다면 로케이션 매니저를 가져오기
            val location: Location? = manager.getLastKnownLocation(LocationManager.GPS_PROVIDER)
            location?.let{
                val latitude = location.latitude
                val longitude = location.longitude
                val accuracy = location.accuracy
                val time = location.time
                Log.d("map_test", "$latitude, $location, $accuracy, $time")
            }
        }
        
* getAccuracy() : 정확도
* getLatitude() : 위도
* getLongitude() : 경도
* getTiem() : 획득 시간
  • 계속해서 위치를 가져와야 한다면 LocationListener를 이용(예: 내비게이션)
// 
val listener: LocationListener = object : LocationListener {
            override fun onLocationChanged(location: Location) {
                Log.d("map_test,","${location.latitude}, ${location.longitude}, ${location.accuracy}")
            }
        }
        // 지정해주어야 함
        manager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 10_000L, 10f, listener)
        // (.. 생략 ..) //
        // 업데이트가 끝나면 removeUpdates 사용해서 꼭 삭제해줘야함
        manager.removeUpdates(listener)
        
 * onLocationChanged() : 새로운 위치를 가져오면 호출됨
 * onProviderEnabled(): 위치 제공자가 이용할 수 있는 상황이면 호출됨
 * onProviderDisabled() : 위치 제공자가 이용할수 없는 상황이면 호출됨

구글 Play 서비스의 위치 라이브러리

  • 편리하고 정확도가 더 높음
  • 최적의 알고리즘으로 위치 제공자를 지정할 수 있도록 Fused Location Provider 라이브러리를 제공
  • gradle 설정 파일에 아래와 같은 코드를 추가해야 사용 가능
implementation 'com.google.android.gms:play-services:12.0.1'

위치 제공자를 지정할 때 고려할 사항

  • 전력을 적게 소비하는가
  • 정확도는 높은가
  • API가 간단한가
  • 부가 기능을 제공하는가
  • 대부분 안드로이드 기기를 지원하는가

Fused Location Provider

  • FusedLocationProviderClient : 위치 정보를 얻음
  • GoogleApiClient : 위치 제공자 준비 등 다양한 콜백 제공
val connectionCallback = object: GoogleApiClient.ConnectionCallbacks{
            override fun onConnected(p0: Bundle?) {
                // 위치 제공자를 사용할 수 있을 때
                // 위치 획득
            }

            override fun onConnectionSuspended(p0: Int) {
                // 위치 제공자를 사용할 수 없을 때
            }
        }
        val onConnectionFailCallback = object : GoogleApiClient.OnConnectionFailedListener{
            override fun onConnectionFailed(p0: ConnectionResult) {
                // 사용할 수 있는 위치 제공자가 없을 때
            }
        }
        // 선언할 때
        val apiClient = GoogleApiClient.Builder(this)
            .addApi(LocationServices.API)
            .addConnectionCallbacks(connectionCallback)
            .addOnConnectionFailedListener(onConnectionFailCallback)
            .build()
FusedLocationProviderClient 초기화
val providerClient = LocationServices.getFusedLocationProviderClient(this)

GoogleApiClient 객체에 위치 제공자를 요청
apiClient.connect()
  • onConnect() 함수에서 FusedLocationProviderClient의 getLastLocation() 함수 호출
// 위치 제공자를 사용할 수 있는 상황일 때
    override fun onConnected(p0: Bundle?) {
        if(ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) 
        								=== PackageManager.PERMISSION_GRANTED){
            providerClient.lastLocation.addOnSuccessListener(
                this@MainActivity,
                object: OnSuccessListener<Location> {
                    override fun onSuccess(p0: Location?) {
                        p0?.let {
                            val latitude = p0.latitude
                            val longitude = p0.longitude
                            Log.d("map_test", "$latitude, $longitude")
                        }
                    }
                }
            )
            apiClient.disconnect()
        }
    }

'TodayILearned > Android&Kotlin' 카테고리의 다른 글

코틀린 이해하기  (0) 2023.09.14
구글 지도앱 만들기  (2) 2023.09.14
안드로이드 앱의 기본 구조  (2) 2023.09.14
Room  (0) 2023.09.13
SharedPreferences  (4) 2023.09.13