개발 노트/Kotlin

[Android/Kotlin] 사용자 위치 얻기

juwon2 2024. 5. 1. 00:27

# 위치 접근 권한

 

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

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

 

 

# 권한 설정

안드로이드 애플리케이션에서 특정 기능을 사용하기 위해서는 해당 기능에 필요한 권한을 사용자로부터 획득해야 한다. 권한 요청 절차는 사용자의 동의를 얻는 과정을 포함하며, 보안과 사용자의 개인정보 보호를 위해 필수적이다

 

# 매니페스트에 권한추가

앱이 위치 정보에 접근하려면, 먼저 AndroidManifest.xml 파일에 위치 권한을 추가해야 한다

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.myapp">

    <!-- 정밀 위치 권한 요청 -->
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

    ...
</manifest>

 

 

# 권한 요청

런타임 시, 앱은 사용자에게 권한을 요청해야 한다. 안드로이드 6.0(API 레벨 23) 이상에서는 사용자가 앱을 사용하는 동안 권한을 부여하거나 취소할 수 있다

 

아래는 ACCESS_FINE_LOCATION 권한을 요청하고 획득하는 예제 코드다

class MainActivity : AppCompatActivity() {

    companion object {
        private const val PERMISSION_REQUEST_ACCESS_FINE_LOCATION = 100
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        requestLocationPermission()
    }

    private fun requestLocationPermission() {
        if (ContextCompat.checkSelfPermission(
                this,
                Manifest.permission.ACCESS_FINE_LOCATION
            ) != PackageManager.PERMISSION_GRANTED
        ) {
            // 권한이 없을 경우, 사용자에게 요청
            ActivityCompat.requestPermissions(
                this,
                arrayOf(Manifest.permission.ACCESS_FINE_LOCATION),
                PERMISSION_REQUEST_ACCESS_FINE_LOCATION
            )
        } else {
            // 권한이 이미 있을 경우, 위치 정보를 사용할 수 있음
            getLocation()
        }
    }

    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<String>,
        grantResults: IntArray
    ) {
        when (requestCode) {
            PERMISSION_REQUEST_ACCESS_FINE_LOCATION -> {
                if ((grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
                    // 권한이 부여되면 위치 정보를 사용할 수 있음
                    getLocation()
                } else {
                    // 권한이 거부되면, 기능 사용 불가
                }
                return
            }
        }
    }

    private fun getLocation

MainActivity.kt

 

위 코드에서 requestLocationPermission 함수는 먼저 앱에 위치 권한이 있는지 확인한다.

권한이 없다면 ActivityCompat.requestPermissions 메소드를 사용하여 권한을 요청하고, 결과는 onRequestPermissionsResult 콜백 메소드에서 처리한다. 사용자가 권한을 부여하면 getLocation 메소드를 호출하여 위치 정보를 사용할 수 있다

 

 

 

 

 

 

# 플랫폼 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")
            }
        }

위치 한번만 가져오기

 

 

 

  • 위치정보얻기 (계속 위치를 가져오는 법) - ex) 이동하는 위치가 필요할 때

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

위치 계속 가져오기