Souhail Marghabi
11/10/2020, 4:12 PMnrobi
11/10/2020, 4:43 PMrequestLocationUpdates
nrobi
11/10/2020, 4:51 PMlastLocation
will return only the cached location, probably at the point of your request it's null
, you could also check out currentLocation
, which will trigger a location calculation, so probably is heaviernrobi
11/10/2020, 4:53 PMlastLocation ?: currentLocation ?: requestLocationUpdates
logic would make sense in your caseSouhail Marghabi
11/10/2020, 4:53 PMnrobi
11/10/2020, 4:54 PMSouhail Marghabi
11/10/2020, 4:55 PMnrobi
11/10/2020, 4:58 PMSouhail Marghabi
11/10/2020, 5:05 PMSouhail Marghabi
11/10/2020, 5:05 PMnrobi
11/10/2020, 5:16 PMSouhail Marghabi
11/10/2020, 5:19 PM/**
*
* @property locationProviderClient Android Native location tracking service
* @property appContext Global Application Context
* @constructor
*/
class LocationServiceProviderImpl (
private val locationProviderClient: FusedLocationProviderClient,
context: Context) : LocationServiceProvider {
private val appContext = context.applicationContext
private val TAG = this::class.java.name
/**
*
* @param lastFetchedLocation Coordinate
* @return Boolean
*/
override suspend fun hasLocationChanged(lastFetchedLocation: Coordinate): Boolean {
return try {
hasDeviceLocationChanged(lastFetchedLocation)
}
catch (e: LocationTrackingDenied){
Log.d(TAG, appContext.getString(R.string.location_provider_error))
false
}
}
/**
*
* @return Coordinate
*/
override suspend fun getCurrentLocation() : Coordinate? {
try {
val test = getLastKnownLocation()
val deviceLocation= getLastDeviceLocation().await()
return Coordinate(deviceLocation.latitude,deviceLocation.longitude)
}catch (e: LocationTrackingDenied){
//Temporary
Log.e(TAG, appContext.getString(R.string.location_provider_error))
}
catch (e: NullPointerException){
//Temporary
Log.e(TAG, appContext.getString(R.string.location_device_error))
return null
}
return null
}
@SuppressLint("MissingPermission")
override suspend fun getLastKnownLocation(): Location = suspendCoroutine { coroutine ->
LocationServices.getFusedLocationProviderClient(appContext).lastLocation
.addOnSuccessListener { location -> coroutine.resume(location) }
.addOnCanceledListener { Log.e(TAG,"Last Known location: on canceled listener") }
.addOnFailureListener { Log.e(TAG,"Last Known location: on failure listener") }
}
/**
* Decide if Device location has changed by a defined threshold range
* @param lastLocation Coordinate
* @return Boolean
*/
private suspend fun hasDeviceLocationChanged(lastLocation: Coordinate) : Boolean{
val deviceLocation = getLastDeviceLocation().await()
val comparisonThreshold = 0.05
return abs(deviceLocation.latitude - lastLocation.latitude) > comparisonThreshold &&
abs(deviceLocation.longitude - lastLocation.longitude) > comparisonThreshold
}
/**
* Retrieves last fetched location asynchronously
* @precondition Location Permission granted
* @return Deferred<Location>
*/
@SuppressLint("MissingPermission")
private fun getLastDeviceLocation(): Deferred<Location> {
return if (hasGPSPermission()) locationProviderClient.lastLocation.executeAsync()
else throw LocationTrackingDenied()
}
/**
* Check if App has Geolocation Permission
* @return Boolean
*/
private fun hasGPSPermission() : Boolean{
return PreferencesHelper.hasPermission(Manifest.permission.ACCESS_FINE_LOCATION)
}
}
Souhail Marghabi
11/10/2020, 5:20 PMnrobi
11/10/2020, 5:28 PMgetLastKnownLocation
I'd do the following, if the lastLocation is null I'd call requestLocationUpdates
and I'd resume the continuation after the first result (Also you should dispose the listener after the first result)Souhail Marghabi
11/10/2020, 5:29 PM@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
@SuppressLint("MissingPermission")
fun startLocationUpdate() = fusedLocationProviderClient.requestLocationUpdates(
locationRequest,
locationCallback,
Looper.getMainLooper()
)
this is what I call every time from a lifecycle aware service binded to the UISouhail Marghabi
11/10/2020, 5:35 PMJan
11/11/2020, 11:12 AM