Created
December 6, 2017 15:49
-
-
Save Jthomas54/c1bdd68653a1832024c7cd4f784baf02 to your computer and use it in GitHub Desktop.
Getting location updates with Android using the FusedLocationProviderClient
This file contains 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.content.Context | |
import android.location.Location | |
import com.google.android.gms.location.* | |
/** | |
* A default implementation using the fused location provider to supply the application with locations | |
*<p> | |
* You should ensure you have the correct permissions in the manifest, that the permissions have | |
* been granted, and location services are enabled. | |
*/ | |
@SuppressWarnings("MissingPermission") | |
class FusedLocationProvider(ctx: Context) : LocationProvider { | |
companion object { | |
//How fast can your application process location updates requested by other applications | |
private val DEFAULT_FASTEST_INTERVAL: Long = 1000 // 1 Second | |
//Interval to ask for location updates until one has been determined | |
private val DEFAULT_SHORT_INTERVAL: Long = 500 // 1/2 Second | |
//Interval that is used AFTER a non-null location is received | |
private val DEFAULT_LONG_INTERVAL: Long = 20 * 60 * 1000 //20 Minutes | |
//The accuracy of the location updates | |
private val LOCATION_PRIORITY = LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY | |
private fun isSameLatLong(l1: Location, l2: Location): Boolean = (l1.latitude == l2.latitude && l1.longitude == l2.longitude) | |
} | |
private val client = LocationServices.getFusedLocationProviderClient(ctx) | |
private val locationCallbackHelper = LocationCallbackHelper() | |
private var lastKnownLocation: Location? = null | |
private var listener: LocationProvider.Listener? = null | |
private var locationRequest = LocationRequest.create() | |
override fun getCurrentLocation(): Location? = lastKnownLocation | |
override fun setListener(listener: LocationProvider.Listener?) { | |
this.listener = listener | |
} | |
override fun startUpdates() { | |
stopUpdates() | |
client.lastLocation | |
.addOnSuccessListener { location -> handleLocationUpdate(location) } | |
.addOnCompleteListener { | |
val interval = if (lastKnownLocation == null) DEFAULT_SHORT_INTERVAL else DEFAULT_LONG_INTERVAL | |
requestLocationUpdates(interval, LOCATION_PRIORITY) | |
} | |
} | |
override fun stopUpdates() { | |
client.removeLocationUpdates(locationCallbackHelper) | |
reset() | |
} | |
//Permissions and location services should be enabled by this point, make sure you do it!! | |
private fun requestLocationUpdates(interval: Long, priority: Int) { | |
locationRequest.setFastestInterval(DEFAULT_FASTEST_INTERVAL) | |
.setInterval(interval) | |
.setPriority(priority) | |
client.requestLocationUpdates(locationRequest, locationCallbackHelper, null) | |
} | |
private fun handleLocationUpdate(location: Location?) { | |
val lastLocation = lastKnownLocation | |
lastKnownLocation = location | |
//Update to a longer interval, also will trigger a location update using the last one | |
if (location != null) { | |
if (lastLocation == null || !isSameLatLong(lastLocation, location)) listener?.onNewLocationUpdate(location) | |
if (locationRequest.interval == DEFAULT_SHORT_INTERVAL) { | |
requestLocationUpdates(DEFAULT_LONG_INTERVAL, LOCATION_PRIORITY) | |
return | |
} | |
} | |
listener?.onLocationUpdate(location) | |
} | |
private fun reset() { | |
lastKnownLocation = null | |
} | |
private inner class LocationCallbackHelper : LocationCallback() { | |
override fun onLocationResult(lr: LocationResult) { | |
handleLocationUpdate(lr.lastLocation) | |
} | |
override fun onLocationAvailability(la: LocationAvailability) { | |
if (lastKnownLocation == null && la.isLocationAvailable) { | |
client.lastLocation.addOnSuccessListener { location -> | |
handleLocationUpdate(location) | |
} | |
} | |
} | |
} | |
} |
This file contains 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.location.Location | |
/** | |
* Interface that is used for abstracting location updates from location providers. | |
* <p> | |
* A device should be checked to ensure it has location services enabled before getting a location. | |
*/ | |
interface LocationProvider { | |
/** | |
* Subscribe to notifications for location updates | |
* @param listener | |
*/ | |
fun setListener(listener: Listener?) | |
/** | |
* Gets the current location known to the [LocationProvider] | |
*/ | |
fun getCurrentLocation(): Location? | |
/** | |
* Starts the location provider's services | |
*/ | |
fun startUpdates() | |
/** | |
* Stops the location provider's services | |
*/ | |
fun stopUpdates() | |
/** | |
* Listener to receive updates from a [LocationProvider] | |
*/ | |
interface Listener { | |
/** | |
* Triggered when a new location is received | |
*/ | |
fun onNewLocationUpdate(location: Location) | |
/** | |
* Triggered when any location update is received | |
*/ | |
fun onLocationUpdate(location: Location?) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment