Skip to content

Instantly share code, notes, and snippets.

@lawloretienne
Created April 11, 2023 06:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lawloretienne/38ba2af36f224457e858564d63284f15 to your computer and use it in GitHub Desktop.
Save lawloretienne/38ba2af36f224457e858564d63284f15 to your computer and use it in GitHub Desktop.
import android.Manifest
import android.content.Context
import android.content.pm.PackageManager
import android.location.Location
import android.os.Looper
import androidx.core.app.ActivityCompat
import androidx.lifecycle.LiveData
import com.google.android.gms.common.api.ApiException
import com.google.android.gms.location.*
import com.google.android.gms.maps.model.LatLng
import timber.log.Timber
class LocationLiveData(var context: Context): LiveData<LocationState>() {
private val fusedLocationClient = LocationServices.getFusedLocationProviderClient(context)
private val settingsClient = LocationServices.getSettingsClient(context)
override fun onActive() {
super.onActive()
if (ActivityCompat.checkSelfPermission(
context,
Manifest.permission.ACCESS_COARSE_LOCATION
) != PackageManager.PERMISSION_GRANTED
) {
return
}
fusedLocationClient.lastLocation.addOnSuccessListener { location ->
location.also {
setLocationData(it)
}
}
requestLocationUpdates()
}
override fun onInactive() {
super.onInactive()
fusedLocationClient.removeLocationUpdates(locationCallback)
}
internal fun requestLocationUpdates() {
settingsClient.checkLocationSettings(locationSettingsRequest)
.addOnSuccessListener {
Timber.i("All location settings are satisfied. The client can initialize location requests here.")
startLocationUpdates()
}
.addOnFailureListener {
Timber.e("FAILURE!! - Location settings are NOT satisfied.")
value = LocationState(LatLng(0.0, 0.0), it as ApiException)
}
}
private fun setLocationData(location: Location?) {
location?.let {
value = LocationState(LatLng(it.latitude, it.longitude), null)
}
}
private fun startLocationUpdates() {
if (ActivityCompat.checkSelfPermission(
context,
Manifest.permission.ACCESS_COARSE_LOCATION
) != PackageManager.PERMISSION_GRANTED
) {
return
}
fusedLocationClient.requestLocationUpdates(locationRequest, locationCallback, Looper.getMainLooper())
}
private val locationCallback = object : LocationCallback() {
override fun onLocationResult(locationResult: LocationResult) {
super.onLocationResult(locationResult)
locationResult.locations.forEach {
setLocationData(it)
}
}
}
companion object {
private const val TWO_MINUTES = 2 * 60 * 1000
private const val THREE_MINUTES = 3 * 60 * 1000
private const val TEN_MINUTES = 10 * 60 * 1000
val locationRequest =
LocationRequest.Builder(
Priority.PRIORITY_BALANCED_POWER_ACCURACY,
THREE_MINUTES.toLong()
).setWaitForAccurateLocation(false)
.setMinUpdateIntervalMillis(TWO_MINUTES.toLong())
.setMaxUpdateDelayMillis(TEN_MINUTES.toLong())
.build()
val locationSettingsRequest = LocationSettingsRequest.Builder()
.addLocationRequest(locationRequest)
.build()
}
}
data class LocationState(
val coordinates: LatLng,
val exception: ApiException?
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment