Skip to content

Instantly share code, notes, and snippets.

@roscrazy
Last active February 8, 2020 04:26
Show Gist options
  • Save roscrazy/ff84c24ff470dbb8d938be8a29c926d3 to your computer and use it in GitHub Desktop.
Save roscrazy/ff84c24ff470dbb8d938be8a29c926d3 to your computer and use it in GitHub Desktop.
FusedLocationService
internal class FusedLocationService(
private val fusedLocationProviderClient: FusedLocationProviderClient
) : LocationService {
override fun requestLocationUpdates(attributes: RxLocationAttributes): Observable<Location> {
return getLocationObservable(attributes)
.retry { n: Int, e: Throwable ->
(n < attributes.retryAttempt
&& e !is GooglePlayServicesNotAvailableException
&& e !is SecurityException)
}
}
@SuppressLint("MissingPermission")
private fun getLocationObservable(attributes: RxLocationAttributes): Observable<Location> {
return Observable.create { emitter ->
log { "FusedLocationService ObservableOnSubscribe create" }
val listener = getLocationListener(emitter)
val completeListener = getOnCompleteListener(emitter)
try {
fusedLocationProviderClient.lastLocation.addOnSuccessListener {
if (!emitter.isDisposed && it != null) emitter.onNext(it)
}
val task = fusedLocationProviderClient.requestLocationUpdates(
getLocationRequest(attributes),
listener,
if (attributes.useCalledThreadToEmitValue) null else Looper.getMainLooper()
)
task.addOnCompleteListener(completeListener)
} catch (e: Exception) {
emitter.tryOnError(e)
}
emitter.setCancellable(getCancellable(listener))
}
}
private fun getCancellable(locationListener: LocationCallback): Cancellable {
return Cancellable {
log { "FusedLocationService Observable has canceled" }
fusedLocationProviderClient.removeLocationUpdates(locationListener)
}
}
private fun getLocationListener(emitter: ObservableEmitter<Location>): LocationCallback {
return object : LocationCallback() {
override fun onLocationResult(locationResult: LocationResult?) {
if (!emitter.isDisposed && locationResult != null && locationResult.lastLocation != null) {
emitter.onNext(locationResult.lastLocation)
} else {
log { "Got location but emitter already disposed" }
}
}
}
}
private fun getOnCompleteListener(emitter: ObservableEmitter<Location>): OnCompleteListener<Void> {
return OnCompleteListener { task ->
if (!task.isSuccessful) {
emitter.tryOnError(
task.exception
?: IllegalStateException("Can't get location from FusedLocationProviderClient")
)
}
}
}
private fun getLocationRequest(attributes: RxLocationAttributes): LocationRequest {
return LocationRequest
.create()
.setPriority(attributes.priority.toFusedPriority())
.setFastestInterval(attributes.fastestInterval)
.setInterval(attributes.updateInterval)
.setSmallestDisplacement(attributes.smallestDisplacement)
}
}
fun Priority.toFusedPriority(): Int {
return when (this) {
Priority.NoPower -> LocationRequest.PRIORITY_NO_POWER
Priority.LowPower -> LocationRequest.PRIORITY_LOW_POWER
Priority.HighAccuracy -> LocationRequest.PRIORITY_HIGH_ACCURACY
Priority.BalancePower -> LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment