Paulius Ruminas
10/30/2019, 8:14 AM_location
channel was closed and we are not sure how can this happen since _location
is a private member and there is no call to _location.close()
. What are we missing?
Dagger
@Provides
@Singleton
fun gpsLocationService(): GpsLocationService = GpsLocationService(
context = context,
coroutineContext = Dispatchers.Default
)
Service
class GpsLocationService(
private val context: Context,
override val coroutineContext: CoroutineContext
) : CoroutineScope {
private val logger = Logger.get(this::class)
private val _location = BroadcastChannel<Location>(1)
private val interval: Millis = GpsUpdateInterval.High.interval
private val fusedLocationClient = LocationServices.getFusedLocationProviderClient(context)
private val locationCallback: LocationCallback = object : LocationCallback() {
override fun onLocationResult(locationResult: LocationResult) {
if (GpsHelper.isGpsEnabled(context)) {
logger.trace("Location acquired (${locationResult.lastLocation}).")
_location.sendBlocking(locationResult.lastLocation)
} else {
logger.trace("GPS is disabled, ignoring location change.")
}
}
}
suspend fun requestLocation(): Location? = _location.openSubscription().consume {
val location = withTimeoutOrNull(15.seconds) { receiveOrNull() }
location
}
}
bohsen
10/31/2019, 7:28 AM_location.openSubscription().consume {}
will invoke cancel()
after consuming. You should use consumeEach
instead.bohsen
10/31/2019, 7:28 AMbohsen
10/31/2019, 7:31 AMrequestLocation()
to return Flow<Location>
bohsen
10/31/2019, 7:32 AMBroadcastChannel
has an asFlow
extension AFAIKPaulius Ruminas
10/31/2019, 7:42 AM@Test
fun test() {
val a = BroadcastChannel<Unit>(1)
runBlocking {
a.openSubscription().consume {
}
}
kotlin.test.assertEquals(a.isClosedForSend, false)
}
bohsen
10/31/2019, 7:53 AMBroadcastChannel
?Paulius Ruminas
10/31/2019, 7:58 AMfun requestUpdates(): ReceiveChannel<Location> = _location.openSubscription()
I have this method in the class as well just did not copy it into the example.Paulius Ruminas
10/31/2019, 8:00 AM.close()
that a broadcast channel could be closed? I can not figure that out from the stack trace since there is no information about who closed the channel.
Fatal Exception: kotlinx.coroutines.channels.ClosedSendChannelException: Channel was closed
at kotlinx.coroutines.channels.Closed.getSendException(AbstractChannel.kt:1048)
at kotlinx.coroutines.channels.AbstractSendChannel.offer(AbstractChannel.kt:166)
at kotlinx.coroutines.channels.AbstractSendChannel.send(AbstractChannel.kt:146)
at kotlinx.coroutines.channels.BroadcastCoroutine.send$suspendImpl(Broadcast.kt)
at kotlinx.coroutines.channels.BroadcastCoroutine.send(Broadcast.kt)
at kotlinx.coroutines.channels.BroadcastKt$broadcast$1.invokeSuspend(Broadcast.kt:30)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.ResumeModeKt.resumeMode(ResumeMode.kt:67)
at kotlinx.coroutines.DispatchedKt.resume(Dispatched.kt:319)
at kotlinx.coroutines.DispatchedKt.resumeUnconfined(Dispatched.kt:49)
at kotlinx.coroutines.DispatchedKt.dispatch(Dispatched.kt:298)
at kotlinx.coroutines.CancellableContinuationImpl.dispatchResume(CancellableContinuationImpl.kt:250)
at kotlinx.coroutines.CancellableContinuationImpl.completeResume(CancellableContinuationImpl.kt:327)
at kotlinx.coroutines.channels.AbstractChannel$ReceiveHasNext.completeResumeReceive(AbstractChannel.kt:907)
at kotlinx.coroutines.channels.ArrayBroadcastChannel$Subscriber.checkOffer(ArrayBroadcastChannel.kt:256)
at kotlinx.coroutines.channels.ArrayBroadcastChannel.checkSubOffers(ArrayBroadcastChannel.kt:127)
at kotlinx.coroutines.channels.ArrayBroadcastChannel.offerInternal(ArrayBroadcastChannel.kt:96)
at kotlinx.coroutines.channels.AbstractSendChannel.offer(AbstractChannel.kt:160)
at kotlinx.coroutines.channels.AbstractSendChannel.send(AbstractChannel.kt:146)
at com.eld.android.gps.GpsLocationService$locationCallback$1$onLocationResult$1.invokeSuspend(GpsLocationService.kt:34)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(Dispatched.kt:241)
at kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.common.kt:270)
at kotlinx.coroutines.BlockingCoroutine.joinBlocking(Builders.kt:79)
at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking(Builders.kt:54)
at kotlinx.coroutines.BuildersKt.runBlocking(:1)
at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking$default(Builders.kt:36)
at kotlinx.coroutines.BuildersKt.runBlocking$default(:1)
at com.eld.android.gps.GpsLocationService$locationCallback$1.onLocationResult(GpsLocationService.kt:34)
at com.google.android.gms.internal.location.zzau.notifyListener()
at com.google.android.gms.common.api.internal.ListenerHolder.notifyListenerInternal(:17)
at com.google.android.gms.common.api.internal.ListenerHolder$zaa.handleMessage(:5)
at android.os.Handler.dispatchMessage(Handler.java:111)
at com.google.android.gms.internal.base.zap.dispatchMessage(:8)
at android.os.Looper.loop(Looper.java:207)
at android.os.HandlerThread.run(HandlerThread.java:61)
bohsen
10/31/2019, 9:38 AMconsume
. Just sayin'.
Check docs on consume
and cancel
. You probably call requestLocation()
somewhere before you invoke your locationCallback
.Paulius Ruminas
10/31/2019, 10:29 AM