Last active
June 5, 2018 10:05
-
-
Save Abdullamhd/e0eedb0a0ef84e94c01c4f37dc811654 to your computer and use it in GitHub Desktop.
kotlin extension function to request location updates from activity with automatic lifecycle management with lifecycle observer , you don't have to unregister the listener
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
| import android.Manifest.permission.ACCESS_COARSE_LOCATION | |
| import android.Manifest.permission.ACCESS_FINE_LOCATION | |
| import android.annotation.SuppressLint | |
| import android.arch.lifecycle.Lifecycle | |
| import android.arch.lifecycle.LifecycleObserver | |
| import android.arch.lifecycle.OnLifecycleEvent | |
| import android.content.Context | |
| import android.location.Criteria | |
| import android.location.Location | |
| import android.location.LocationListener | |
| import android.location.LocationManager | |
| import android.os.Bundle | |
| import android.support.v7.app.AppCompatActivity | |
| fun AppCompatActivity.requestLocationUpdates(criteria: Criteria = createDefaultCirtirea(), isSingleUpdate : Boolean = true, block : (Location) -> Unit){ | |
| val locationManager = createLocationManager(this) | |
| val locationListener = configureListener(block) | |
| lifecycle.addObserver(handleLocationUpdates(locationManager,locationListener,criteria,isSingleUpdate)) | |
| } | |
| private fun configureListener(block: (Location) -> Unit) = Listener(block) | |
| private fun createDefaultCirtirea() = Criteria().apply { | |
| accuracy = Criteria.POWER_LOW | |
| powerRequirement = Criteria.POWER_MEDIUM | |
| } | |
| private fun handleLocationUpdates(manager: LocationManager, listener: LocationListener , criteria: Criteria , singleUpdate : Boolean) = ActivityLifecycleObserver(singleUpdate, manager, criteria, listener) | |
| private fun createLocationManager(context: Context) = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager | |
| private class Listener(private val block: (Location) -> Unit) : LocationListener { | |
| override fun onLocationChanged(location: Location) { | |
| block(location) | |
| } | |
| override fun onStatusChanged(provider: String?, status: Int, extras: Bundle?){} | |
| override fun onProviderEnabled(provider: String?){} | |
| override fun onProviderDisabled(provider: String?){} | |
| } | |
| private class ActivityLifecycleObserver(private val singleUpdate: Boolean, private val manager: LocationManager, private val criteria: Criteria, private val listener: LocationListener) : LifecycleObserver { | |
| @SuppressLint("MissingPermission") | |
| @OnLifecycleEvent(Lifecycle.Event.ON_RESUME) | |
| fun registerListener() = try { | |
| if (singleUpdate){ | |
| manager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER)?.let { | |
| listener.onLocationChanged(it) | |
| } | |
| } else { | |
| // according to the documentation we register the same listener with 2 provider if we need both provider | |
| manager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,0L,0F,listener) | |
| manager.requestLocationUpdates(LocationManager.GPS_PROVIDER,0L,0F,listener) | |
| } | |
| } catch (e : SecurityException){ | |
| //TODO there is a better way to handling this | |
| throw SecurityException("Permissions : ${ACCESS_FINE_LOCATION} and ${ACCESS_COARSE_LOCATION} are missing , did you requested runtime permission ?") | |
| } | |
| @SuppressLint("MissingPermission") | |
| @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE) | |
| fun unregisterListener() = manager.removeUpdates(listener) | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment