Android/StoreInfo

<강의> 안드로이드 앱 개발 심화 - 사용자 위치 얻기

re트 2024. 1. 24. 15:54
728x90

1. 위치 접근 권한

protection level이 dangerous이기 때문에 사용자에게 권한을 요청하여 받아야함

1) android.permission.ACCESS_COARSE_LOCATION

- 와이파이나 모바일 데이터 또는 둘 다를 사용해 기기의 위치에 접근하는 권한

2) android.permission.ACCESS_FINE_LOCATION

- 위성, 와이파이, 모바일 데이터 등 이용할 수 있는 위치 제공자를 사용해 최대한 정확한 위치에 접근하는 권한

3) android.permission.ACCESS_BACKGROUND_LOCATION

- 안드로이드 10(API 레벨 29) 이상에서 백그라운드 상태에서 위치에 접근하는 권한

 

2. LocationManager

사용자의 위치를 얻기 위해 사용하는 시스템 서비스

val manager = getSystemService(LOCATION_SERVICE) as LocationManager

 

3. 위치 제공자

현재 기기에 어떤 위치 제공자가 있는지 알고 싶다면 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..

 

지금 사용할 수 있는 위치 제공자를 알고 싶다면 LocationManager의 getProviders() 함수를 사용

result = "Enabled Providers : "
val enabledProviders = manager.getProviders(true)
for (provider in enabledProviders) {
		result += " $provider. "
}
Log.d("maptest", result)  // Enabled Providers : passive, gps, network..

 

1) GPS

- GPS 위성을 이용

2) Network

- 이동 통신망을 이용

3) Wifi

- 와이파이를 이용

4) Passive

- 다른 앱에서 이용한 마지막 위치 정보를 이용

 

4. Criteria

Criteria 클래스에 조건을 명시하여 조건에 맞는 가장 최적의 위치 정보 제공자를 이용하는 방법

조건에 맞는 위치 정보 제공자가 없으면 알아서 조건이 조정됨

1) accuracy, setAccuracy()

- 정확도

2) isAltitudeRequired, setAltitudeRequired()

- 고도 제공 여부

3) isBearingRequired, setBearijngRequired()

- 방향 제공 여부

4) isSpeedRequired, setSpeedRequired()

- 속도 제공 여부

5) isCostAllowed, setCostAllowed()

- 비용 허용 여부

6) powerRequirement, setPowerRequirement()

- 전원 소모량

 

 

5. 위치 정보 

1) 한번만 위치 정보를 가져오는 경우

- LocationManager의 getLastKnownLocation() 함수 사용

- Location은 위치의 정확도, 위도, 경도, 획득 시간 등의 데이터를 포함

  > accuracy, getAccuracy() : 정확도

  > latitude, getLatitude() : 위도

  > longitude, getLongitude() : 경도

  > time, getTime() : 획득 시간

  > altitude, getAltitude() : 고도

  > bearing, getBearing() : 방위

  > provider, getProvider() : 위치 정보 제공자

  > speed, getSpeed() : 속도

  > elapsedRealtimeNanos, getElapsedRealtimeNanos() : 획득시간(나노초)

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")
    }
}

 

2) 계속 위치 정보를 가져와야하는 경우

- LocationListener 사용

  > onLocationChanged() : 새로운 위치를 가져오면 호출됨

  > onProviderEnabled() : 위치 제공자가 이용할 수 있는 상황이면 호출됨

  > onProviderDisabled() : 위치 제공자가 이용할 수 없는 상황이면 호출됨

val listener: LocationListener = object : LocationListener {
    override fun onLocationChanged(location: Location) {
        Log.d("map_test,","${location.latitude}, ${location.longitude}, ${location.accuracy}")
    }
}

// 10초마다 업데이트, 10m 변경될 때마다 업데이트
manager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 10_000L, 10f, listener)
// (.. 생략 ..) //
manager.removeUpdates(listener)

 

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

구글에서는 최적의 알고리즘으로 위치 제공자를 지정할 수 있도록 Fused Location Provider라는 라이브러리를 제공

implementation 'com.google.android.gms:play-services:12.0.1'

 

위치정보를 가져오는 FusedLocationProviderClient 초기화

val providerClient = LocationServices.getFusedLocationProviderClient(this)

 

GoogleApiClient의 ConnectionCallbacks와 OnConnectionFailedListener 오버라이딩

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) {
        // 사용할 수 있는 위치 제공자가 없을 때
    }
}

 

GoogleApiClient의 Builder를 가지고 객체 생성

val apiClient = GoogleApiClient.Builder(this)
     .addApi(LocationServices.API)
     .addConnectionCallbacks(connectionCallback)
     .addOnConnectionFailedListener(onConnectionFailCallback)
     .build()

 

GoogleApiClient 객체에 위치 제공자 요청

apiClient.connect()

 

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()
    }
}
반응형