Android NsdManager无法发现服务

时间:2018-01-26 19:11:44

标签: android bonjour zeroconf network-service nsdmanager

在关注他们的教程NsdManager时,我遇到了Androids Using Network Service Discovery的问题。

我的网络上有一些zeroconf / bonjour硬件设备。从我的mac我可以通过我的终端发现所有这些,如下所示 dns-sd -Z _my-mesh._tcp.

从我的Android应用程序首次运行中,我可以使用NsdManager完美地发现这些服务。但是,如果我重新启动应用程序并再次尝试,则找不到任何服务。成功调用onDiscoveryStarted但之后没有其他任何内容。在等待的时候,我可以从我的mac确认服务仍然在那里成功。

然后我可以打开我的Zeroconf应用程序(在Android上),它会显示我的mac等服务。当我回到我的应用程序时,我看到它立即收到我之前预期的所有回调。所以我认为我的方法有问题,但我不确定是什么。下面是我用来发现和解决服务的代码。视图是一个巨大的文本视图(在滚动视图中)我一直在编写文本以便于调试。

import android.annotation.SuppressLint
import android.content.Context
import android.net.nsd.NsdManager
import android.net.nsd.NsdServiceInfo
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.widget.TextView

class MainActivity : AppCompatActivity(),
                     NsdManager.DiscoveryListener {

    private var nsdManager: NsdManager? = null
    private var text: TextView? = null
    private var isResolving = false
    private val services = ArrayList<ServiceWrapper>()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        this.text = findViewById(R.id.text)
        this.nsdManager = application.getSystemService(Context.NSD_SERVICE) as NsdManager

    }

    override fun onResume() {
        super.onResume()
        this.nsdManager?.discoverServices("_my-mesh._tcp.", NsdManager.PROTOCOL_DNS_SD, this)
        write("Resume Discovering Services")
    }

    override fun onPause() {
        super.onPause()
        this.nsdManager?.stopServiceDiscovery(this)
        write("Pause Discovering Services")
    }

    override fun onServiceFound(serviceInfo: NsdServiceInfo?) {
        write("onServiceFound(serviceInfo = $serviceInfo))")
        if (serviceInfo == null) {
            return
        }
        add(serviceInfo)
    }

    override fun onStopDiscoveryFailed(serviceType: String?, errorCode: Int) {
        write("onStopDiscoveryFailed(serviceType = $serviceType, errorCode = $errorCode)")
    }

    override fun onStartDiscoveryFailed(serviceType: String?, errorCode: Int) {
        write("onStartDiscoveryFailed(serviceType = $serviceType, errorCode = $errorCode)")
    }

    override fun onDiscoveryStarted(serviceType: String?) {
        write("onDiscoveryStarted(serviceType = $serviceType)")
    }

    override fun onDiscoveryStopped(serviceType: String?) {
        write("onDiscoveryStopped(serviceType = $serviceType)")
    }

    override fun onServiceLost(serviceInfo: NsdServiceInfo?) {
        write("onServiceLost(serviceInfo = $serviceInfo)")
    }

    private fun createResolveListener(): NsdManager.ResolveListener {
        return object : NsdManager.ResolveListener {
            override fun onResolveFailed(serviceInfo: NsdServiceInfo?, errorCode: Int) {
                write("onResolveFailed(serviceInfo = $serviceInfo, errorCode = $errorCode)")
                isResolving = false
                resolveNext()
            }

            override fun onServiceResolved(serviceInfo: NsdServiceInfo?) {
                write("onServiceResolved(serviceInfo = $serviceInfo)")
                if (serviceInfo == null) {
                    return
                }
                for (servicewrapper in services) {
                    if (servicewrapper.serviceInfo.serviceName == serviceInfo.serviceName) {
                        servicewrapper.resolve(serviceInfo)
                    }
                }
                isResolving = false
                resolveNext()
            }
        }
    }

    @SuppressLint("SetTextI18n")
    private fun write(text: String?) {
        this.text?.let {
            it.post({
                        it.text = it.text.toString() + "\n" + text + "\n"
                    })
        }
    }

    fun add(serviceInfo: NsdServiceInfo) {
        for (servicewrapper in services) {
            if (servicewrapper.serviceInfo.serviceName == serviceInfo.serviceName) {
                return
            }
        }
        services.add(ServiceWrapper(serviceInfo))
        resolveNext()
    }

    @Synchronized
    fun resolveNext() {
        if (isResolving) {
            return
        }
        isResolving = true
        for (servicewrapper in services) {
            if (servicewrapper.isResolved) {
                continue
            }
            write("resolving")
            this.nsdManager?.resolveService(servicewrapper.serviceInfo, createResolveListener())
            return
        }
        isResolving = false

    }

    inner class ServiceWrapper(var serviceInfo: NsdServiceInfo) {

        var isResolved = false

        fun resolve(serviceInfo: NsdServiceInfo) {
            isResolved = true
            this.serviceInfo = serviceInfo


        }

    }


}

0 个答案:

没有答案