Skip to content

Instantly share code, notes, and snippets.

@roscrazy
Created February 8, 2020 08:04
Show Gist options
  • Save roscrazy/cbff8abe07d83ad2488045957bd7ae3c to your computer and use it in GitHub Desktop.
Save roscrazy/cbff8abe07d83ad2488045957bd7ae3c to your computer and use it in GitHub Desktop.
AndroidLocationService
internal class AndroidLocationService(private val locationManager: LocationManager) :
LocationService {
override fun requestLocationUpdates(attributes: RxLocationAttributes): Observable<Location> {
return Observable.create<Location> { emitter ->
log { "AndroidLocationService ObservableOnSubscribe create" }
val locationListener = RxLocationListener(emitter)
emitter.setCancellable {
log { "AndroidLocationService ObservableOnSubscribe canceled" }
locationManager.removeUpdates(locationListener)
}
try {
val providers = locationManager.allProviders
when (attributes.priority) {
Priority.BalancePower -> {
fetchLastKnowLocation(
arrayOf(LocationManager.NETWORK_PROVIDER, LocationManager.PASSIVE_PROVIDER), emitter
)
requestLocationUpdates(LocationManager.NETWORK_PROVIDER, providers, locationListener, attributes)
requestLocationUpdates(LocationManager.PASSIVE_PROVIDER, providers, locationListener, attributes)
}
Priority.HighAccuracy -> {
fetchLastKnowLocation(arrayOf(LocationManager.GPS_PROVIDER), emitter)
requestLocationUpdates(LocationManager.GPS_PROVIDER, providers, locationListener, attributes)
}
Priority.LowPower -> {
fetchLastKnowLocation(arrayOf(LocationManager.NETWORK_PROVIDER), emitter)
requestLocationUpdates(LocationManager.NETWORK_PROVIDER, providers, locationListener, attributes)
}
Priority.NoPower -> {
fetchLastKnowLocation(arrayOf(LocationManager.PASSIVE_PROVIDER), emitter)
requestLocationUpdates(LocationManager.PASSIVE_PROVIDER, providers, locationListener, attributes)
}
}
log { "AndroidLocationService ObservableOnSubscribe finish created" }
} catch (e: Exception) {
if (!emitter.tryOnError(e)) {
log { e.toString() }
}
}
}
.retry { n: Int, e: Throwable ->
(n < attributes.retryAttempt && e !is SecurityException)
}
}
private fun fetchLastKnowLocation(providers: Array<String>, emitter: ObservableEmitter<Location>) {
providers.forEach {
locationManager.getLastKnownLocation(it)?.let {
if (!emitter.isDisposed) {
emitter.onNext(it)
}
return
}
}
}
@Throws(IllegalStateException::class)
private fun requestLocationUpdates(
provider: String,
providers: MutableList<String>,
locationListener: RxLocationListener, attributes: RxLocationAttributes
) {
if (providers.contains(provider)) {
locationManager.requestLocationUpdates(
provider,
attributes.updateInterval,
attributes.smallestDisplacement,
locationListener,
if (attributes.useCalledThreadToEmitValue) null else Looper.getMainLooper()
)
}
}
inner class RxLocationListener(private val emitter: ObservableEmitter<Location>) :
LocationListener {
override fun onLocationChanged(location: Location?) {
if (!emitter.isDisposed && location != null)
emitter.onNext(location)
}
override fun onStatusChanged(s: String, i: Int, bundle: Bundle) {}
override fun onProviderEnabled(s: String) {}
override fun onProviderDisabled(s: String) {}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment