이 앱에서는 사용자가 산책을 할 때 위치를 추적할거에요.
<manifest ... >
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
...
</manifest>
class TrackingService: LifecycleService() {
lateinit var fusedLocationProviderClient: FusedLocationProviderClient
//...
override fun onCreate() {
super.onCreate()
//...
fusedLocationProviderClient = getFusedLocationProviderClient(this)
//...
}
LocationRequest
데이터 객체에서 정의해요.interval
은 위치 요청에 필요한 수신 간격이에요.fastestInterval
은 위치 요청에 필요한 가장 빠른 수신 간격이에요.priority
는 위치 요청에 필요한 정확도를 설정해요.이 앱에서는 가장 정확한 위치를 요청하는
PRIORITY_HIGH_ACCURACY
를 설정했어요.
@SuppressLint("MissingPermission")
private fun updateLocationChecking(isTracking: Boolean) {
if (isTracking) {
if (TrackingUtility.hasLocationPermissions(this)) {
val locationRequest = LocationRequest.create().apply {
interval = LOCATION_UPDATE_INTERVAL
fastestInterval = FASTEST_LOCATION_INTERVAL
priority = PRIORITY_HIGH_ACCURACY
}
//...
}
} else {
//...
}
}
LocationCallback.onLocationResult()
콜백 메서드에 포함되어 있는 Location
객체로 얻어올 수 있어요.val locationCallback = object : LocationCallback() {
override fun onLocationResult(locationResult: LocationResult) {
super.onLocationResult(locationResult)
if (isTracking.value!!) {
locationResult?.locations?.let {
for (location in it) {
// Update UI with location data
}
}
}
}
}
requestLocationUpdates()
로 갱신 되는 위치를 확인할 수 있어요.removeLocationUpdates
로 위치 갱신을 중지할 수 있어요.이 앱에서는 사용자가 산책 시작 버튼을 눌렀을 때 위치를 갱신하고 산책 끝 버튼을 눌렀을 때 위치 요청을 중지해요.
@SuppressLint("MissingPermission")
private fun updateLocationTracking(isTracking: Boolean) {
if (isTracking) {
if (TrackingUtility.hasLocationPermissions(this)) {
//...
fusedLocationProviderClient.requestLocationUpdates(
locationRequest,
locationCallback,
Looper.getMainLooper()
)
}
} else {
fusedLocationProviderClient.removeLocationUpdates(locationCallback)
}
}
dependencies {
implementation 'com.vmadalin:easypermissions-ktx:1.0.0'
}
fun hasLocationPermissions(context: Context) =
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
EasyPermissions.hasPermissions(
context,
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION
)
} else {
EasyPermissions.hasPermissions(
context,
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_BACKGROUND_LOCATION
)
}
class TrackingFragment : Fragment(R.layout.fragment_tracking), EasyPermissions.PermissionCallbacks {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
//...
binding.btnStart.setOnClickListener {
if(TrackingUtility.hasLocationPermissions(requireContext())){
sendCommandToService(ACTION_START_OR_RESUME_SERVICE)
}else {
requestPermissions()
}
}
//...
}
// ...
private fun requestPermissions() {
if (TrackingUtility.hasLocationPermissions(requireContext())) { // 권한이 있는 경우에는 권한을 요청하지 않습니다.
return
}
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
EasyPermissions.requestPermissions(
this,
"'어야가자' 이용을 위해 위치 권한을 '허용'으로 선택해주세요.",
Constants.REQUEST_CODE_LOCATION_PERMISSION,
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION
)
} else {
EasyPermissions.requestPermissions(
this,
"'어야가자' 이용을 위해 위치 권한을 '허용'으로 선택해주세요.",
Constants.REQUEST_CODE_LOCATION_PERMISSION,
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_BACKGROUND_LOCATION
)
}
}
override fun onPermissionsGranted(requestCode: Int, perms: MutableList<String>) {
TODO("Not yet implemented")
}
override fun onPermissionsDenied(requestCode: Int, perms: MutableList<String>) {
if (EasyPermissions.somePermissionPermanentlyDenied(this, perms)) {
AppSettingsDialog.Builder(this).build().show()
} else {
requestPermissions()
}
}
}
이 앱에서는 UI 업데이트를 위한 데이터를 관찰하여 위치를 표시할거에요.
companion object {
//...
val trackingLocation = MutableLiveData<LatLng>()
}
//...
val locationCallback = object : LocationCallback() {
override fun onLocationResult(locationResult: LocationResult) {
super.onLocationResult(locationResult)
if (isTracking.value!!) {
locationResult?.locations?.let {
for (location in it) {
var locationUpdate = LatLng(location.latitude!!, location.longitude!!)
trackingLocation.postValue(locationUpdate)
}
}
}
}
}
private fun subscribeToObservers() {
//...
TrackingService.trackingLocation.observe(viewLifecycleOwner, { trackingLocation ->
map?.animateCamera(CameraUpdateFactory.newLatLngZoom(trackingLocation, MAP_ZOOM))
})
}
마지막으로 알려진 위치 가져오기
위치 설정 변경
위치 업데이트 요청
Tracking User Location in the Background - MVVM Running Tracker App - Part 13