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 分钟前
皮皮宋渗透日记 11|文件包含漏洞全解析:LFI/RFI/ 伪协议 / 绕过 / 防御
android·安全
阿拉斯攀登8 分钟前
【无人售货柜・RK+YOLO】篇 6:安卓端落地!RK3576 + 安卓系统,YOLO RKNN 模型实时推理保姆级教程
android·人工智能·yolo·目标跟踪·瑞芯微·嵌入式驱动
只能是遇见33 分钟前
ERROR 1524 (HY000) Plugin ‘mysql_native_password‘ is not loaded
android·数据库·mysql
helloworddm1 小时前
第一篇:设计模式在 Android 视频播放器中的实战应用
android·设计模式·音视频
恋猫de小郭1 小时前
Android 禁止侧载将正式实施,需要等待 24 小时冷静期
android·flutter·harmonyos
idealzouhu1 小时前
【Kotlin】 数据流完全指南:冷流、热流与 Android 实战
android·开发语言·kotlin
有位神秘人1 小时前
Android中Mvvm+Retrofit的常用网络架构记录
android·网络·retrofit
常利兵1 小时前
Android 字体字重设置:从XML到Kotlin的奇妙之旅
android·xml·kotlin
hnlgzb2 小时前
kotlin安卓app中,当一个类继承ViewModel类的时候,这个类是想干什么?
android·开发语言·kotlin
zh_xuan2 小时前
Android compose测试数据双向绑定
android·compose