[Android/Kotlin] 사용자 위치 얻기
# 위치 접근 권한
사용자의 위치를 추적하기위한 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)
위치 계속 가져오기