android/app/src/main/java/com/srtk/airlink/NetworkDiscovery.kt
2025-11-21 21:37:05 +05:30

125 lines
No EOL
4.3 KiB
Kotlin

package com.srtk.airlink
import android.content.Context
import android.net.nsd.NsdManager
import android.net.nsd.NsdServiceInfo
import android.util.Log
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.callbackFlow
import java.net.InetAddress
data class ServerInfo(
val name: String,
val ip: InetAddress,
val port: Int
) {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is ServerInfo) return false
return ip == other.ip && port == other.port
}
override fun hashCode(): Int {
return 31 * ip.hashCode() + port
}
}
class DiscoveryManager(context: Context) {
private val TAG = "DiscoveryManager"
private val nsdManager = context.getSystemService(
Context.NSD_SERVICE
) as NsdManager
private val SERVICE_TYPE = "_procam._udp."
fun discover(): Flow<ServerInfo> = callbackFlow {
val discoveryListener = object : NsdManager.DiscoveryListener {
override fun onDiscoveryStarted(regType: String) {
Log.d(TAG, "Discovery started")
}
override fun onServiceFound(service: NsdServiceInfo) {
if (service.serviceType.contains("_procam")) {
try {
nsdManager.resolveService(
service,
object : NsdManager.ResolveListener {
override fun onResolveFailed(
serviceInfo: NsdServiceInfo,
errorCode: Int
) {
Log.w(TAG, "Resolve failed: $errorCode")
}
override fun onServiceResolved(
serviceInfo: NsdServiceInfo
) {
try {
val server = ServerInfo(
name = serviceInfo.serviceName,
ip = serviceInfo.host,
port = serviceInfo.port
)
trySend(server)
} catch (e: Exception) {
Log.e(
TAG,
"Error creating ServerInfo: ${e.message}"
)
}
}
}
)
} catch (e: Exception) {
Log.e(TAG, "Resolve error: ${e.message}")
}
}
}
override fun onServiceLost(service: NsdServiceInfo) {
Log.d(TAG, "Service lost: ${service.serviceName}")
}
override fun onDiscoveryStopped(serviceType: String) {
Log.d(TAG, "Discovery stopped")
}
override fun onStartDiscoveryFailed(
serviceType: String,
errorCode: Int
) {
Log.e(TAG, "Start discovery failed: $errorCode")
try {
nsdManager.stopServiceDiscovery(this)
} catch (e: Exception) {
Log.e(TAG, "Stop discovery error: ${e.message}")
}
}
override fun onStopDiscoveryFailed(
serviceType: String,
errorCode: Int
) {
Log.e(TAG, "Stop discovery failed: $errorCode")
}
}
try {
nsdManager.discoverServices(
SERVICE_TYPE,
NsdManager.PROTOCOL_DNS_SD,
discoveryListener
)
} catch (e: Exception) {
Log.e(TAG, "Discovery start error: ${e.message}")
}
awaitClose {
try {
nsdManager.stopServiceDiscovery(discoveryListener)
} catch (e: Exception) {
Log.e(TAG, "Discovery cleanup error: ${e.message}")
}
}
}
}