refactor: simplify NsdManager service handling

This commit is contained in:
andrekir 2024-01-28 07:24:26 -03:00
parent 8709c6ba53
commit 91943860e9
2 changed files with 19 additions and 28 deletions

View file

@ -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<NsdManager?>,
private val connectivityManager: dagger.Lazy<ConnectivityManager>,
) : Logging {
val networkAvailable get() = connectivityManager.get().networkAvailable()
private val _resolvedList = MutableStateFlow<List<NsdServiceInfo>>(emptyList())
val resolvedList: StateFlow<List<NsdServiceInfo>> 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"

View file

@ -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<List<NsdServiceInfo>> = 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<List<NsdServiceInfo>> = 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 {