위치 (Location)
위치는 카테고리와 정확성에 따라 나눌 수 있습니다.
- 카테고리 : 포그라운드 위치 또는 백그라운드 위치
- 정확성 : 대략적인 위치 또는 정확한 위치
포그라운드 위치
앱에 위치 정보를 특정 시간 동안 공유하거나 수신하는 기능이 포함되어 있다면 포그라운드 위치 정보 액세스 권한이 필요합니다.
현재 표시되고 있는 액티비티 또는 실행 중인 포그라운드 서비스가 현재 위치에 액세스한다면 시스템은 앱에서 포그라운드 위치를 사용하고 있다고 간주합니다.
포그라운드 위치를 사용하고 있는 포그라운드 서비스는 Android 10 (API 29) 이상부터는 다음과 같이 포그라운드 서비스 유형을 선언해야 합니다.
<!-- Recommended for Android 9 (API level 28) and lower -->
<!-- Required for Android 10 (API level 29) and higher -->
<service
android:name="MyService"
android:foregroundServiceType="location" >
</service>
또한, 다음과 같이 앱에서 ACCESS_COARSE_LOCATION 권한 또는 ACCESS_FINE_LOCATION 권한을 요청한다면 포그라운드 위치가 필요하다는 것을 의미합니다.
<manifest ... >
<!-- 대략적인 위치 -->
<!-- Always include this permission -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<!-- 정확한 위치 -->
<!-- Include only if your app benefits from precise location access. -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
</manifest>
백그라운드 위치
앱의 기능이 지속적으로 다른 사용자와 위치를 공유하거나 Geofencing API를 사용하는 경우에는 백그라운드 위치 정보 액세스 권한이 필요합니다.
앱에서 포그라운드 위치가 필요한 상황 이외의 모든 상황에서 현재 위치에 액세스한다면 시스템은 앱에서 백그라운드 위치를 사용하고 있다고 간주합니다.
Android 10 (API 29) 이상부터는 개발자는 런타임 시 백그라운드 위치 정보 액세스 권한을 요청하기 위해 앱 매니페스트에서 ACCESS_BACKGROUND_LOCATION 권한을 선언해야 합니다.
이전 버전의 Android에서는 앱이 포그라운드 위치 정보 액세스 권한을 수신하면 자동으로 백그라운드 위치 정보 액세스 권한도 수신합니다.
<manifest ... >
<!-- Required only when requesting background location access on
Android 10 (API level 29) and higher. -->
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
</manifest>
대략적인 위치
- ACCESS_COARSE_LOCATION 권한을 통해 대략적인 위치를 수신할 수 있습니다.
- 오차 범위는 약 3km 이내입니다.
- 정확한 위치가 필요 없는 경우는 대략적인 위치 권한만 사용합니다.
정확한 위치
- ACCESS_FINE_LOCATION 권한을 통해 정확한 위치를 수신할 수 있습니다.
- 오차 범위는 약 50m 이내입니다.
- Android 12 (API 31) 이후부터는 사용자가 대략적인 위치 권한만 허용할 수 있으므로 대략적인 위치 권한과 정확한 위치 권한을 동시에 요청해야 합니다.
런타임 시 위치 정보 액세스 권한 요청
앱의 기능에서 위치 정보 액세스 권한이 필요하다면 사용자가 이 기능과 상호작용할 때까지 기다린 후 런타임 권한을 요청합니다.
val locationPermissionRequest = registerForActivityResult(
ActivityResultContracts.RequestMultiplePermissions()
) { permissions ->
when {
permissions.getOrDefault(Manifest.permission.ACCESS_FINE_LOCATION, false) -> {
// Precise location access granted.
}
permissions.getOrDefault(Manifest.permission.ACCESS_COARSE_LOCATION, false) -> {
// Only approximate location access granted.
} else -> {
// No location access granted.
}
}
}
// 런타임 권한 요청
locationPermissionRequest.launch(arrayOf(Manifest.permission.ACCESS_COARSE_LOCATION))
마지막으로 알려진 위치 가져오기
앱에서 마지막으로 알려진 사용자 기기의 위치를 요청할 수 있는 방법에는 여러 가지가 있습니다.
Context.getSystemService() 함수의 LocationManager를 사용하거나 Google Play 서비스의 Location API 중 하나인 FusedLocationProviderClient를 사용하여 위치 정보를 조회할 수 있습니다.
여기서 FusedLocationProviderClient는 LocationManager보다 간편하고 기기의 배터리 전력 사용을 최적화해줍니다.
다음은 FusedLocationProviderClient을 사용하는 방법입니다.
- 마지막으로 알려진 위치 정보 가져오기 : FusedLocationProviderClient.getLastLocation()
- 캐싱된 데이터를 반환하기 때문에 위치 정보를 반환하는 속도가 빠릅니다.
- 휴대폰을 재부팅하거나 GPS를 껐다가 킨 경우에는 캐싱된 데이터가 제거되므로 null을 반환합니다.
- 캐싱 만료 시간을 지정하지 않기 때문에 위치의 신뢰도가 떨어집니다.
- 새로운 위치 정보 가져오기 : FusedLocationProviderClient.requestLocationUpdates()
- 신뢰할 수 있는 위치 정보를 받을 수 있습니다.
- 마지막에 알려진 위치를 조회할 때보다 상대적으로 요청 응답시간이 깁니다.
- stopLocationUpdates()를 호출해주지 않으면 리소스 낭비를 야기합니다.
private lateinit var fusedLocationClient: FusedLocationProviderClient
fusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
// 마지막으로 알려진 위치 정보 가져오기
fusedLocationClient.lastLocation
.addOnSuccessListener { location : Location? ->
// Got last known location. In some rare situations this can be null.
}
// 새로운 위치 정보 가져오기
fusedLocationClient.requestLocationUpdates(
locationRequest,
locationCallback,
Looper.getMainLooper()
)
// 위치 정보 업데이트 중지
private fun stopLocationUpdates() {
fusedLocationClient.removeLocationUpdates(locationCallback)
}
'안드로이드 > 활용' 카테고리의 다른 글
[Android] 네이버 지도 사용하기 (0) | 2023.09.13 |
---|---|
[Android] 앱 위젯 만들기 (0) | 2023.09.12 |
[Android] Firebase 기능 사용하기 (0) | 2023.09.03 |
[Android] Firebase (0) | 2023.08.29 |
[Android] Lottie 사용하기 (0) | 2023.08.22 |