监听器已在使用中(服务发现)

18

如果错误的意思是我不能在解决一个服务的同时解决另一个服务,那该怎么办呢?有什么方法可以等待到它被解决吗?

@Override
public void onServiceFound(NsdServiceInfo service) {
    Log.d(TAG, "Service found. " + service);
    if (service.getServiceType().equals(SERVICE_TYPE)) {
        if (service.getServiceName().contains(mServiceName)) {
            mNsdManager.resolveService(service, mResolveListener);
        }
    }
}
java.lang.IllegalArgumentException: listener already in use at android.net.nsd.NsdManager.resolveService(NsdManager.java:613) at com.example.miguel.broadcast.LocalService$2.onServiceFound(LocalService.java:145)

也许你的问题与这个已报告的错误有关?https://code.google.com/p/android/issues/detail?id=56830 - Okas
@Okas 我正在使用Android L,我从未遇到过这个错误。 - Kenny
你有找到解决方法吗?我在我的棒棒糖设备上也遇到了这个错误,但在其他设备上没有。 - Da-Jin
@tastypython 有点像...我用了一个变通方法。错误总是在使用其中一个条件时触发(我希望我能在这里提供更多帮助),尝试删除或更改其中一个条件,它最终会起作用。我有一段时间前删除了我的项目,很抱歉!阅读谷歌的示例代码,它会帮助很多。 - Kenny
谢谢您的回复,即使谷歌的示例应用程序也出现了问题,我已经转向使用jmdns。我认为谷歌的nsd API开发不够完善。 - Da-Jin
3个回答

27

你不必等待!如果查看这里 的javadocs,你会注意到对于参数listener,它说“用于接收成功或失败的回调。不能为null。在活动服务解析中不能使用。”

因此,为了使其工作,只需执行以下操作:

mNsdManager.resolveService(service, new MyResolveListener());

MyResolveListener 是:

private class MyResolveListener implements NsdManager.ResolveListener {
        @Override
        public void onResolveFailed(NsdServiceInfo serviceInfo, int errorCode) {
            //your code
        }

        @Override
        public void onServiceResolved(NsdServiceInfo serviceInfo) {
            //your code
        }
    }

希望这能有所帮助 :)


嘿,谢谢回答。我甚至不记得我是如何解决这个问题的,但现在它对互联网很有用了!;) - Kenny

15

我也曾遇到这个问题,并且一直在遵循NsdChat中阐述的Android NsdHelper实现方法,链接在这里。这个例子展示了在NsdHelper类中创建单个NsdManager.ResolveListener mResolveListener,并将该ResolveListener用于所有对NsdManager.resolveService的调用。

这里我读到,"每个活动注册或发现请求都应使用单独的监听器"。

因此,不要使用类变量mResolveListener,而是在每次调用mNsdManager.resolveService时创建一个新的监听器:

@Override
public void onServiceFound(NsdServiceInfo serviceInfo) {
    Log.d(TAG, "Service found: "+ serviceInfo);
    if (serviceInfo.getServiceType().equals(SERVICE_TYPE)){
        mNsdManager.resolveService(serviceInfo, new NsdManager.ResolveListener() {
            @Override
            public void onResolveFailed(NsdServiceInfo serviceInfo, int errorCode) {
                Log.e(TAG, "Resolve Failed: " + serviceInfo);
            }
            @Override
            public void onServiceResolved(NsdServiceInfo serviceInfo) {
                Log.i(TAG, "Service Resolved: " + serviceInfo);
            }
        });
    }
}

7

您需要确保不传递已经注册过的监听器对象。您可以在此处查看导致此行为更改的提交here

以下是提交消息文本:

文档并强制执行“每个侦听器一个请求”的规则
NsdManager的API和实现意味着每个活动注册或发现请求都需要使用单独的侦听器。这没有正式记录或正确执行,如果应用程序同时为多个请求使用一个Listener,则会发生奇怪且不可预测的事情。
更新文档以使其成为明确要求。
在提交新请求进行处理时强制执行限制; 如果Listener已被用于跟踪活动请求,则抛出异常。
记录应用程序在停止时应注销服务并取消服务发现(在KitKat及以前的版本中,如果未执行此操作,它们将泄漏)。
重新排序“释放侦听器”操作,使其在Listener回调之前发生,以便一旦进入回调,应用程序就可以重用Listener-这可以消除竞争条件。记录这一点。
第2步:拼写错误、添加有关API级别的文档,并更改为使用明确定义的“忙侦听器”的返回值。

另外,请注意,如果您从Android开发者网站下载了NsdChat示例项目(即NsdChat.zip或类似文件),那么该项目的代码可能已经过时。

请尝试使用主分支上的最新代码...您可以从此处复制并粘贴到您的示例项目中。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接