Wifi P2P服务发现间歇性地工作

时间:2014-10-10 13:41:35

标签: android wifi-direct service-discovery wifip2p dns-sd

Wifi P2P服务发现的行为不符合预期。我看到间歇性的问题,DNSSD侦听器不会一直被调用,因此我不知道运行相同应用程序的附近设备。我使用以下两个API - 一个用于注册要由其他设备发现的服务,另一个用于发现在其他设备上运行的附近服务。任何想法,如果我在这里做错了或者是否有一些特定的其他Android API调用序列需要在我调用这些API之前进行,以确保在注册新服务时甚至是服务时始终调用侦听器在我们调用API以发现本地服务之前注册。

注册本地服务的API:

private void registerService() {
    Map<String, String> values = new HashMap<String, String>();
    values.put("name", "Steve");
    values.put("port", "8080");
    WifiP2pServiceInfo srvcInfo = WifiP2pDnsSdServiceInfo.newInstance(mMyDevice.deviceName, "_http._tcp", values);

    manager.addLocalService(channel, srvcInfo, new WifiP2pManager.ActionListener() {

        @Override
        public void onSuccess() {
            Toast.makeText(WiFiDirectActivity.this, "Local service added successfully", 
                Toast.LENGTH_SHORT).show();
        }

        @Override
        public void onFailure(int reasonCode) {
            Toast.makeText(WiFiDirectActivity.this, "Local service addition failed : " + reasonCode,
                    Toast.LENGTH_SHORT).show();
        }
    });
}

发现本地服务的API:

public void discoverService() {

    manager.clearServiceRequests(channel, null);

    DnsSdTxtRecordListener txtListener = new DnsSdTxtRecordListener() {
        @Override
        /* Callback includes:
         * fullDomain: full domain name: e.g "printer._ipp._tcp.local."
         * record: TXT record data as a map of key/value pairs.
         * device: The device running the advertised service.
         */
        public void onDnsSdTxtRecordAvailable(String fullDomain, Map record, WifiP2pDevice device) {
            Log.d(TAG, "DnsSdTxtRecord available -" + record.toString());
        }
    };

    DnsSdServiceResponseListener servListener = new DnsSdServiceResponseListener() {
        @Override
        public void onDnsSdServiceAvailable(String instanceName, String registrationType, WifiP2pDevice resourceType) {
            Log.d(TAG, "onBonjourServiceAvailable " + instanceName);
        }
    };

    manager.setDnsSdResponseListeners(channel, servListener, txtListener);

    WifiP2pDnsSdServiceRequest serviceRequest = WifiP2pDnsSdServiceRequest.newInstance();
    manager.addServiceRequest(channel, serviceRequest, new ActionListener() {

        @Override
        public void onSuccess() {
            // Success!
            Log.d(TAG, "addServiceRequest success");
        }

        @Override
        public void onFailure(int code) {
            // Command failed.  Check for P2P_UNSUPPORTED, ERROR, or BUSY
            Log.d(TAG, "addServiceRequest failure with code " + code);
        }

    });
    manager.discoverServices(channel, new ActionListener() {

        @Override
        public void onSuccess() {
            // Success!
            Log.d(TAG, "discoverServices success");
        }

        @Override
        public void onFailure(int code) {
            // Command failed.  Check for P2P_UNSUPPORTED, ERROR, or BUSY
            if (code == WifiP2pManager.P2P_UNSUPPORTED) {
                Log.d(TAG, "P2P isn't supported on this device.");
            } else {
                Log.d(TAG, "discoverServices failure");
            }
        }
    });
}

注意:经理&amp;通道初始化为

WifiP2pManager manager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);
Channel channel = manager.initialize(this, getMainLooper(), null);

2 个答案:

答案 0 :(得分:28)

WifiP2p(一般情况下):

