It seems that you are trying to get the last location from the Android location service. This is one of many Task
-returning calls in the Google Play Services. Kotlin already has a module, kotlinx-coroutines-play-services
, that contributes a function
suspend fun <T> Task<T>.await(): T?
With that in your project, you can simply write this:
suspend fun getMyLocation(): Location? =
LocationServices.getFusedLocationProvider(context)
.lastLocation
.await()
If you want to integrate it with other Flow
-based code, add this wrapper function:
fun <T> Task<T>.asFlow() = flow { emit(await()) }
and now you can write
fun getLocationAsFlow(): Flow<Location?> =
LocationServices.getFusedLocationProvider(context)
.lastLocation
.asFlow()
If, for educational purposes, you would like to see how it can be implemented directly, without the additional module, then the most straightforward approach would be as follows:
fun getLocationAsFlow() = flow {
val location = suspendCancellableCoroutine<Location?> { cont ->
LocationServices.getFusedLocationProvider(context)
.lastLocation
.addOnCompleteListener {
val e = exception
when {
e != null -> cont.resumeWithException(e)
isCanceled -> cont.cancel()
else -> cont.resume(result)
}
}
}
emit(location)
}
This is the result of inlining a simplified implementation of Task.await()
into its use site.