18

我正在尝试在我公司的专有硬件设备上执行服务发现,该设备托管自己的 WiFi 网络并通过该网络宣传 bonjour 服务。当我连接到那个 WiFi 网络时,我正在使用 NSD 来发现该服务并解决它。

代码非常简单,通常运行良好且快速。除了我有一个相当反复出现的问题(大约 10 次尝试中的 5 次)到目前为止本地化到我的三星 S8+。目前无法在 S6 或 Pixel XL 上重现。

问题是 DiscoveryListener 除了 onDiscoveryStarted() 之外从不做任何事情,它只是永远运行。如果我杀死该应用程序并重新开始,有时它会工作,有时它会继续挂起。

就像有一个阻塞的线程或其他东西,但日志中没有有用的信息(我可以找到),而且我还没有找到任何东西可以锁定,因为我可以做些什么来从中恢复。

我添加了一个超时,它将在 30 秒后停止侦听器,但通常当我在那之后重试时它仍然不起作用。

服务发现过程包含在一个 LiveData 中,它在活动时启动它。

    const val SERVICE_TYPE_FOO = "_foo._tcp."

    private val serviceDiscoveryListener = ServiceDiscoveryListener()

    override fun onActive() {
        super.onActive()
        stopRunnable = StopDiscoveryRunnable()
        nsdManager.discoverServices(
            SERVICE_TYPE_FOO,
            NsdManager.PROTOCOL_DNS_SD,
            serviceDiscoveryListener
        )
        handler.postDelayed(stopRunnable, SERVICE_DISCOVERY_TIMEOUT_MS)
    }

private lateinit var stopRunnable: Runnable

private inner class StopDiscoveryRunnable : Runnable {
    override fun run() {
        try {
            nsdManager.stopServiceDiscovery(serviceDiscoveryListener)
            Timber.w("service discovery timed out")
            postValue(ServiceDiscoveryState.Error)
        } catch (e: Throwable) {
            // no-op
        }
    }
}

听众很简单...

private inner class ServiceDiscoveryListener : NsdManager.DiscoveryListener {
    override fun onServiceFound(serviceInfo: NsdServiceInfo?) {
        if (serviceInfo != null) {
            if (serviceInfo.serviceName.isNotEmpty() &&
                serviceInfo.serviceName.containsFoo()
            ) {
                nsdManager.resolveService(serviceInfo, ResolveListener())
                handler.removeCallbacks(stopRunnable)
            }
        }
    }

    override fun onStopDiscoveryFailed(serviceType: String?, errorCode: Int) {
        Timber.d("stop discovery failed")
        nsdManager.stopServiceDiscovery(this)
        postValue(ServiceDiscoveryState.Error)
    }

    override fun onStartDiscoveryFailed(serviceType: String?, errorCode: Int) {
        Timber.d("start discovery failed")
        nsdManager.stopServiceDiscovery(this)
        postValue(ServiceDiscoveryState.Error)
    }

    override fun onDiscoveryStarted(serviceType: String?) {
        Timber.d("discovery started")
    }

    override fun onDiscoveryStopped(serviceType: String?) {
        Timber.d("discovery stopped")
    }

    override fun onServiceLost(serviceInfo: NsdServiceInfo?) {
        Timber.d("discovery service lost")
        postValue(ServiceDiscoveryState.Error)
    }
}

private inner class ResolveListener : NsdManager.ResolveListener {
    override fun onResolveFailed(serviceInfo: NsdServiceInfo?, errorCode: Int) {
        Timber.d("resolve failed. errorCode = $errorCode")
        if (errorCode != NsdManager.FAILURE_ALREADY_ACTIVE) {
            Timber.d("not already active, so error")
            postValue(ServiceDiscoveryState.Error)
        } else {
            Timber.d("already active")
        }
    }

    override fun onServiceResolved(serviceInfo: NsdServiceInfo?) {
        if (serviceInfo != null) {
            Timber.d("resolved service: ${serviceInfo.serviceName} host: ${serviceInfo.host}:${serviceInfo.port} type: ${serviceInfo.serviceType}")
            postValue(ServiceDiscoveryState.FooService(serviceInfo))
        }
    }
}

我无法在日志中找到太多有价值的东西,尽管当事情不工作时我确实看到了这条消息。试图寻找有关这个问题的答案的尝试并没有取得成果。

04-26 13:50:14.541 953-1218/? W//system/bin/netd:使用无效的 DNSServiceRef 0x72bb818000 FFFFFFFF DDDDDDDD 调用 dnssd_clientstub DNSServiceProcessResult

我还能提供哪些其他信息?

我已经在我的 S8+ 上使用 Andriy Druk 的 bonjour服务浏览器示例代码重现了这个问题,它甚至不使用 NSD ......所以看起来问题可能出在核心 mDNS 代码中,而不是特定于 Google 的 NSD 实现?

S8+ 上是否有一些系统软件或膨胀软件可能会干扰我对 NSD 或 mDNS 的使用 - 线程阻塞或其他什么?

4

0 回答 0