Skip to content

Instantly share code, notes, and snippets.

@Abdullamhd
Last active June 5, 2018 10:05
Show Gist options
  • Select an option

  • Save Abdullamhd/e0eedb0a0ef84e94c01c4f37dc811654 to your computer and use it in GitHub Desktop.

Select an option

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
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