Android NSD - 永久挂起/运行 - 特定于设备?

Ken*_*man 15 android mdns bonjour dns-sd nsd

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

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

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

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

我添加了一个超时,它将在30秒后停止监听器,但通常在我重试之后它仍然无效.

服务发现过程包含在LiveData中,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
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

听众很简单......

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))
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我无法在日志中找到很多有价值的东西,尽管当事情不起作用时我确实看到了这条消息.试图寻找有关这方面的答案并没有取得多少成果.

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

我可以提供哪些其他信息?

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

S8 +上是否有一些系统软件或英国媒体报道可能会干扰我使用NSD或mDNS - 线程阻塞或其他什么?