android NDSDManager onResolveFailed errorCode=3的解决方案

stack overflow有介绍,这个原因可能是系统同时发现了多个

kotlin 复制代码
discoveryListener = object : NsdManager.DiscoveryListener {
	     override fun onServiceFound(service: NsdServiceInfo) {
	         onServiceFoundInfo(service) //解析info
	     }
	 	....
	 }

fun onServiceFoundInfo() {
//开始解析
	nsdManager.resolveService(next, object : NsdManager.ResolveListener {
      override fun onResolveFailed(serviceInfo: NsdServiceInfo, errorCode: Int) {
             loge(TAG) { "Failed to resolve service: ${serviceInfo.serviceName}, error: $errorCode" }
         }
       override fun onServiceResolved(serviceInfo: NsdServiceInfo) {
             //解析成功
        
         })
}

如果你这里直接开始解析,在某些手机上,可能就报错了。告诉你,解析出错,errorCode=3。

因为可能同时有多个onServiceFound过来,同时,resolveService就会出错。

解决办法:串行执行。

这里采用kotlin的suspendCancellableCoroutine + LinkedBlockingQueue解决。

kotlin 复制代码
 private val mResolveQueue = LinkedBlockingQueue<NsdServiceInfo>()
 private val mIsResolving = AtomicBoolean(false)

discoveryListener = object : NsdManager.DiscoveryListener {
      override fun onServiceFound(service: NsdServiceInfo) {
             onServiceFoundInfo(service)
         }
		....
     }

private fun onServiceFoundInfo(service: NsdServiceInfo) {
        mResolveQueue.offer(service) //内部有锁的
        processResolveQueue()
    }

    private fun processResolveQueue() {
        if (!mIsResolving.compareAndSet(false, true)) return
        scope.launch { //子线程
            while (true) {
                val next = mResolveQueue.poll() ?: break
                val resolved = suspendCancellableCoroutine { cont ->
                    try {
                        nsdManager.resolveService(next, object : NsdManager.ResolveListener {
                            override fun onResolveFailed(serviceInfo: NsdServiceInfo, errorCode: Int) {
                                loge(TAG) { "Failed to resolve service: ${serviceInfo.serviceName}, error: $errorCode" }
                                if (cont.isActive) cont.resume(null)
                            }
                            override fun onServiceResolved(serviceInfo: NsdServiceInfo) {
                                if (cont.isActive) cont.resume(serviceInfo)
                            }
                        })
                    } catch (e: Exception) {
                        loge(TAG, e) { "Failed to resolve service: ${next.serviceName}, error: ${e.message}" }
                        if (cont.isActive) (
                            //if(!e.message.isNullOrEmpty()) cont.resumeWithException(e) else cont.resume(null)
                            cont.resume(null) //不做异常抛出
                        )
                    }
                }
                if (resolved != null) {
                    handleResolvedService(resolved) //todo 自己的逻辑
                }
            }
            mIsResolving.set(false)
            if (mResolveQueue.isNotEmpty()) {
                processResolveQueue()
            }
        }
    }
相关推荐
曲幽3 小时前
Termux里的二进制和脚本,到底怎么运行才不踩坑?Termux-service 保活妙招!
android·termux·nohup·services·wake-lock
plainGeekDev4 小时前
单例模式 → object 声明
android·java·kotlin
程序员陆业聪4 小时前
读者点单·03|Compose 与传统 View 混用的 12 个真实坑
android
程序员陆业聪4 小时前
读者点单·02|Android 启动优化实战:Trace 抓取→Application 编排→冷启动全流程拆解
android
Coffeeee4 小时前
帮你快速理解AI Agent之我想招个Android实习生
android·人工智能·agent
恋猫de小郭6 小时前
苹果 AirPods 协议,Android 也可以使用完整版 AirPods 能力
android·前端·flutter
黄林晴6 小时前
告别无效重建:Gradle 9.6.0 解决 CI 构建缓存失效痛点告别无效重建:Gradle 9.6.0 解决 CI 建筑缓存失效痛点
android·gradle
张风捷特烈6 小时前
Flutter 类库大揭秘#01 | path_provider架构与设计
android·flutter
_阿南_15 小时前
Android文件读写和分享总结
android
通玄1 天前
Jetpack Compose 入门系列(六):Navigation 3 页面导航
android