Skip to content

Instantly share code, notes, and snippets.

@chrisk8er
Forked from Razeeman/LocationManagerImpl.kt
Created September 23, 2022 08:33
Show Gist options
  • Save chrisk8er/7616326ef211a1e8d0727e5b5876c028 to your computer and use it in GitHub Desktop.
Save chrisk8er/7616326ef211a1e8d0727e5b5876c028 to your computer and use it in GitHub Desktop.
Android Get User Location Manager
class LocationManagerImpl @Inject constructor(
private val permissionManager: PermissionManager,
private val context: Context
) : LocationManager {
override fun getUserLocationUpdates(): Observable<UserLocation> =
if (checkIfGooglePlayAvailable()) getLocationFromGooglePlay() else getLocationFromAndroidSdk()
override fun getDefaultLocation(): UserLocation = UserLocation(DEFAULT_LATITUDE, DEFAULT_LONGITUDE)
@SuppressLint("MissingPermission")
private fun getLocationFromAndroidSdk(): Observable<UserLocation> {
return Observable
.create { emitter ->
val locationManager =
context.getSystemService(Context.LOCATION_SERVICE) as android.location.LocationManager
val listener = object : LocationListener {
override fun onStatusChanged(p0: String?, p1: Int, p2: Bundle?) {}
override fun onProviderEnabled(p0: String?) {}
override fun onProviderDisabled(p0: String?) {}
override fun onLocationChanged(location: Location) {
emitter.processLocation(location)
}
}
emitter.setDisposable(Disposables.fromAction {
locationManager.removeUpdates(listener)
})
if (permissionManager.isLocationsGranted()) {
if (locationManager.isProviderEnabled(GPS_PROVIDER) ||
locationManager.isProviderEnabled(NETWORK_PROVIDER)
) {
locationManager.requestLocationUpdates(
GPS_PROVIDER,
LOCATION_UPDATE_TIME,
0f,
listener
)
locationManager.requestLocationUpdates(
NETWORK_PROVIDER,
LOCATION_UPDATE_TIME,
0f,
listener
)
val location = locationManager.getLastKnownLocation(GPS_PROVIDER)
?: locationManager.getLastKnownLocation(NETWORK_PROVIDER)
emitter.processLocation(location)
} else {
emitter.processError(LocationProviderMissingException)
}
} else {
emitter.processError(LocationPermissionDeniedException)
}
}
}
private fun getLocationFromGooglePlay(): Observable<UserLocation> {
return Observable.create { emitter ->
val fusedLocationClient = LocationServices.getFusedLocationProviderClient(context)
fusedLocationClient.flushLocations()
val locationCallback = object : LocationCallback() {
override fun onLocationResult(locationResult: LocationResult?) {
locationResult?.locations?.forEach {
emitter.processLocation(it)
}
}
}
fusedLocationClient.requestLocationUpdates(
LocationRequest().setInterval(LOCATION_UPDATE_TIME),
locationCallback,
Looper.getMainLooper()
)
emitter.setDisposable(Disposables.fromAction {
fusedLocationClient.removeLocationUpdates(locationCallback)
})
if (permissionManager.isLocationsGranted()) {
fusedLocationClient.lastLocation
.addOnSuccessListener { location ->
emitter.processLocation(location)
}
.addOnFailureListener { exception ->
Timber.d(exception)
emitter.processError(LocationProviderMissingException)
}
} else {
emitter.processError(LocationPermissionDeniedException)
}
}
}
private fun checkIfGooglePlayAvailable(): Boolean =
GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(context) == SUCCESS
private fun ObservableEmitter<UserLocation>.processLocation(location: Location?) {
if (isDisposed) return
location?.let { onNext(UserLocation(it.latitude, it.longitude)) }
?: onNext(getDefaultLocation())
}
private fun ObservableEmitter<UserLocation>.processError(exception: RuntimeException) {
if (!isDisposed) onError(exception)
}
private companion object {
const val LOCATION_UPDATE_TIME = 2000L // in milliseconds
// Default location - Moscow
const val DEFAULT_LATITUDE = 55.751385
const val DEFAULT_LONGITUDE = 37.615558
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment