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()
            }
        }
    }
相关推荐
芦半山2 小时前
四年之后,重新审视 MTE:从硬件架构到工程落地
android·安全
2501_916007472 小时前
iOS与Android符号还原服务统一重构实践总结
android·ios·小程序·重构·uni-app·iphone·webview
allk552 小时前
Android 屏幕适配全维深度解析
android·性能优化·界面适配
Android系统攻城狮3 小时前
Android ALSA驱动进阶之获取采样格式位宽snd_pcm_format_width:用法实例(九十八)
android·pcm·音频进阶·alsa驱动
莫比乌斯环3 小时前
【日常随笔】Android 跳离行为分析 - Instrumentation
android·架构·代码规范
aningxiaoxixi3 小时前
android 媒体之 MediaSession
android·媒体
GoldenPlayer3 小时前
Android文件权限报错
android
Jomurphys3 小时前
Compose 适配 - 全屏显示 EdgeToEdge
android
ii_best3 小时前
「安卓开发辅助工具按键精灵」xml全分辨率插件jsd插件脚本教程
android·xml·开发语言·编辑器·安卓