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()
            }
        }
    }
相关推荐
fengci.13 小时前
Microweber CMS 未授权路径穿越漏洞(CVE-2026-65694)
android·开发语言·前端·学习·php
stevenzqzq14 小时前
Android 矢量图(Vector Drawable)核心坐标与尺寸机制技术文档
android
plainGeekDev15 小时前
运行时获取依赖 → 编译时注入
android·java·kotlin
Wiktok15 小时前
Vue3(Vite)打包安卓APP 完整最佳实践
android·vue
略略略咯咯15 小时前
LocalDateTime
android
Co_Hui15 小时前
Android 系统服务的添加
android
蜡台16 小时前
Flutter Container 与装饰完整讲解
android·javascript·flutter·dart
杉氧17 小时前
用 Compose 挑战交互与动效天花板:ComposeCraftLab 开源实验室全解析
android·前端·kotlin
朝与同歌暮同酒17 小时前
冒泡社区《幻想三国》还能玩吗?安卓手机与电脑模拟器试玩记录
android·智能手机·电脑
音视频牛哥18 小时前
从数字孪生到机器人操控:Android Unity3D下RTMP/RTSP多路低延迟播放实践
android·unity·音视频·unity rtsp播放器·unity rtmp播放器·rtsp player·rtmp player