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()
            }
        }
    }
相关推荐
黄林晴1 天前
Android 17 再曝猛料:通知栏和快捷设置终于分家了,这操作等了十年
android
有位神秘人1 天前
Android获取设备中本地音频
android·音视频
JMchen1231 天前
Android网络安全实战:从HTTPS到双向认证
android·经验分享·网络协议·安全·web安全·https·kotlin
CS创新实验室1 天前
Pandas 3 的新功能
android·ide·pandas
ujainu1 天前
护眼又美观:Flutter + OpenHarmony 鸿蒙记事本一键切换夜间模式(四)
android·flutter·harmonyos
三少爷的鞋1 天前
为什么我不在 Android ViewModel 中直接处理异常?
android
草莓熊Lotso1 天前
Linux 文件描述符与重定向实战:从原理到 minishell 实现
android·linux·运维·服务器·数据库·c++·人工智能
恋猫de小郭1 天前
Flutter Zero 是什么?它的出现有什么意义?为什么你需要了解下?
android·前端·flutter
工程师老罗1 天前
如何在Android工程中配置NDK版本
android
Libraeking1 天前
破壁行动:在旧项目中丝滑嵌入 Compose(混合开发实战)
android·经验分享·android jetpack