Kotlin android (사용자 위치 얻기)

subak96·2023년 9월 14일
1

여러 앱들을 사용하다보면 주로 뜨는 안내문구를 본 적이 있을것이다.

"GPS 위치 권한을 허용하시겠습니까?" 라는 문구다.

오늘은 이 위치 권한을 얻는 방법을 알아보고자 한다.

위치 접근 권한

먼저 사용자의 위치를 주적하기 위한 3가지의 권한이 있다.

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

말 그대로 와이파이나 위성, 모바일데이터를 이용해서 사용자의 기기에 접근하는 방식이다. 그리고 백그라운드 상태 또한 많이들 들어봤을겄이다. 이는 어플이 화면상 꺼져있더라도 어플 자체는 실행중인 상태라고 생각하면 된다. 쉽게 현재 존재하는 게임으로 예를 들자면 모바일 게임인 포켓몬** 을 생각하면 된다. 어플을 꺼놓고 걷더라도 내가 얼마나 걸었는지 얼마나 멀리 갔는지 알 수있다.

플래폼 API의 위치 매니저

  • 사용자의 위치를 얻을 때는 LocationManager라는 시스템 서비스를 이용
	val manager = getSystemService(LOCATION_SERVICE) as LocationManager
    
  • 위치 제공자 지정하기

    • GPS: GPS 위성을 이용합니다.
    • Network: 이동 통신망을 이용합니다.
    • Wifi: 와이파이를 이용합니다.
    • Passive: 다른 앱에서 이용한 마지막 위치 정보를 이용합니다.
  • 현재 기기에 어떤 위치 제공자가 있는지를 알고 싶다면 LocationManager의 allProviders 프로퍼티를 이용

    		var result = "All Providers : "
    		val providers = manager.allProviders
    		for (provider in providers) {
    		result += " $provider. "
    		}
    		Log.d("maptest", result)  // All Providers : passive, gps, network..
    		//모든 위치 제공자 알아보기
      
      
  • 지금 사용할 수 있는 위치 제공자를 알아보려면 getProviders() 함수를 이용

     result = "Enabled Providers : "
    		val enabledProviders = manager.getProviders(true)
    		for (provider in enabledProviders) {
    		result += " $provider. "
    		}
    		Log.d("maptest", result)  // Enabled Providers : passive, gps, network..
    		//지금 사용할 수 있는 위치 제공자 알아보기
     
     
     
  • 위치정보얻기

    • LocationManager의 getLastKnownLocation() 함수를 이용
    • Location은 위치의 정확도, 위도, 경도, 획득 시간 등의 데이터를 포함
      • getAccuracy(): 정확도

      • getLatitude(): 위도

      • getLongitude(): 경도

      • getTime(): 획득 시간

        		if (ContextCompat.checkSelfPermission(
        		this,
        		Manifest.permission.ACCESS_FINE_LOCATION
        		) == PackageManager.PERMISSION_GRANTED
        		) {
        		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")
        		}
        		}
        		//위치 한 번만 가져오기
  • 계속 위치를 가져와야 한다면 LocationListener를 이용

    • onLocationChanged(): 새로운 위치를 가져오면 호출됩니다.
    • onProviderEnabled(): 위치 제공자가 이용할 수 있는 상황이면 호출됩니다.
    • onProviderDisabled(): 위치 제공자가 이용할 수 없는 상황이면 호출됩니다.
      	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)
      	// (.. 생략 ..) //
      	manager.removeUpdates(listener)
      	//위치 계속 가져오기

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

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

    • 전력을 적게 소비하는가?
    • 정확도는 높은가?
    • API가 간단한가?
    • 부가 기능을 제공하는가?
    • 대부분 안드로이드 기기를 지원하는가?
  • 구글에서는 최적의 알고리즘으로 위치 제공자를 지정할 수 있도록 Fused Location Provider라는 라이브러리를 제공

    		implementation 'com.google.android.gms:play-services:12.0.1' 
            //구글 play 서비스 사용 선언
            
  • Fused Location Provider에서 핵심 클래스

    • FusedLocationProviderClient: 위치 정보를 얻습니다.
    • GoogleApiClient: 위치 제공자 준비 등 다양한 콜백을 제공합니다. GoogleApi Client에서는 GoogleApiClient.ConnectionCallbacks와 GoogleApiClient.OnConnection FailedListener 인터페이스를 구현한 객체를 지정
      	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()
      
      	//GoogleApiClient 초기화
  • FusedLocationProviderClient 초기화

    		val providerClient = LocationServices.getFusedLocationProviderClient(this)
      
            //FusedLocationProviderClient 초기화
            
  • GoogleApiClient 객체에 위치 제공자를 요청

    		apiClient.connect()
      
           //GoogleApiClient 객체에 위치 제공자를 요청
           
  • onConnected() 함수에서 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()
    		}
    		}
      

이상 위치 권한을 받아오는 법을 알아보았다.

0개의 댓글