前段时间我正在开发一个基于WifiP2pService Broadcasting/Discovery的非常复杂的网络连接系统的应用程序。根据这些经验,我已经在这里写了几篇关于有多难,穿着和有问题的帖子。以下是其中两个(他们充分了解了我对WifiP2p Service Discovery以及WifiP2p本身所获得的内部知识:

Why is discovering peers for Android WifiDirect so unreliable

Wi-fi P2P. Inform all peers available of some event

我建议你阅读我的两个答案(即使他们更关注WifiP2p本身)。在使用WifiP2p Service Discovery时,他们应该就您应该寻找的事情提供一些观点。 我可以很容易地说,如果你想建立一个高效,相对可靠和强大的WifiP2p连接系统(特别是Service Discovery),你将不得不解决问题。

WifiP2p Service Discovery

为了更好地回答您的确切问题,我会告诉您我做了什么(与您不同),以使Service Discovery工作非常可靠。

<强> 1。广播Service

首先:在注册Service(使用addLocalService方法)之前,您应该使用WifiP2pManager的{​​{1}}方法。重要的是,如果听众传递了clearLocalServices并返回了addLocalService回调,那么您应该 调用clearLocalServices

虽然这很好地设置了广播,但我发现其他节点并不总是能够检测到广播的onSuccess(特别是当这些节点在注册本地时尚未主动检测服务时{ {1}} - 但他们之后“加入”了。我无法找到一种方法来100%可靠地解决这个问题。相信我,我可能正在尝试所有与service相关的事情。不,Service - WifiP2p序列并没有给出令人满意的结果。或者更重要的是:做一些与众不同的工作要好得多。我决定做的是,在成功添加本地服务(clearLocalServices来回addLocalService)后,我开始onSuccess定期调用{{1}方法addLocalService。这似乎迫使重播所有Thread信息。

所以...基本上你的广播代码的基础看起来应该更像这样(请记住,如果网络连接系统是,我将在这里发布的每一段代码都被剥离掉所有“检查”在正确的状态下,您应该自己设计它们以最好地适应您的解决方案:

WifiP2pManager

discoverPeers应该是:

service

<强> 2。发现public void startBroadcastingService(){ mWifiP2pManager.clearLocalServices(mWifiP2pChannel, new WifiP2pManager.ActionListener() { @Override public void onSuccess() { mWifiP2pManager.addLocalService(mWifiP2pChannel, mWifiP2pServiceInfo, new WifiP2pManager.ActionListener() { @Override public void onSuccess() { // service broadcasting started mServiceBroadcastingHandler .postDelayed(mServiceBroadcastingRunnable, SERVICE_BROADCASTING_INTERVAL); } @Override public void onFailure(int error) { // react to failure of adding the local service } }); } @Override public void onFailure(int error) { // react to failure of clearing the local services } }); }

为了发现你mServiceBroadcastingRunnable我使用了类似的方法。两者都设置了发现,并试图强制“重新发现”private Runnable mServiceBroadcastingRunnable = new Runnable() { @Override public void run() { mWifiP2pManager.discoverPeers(mWifiP2pChannel, new WifiP2pManager.ActionListener() { @Override public void onSuccess() { } @Override public void onFailure(int error) { } }); mServiceBroadcastingHandler .postDelayed(mServiceBroadcastingRunnable, SERVICE_BROADCASTING_INTERVAL); } };

使用以下三种Service方法的序列进行设置:

serviceservicesWifiP2pManager

它们按照这个确切的顺序被调用,并且只有在前一个方法使用removeServiceRequest回调“返回”之后才调用特定方法(第二个或第三个确切)。

使用直观方法重新发现addServiceRequest(只需重复上述序列:discoverServices - &gt; onSuccess - &gt; services)。< / p>

我的代码基础看起来更像是这样(要开始removeServiceRequest我先打电话给addServiceRequest然后再打discoverServices):

Service Discovery

prepareServiceDiscovery()

startServiceDiscovery()只是:

public void prepareServiceDiscovery() {
    mWifiP2pManager.setDnsSdResponseListeners(mWifiP2pChannel,
            new WifiP2pManager.DnsSdServiceResponseListener() {

                @Override
                public void onDnsSdServiceAvailable(String instanceName,
                                                    String registrationType, WifiP2pDevice srcDevice) {
                    // do all the things you need to do with detected service
                }
            }, new WifiP2pManager.DnsSdTxtRecordListener() {

                @Override
                public void onDnsSdTxtRecordAvailable(
                        String fullDomainName, Map<String, String> record,
                        WifiP2pDevice device) {
                    // do all the things you need to do with detailed information about detected service
                }
            });

    mWifiP2pServiceRequest = WifiP2pDnsSdServiceRequest.newInstance();
}

这一切使我的系统运作良好。它还不完美,但由于缺乏关于这个主题的文档,我认为我无法做更多的改进。

如果你测试这种方法,请务必告诉我它是如何工作的(或如果它适合你;)。)。

答案 1 :(得分:0)

如果问题是检测到服务,我认为提示组是使设备和服务可检测的最佳方式,但是如果在所有设备中创建了组,则无法直接连接。 但作为wifi网络。 我每天都这样做而且有效。