diff --git a/app/src/main/java/com/geeksville/mesh/repository/network/NetworkRepository.kt b/app/src/main/java/com/geeksville/mesh/repository/network/NetworkRepository.kt index e495e6e81..e4fc30496 100644 --- a/app/src/main/java/com/geeksville/mesh/repository/network/NetworkRepository.kt +++ b/app/src/main/java/com/geeksville/mesh/repository/network/NetworkRepository.kt @@ -2,44 +2,21 @@ package com.geeksville.mesh.repository.network import android.net.ConnectivityManager import android.net.nsd.NsdManager -import android.net.nsd.NsdServiceInfo -import androidx.lifecycle.Lifecycle -import androidx.lifecycle.coroutineScope import com.geeksville.mesh.android.Logging -import com.geeksville.mesh.CoroutineDispatchers -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.collectLatest -import kotlinx.coroutines.flow.update -import kotlinx.coroutines.launch +import kotlinx.coroutines.flow.flowOf import javax.inject.Inject import javax.inject.Singleton @Singleton class NetworkRepository @Inject constructor( - dispatchers: CoroutineDispatchers, - processLifecycle: Lifecycle, private val nsdManagerLazy: dagger.Lazy, private val connectivityManager: dagger.Lazy, ) : Logging { val networkAvailable get() = connectivityManager.get().networkAvailable() - private val _resolvedList = MutableStateFlow>(emptyList()) - val resolvedList: StateFlow> get() = _resolvedList - - init { - processLifecycle.coroutineScope.launch(dispatchers.default) { - val manager = nsdManagerLazy.get() ?: return@launch - manager.discoverServices(SERVICE_TYPE).collectLatest { serviceList -> - _resolvedList.update { - serviceList - .filter { it.serviceName.contains(SERVICE_NAME) } - .mapNotNull { manager.resolveService(it) } - } - } - } - } + val resolvedList + get() = nsdManagerLazy.get()?.serviceList(SERVICE_TYPE, SERVICE_NAME) ?: flowOf(emptyList()) companion object { // To find all available services use SERVICE_TYPE = "_services._dns-sd._udp" diff --git a/app/src/main/java/com/geeksville/mesh/repository/network/NsdManager.kt b/app/src/main/java/com/geeksville/mesh/repository/network/NsdManager.kt index 6e68a0cb7..15c970a76 100644 --- a/app/src/main/java/com/geeksville/mesh/repository/network/NsdManager.kt +++ b/app/src/main/java/com/geeksville/mesh/repository/network/NsdManager.kt @@ -2,14 +2,26 @@ package com.geeksville.mesh.repository.network import android.net.nsd.NsdManager import android.net.nsd.NsdServiceInfo +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.cancel import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.callbackFlow +import kotlinx.coroutines.flow.mapLatest import kotlinx.coroutines.suspendCancellableCoroutine import kotlin.coroutines.resume -internal fun NsdManager.discoverServices( +@OptIn(ExperimentalCoroutinesApi::class) +internal fun NsdManager.serviceList( + serviceType: String, + serviceName: String, +): Flow> = discoverServices(serviceType).mapLatest { serviceList -> + serviceList + .filter { it.serviceName.contains(serviceName) } + .mapNotNull { resolveService(it) } +} + +private fun NsdManager.discoverServices( serviceType: String, protocolType: Int = NsdManager.PROTOCOL_DNS_SD, ): Flow> = callbackFlow { @@ -40,11 +52,13 @@ internal fun NsdManager.discoverServices( trySend(serviceList) } } + trySend(emptyList()) // Emit an initial empty list discoverServices(serviceType, protocolType, discoveryListener) + awaitClose { stopServiceDiscovery(discoveryListener) } } -internal suspend fun NsdManager.resolveService( +private suspend fun NsdManager.resolveService( serviceInfo: NsdServiceInfo, ): NsdServiceInfo? = suspendCancellableCoroutine { continuation -> val listener = object : NsdManager.ResolveListener {