Last active
February 8, 2020 04:26
-
-
Save roscrazy/ff84c24ff470dbb8d938be8a29c926d3 to your computer and use it in GitHub Desktop.
FusedLocationService
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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