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

Sou*_*Das 30 android service-discovery dns-sd wifi-direct wifip2p

无线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();
        }
    });
}
Run Code Online (Sandbox Code Playgroud)

用于发现本地服务的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");
            }
        }
    });
}
Run Code Online (Sandbox Code Playgroud)

注意:经理和渠道初始化为

WifiP2pManager manager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);
Channel channel = manager.initialize(this, getMainLooper(), null);
Run Code Online (Sandbox Code Playgroud)

Bar*_*ski 30

WifiP2p (一般来说):

前一段时间我正在开发基于一个非常复杂的网络连接系统的应用WifiP2pService Broadcasting/Discovery.根据这些经验,我已经在这里写了几篇关于有多难,穿着和有问题的帖子.这里有两个人(他们是相当充分的,我又得到关于里面的学问WifiP2pService DiscoveryWifiP2p本身):

为什么发现Android WifiDirect的同行如此不可靠

Wi-Fi P2P.通知所有可用的同事

我会建议你阅读我的两个答案(即使他们更多地关注WifiP2p自己).他们应该给你一些关于你在使用时应该寻找的东西的一些观点WifiP2p Service Discovery.我可以很容易地说,如果你想建立一个高效,相对可靠和强大的WifiP2p连接系统(尤其是Service Discovery),你将不得不解决问题.

WifiP2p Service Discovery:

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

1.广播Service:

首先:注册您之前Service(含addLocalService方法),你应该使用WifiP2pManagerclearLocalServices方法.重要的是,只有addLocalService在侦听器传入clearLocalServices带有onSuccess回调的返回时,应该调用.

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

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

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
        }
    });
}
Run Code Online (Sandbox Code Playgroud)

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);
    }
};
Run Code Online (Sandbox Code Playgroud)

2.发现Service:

为了发现你service我用过类似的方法.两者都设置了发现,并试图强制"重新发现" services.

使用以下三种WifiP2pManager方法的顺序进行设置:

removeServiceRequest,addServiceRequest,discoverServices

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

重新发现services是用直观的方法进行的(只需重复上述序列: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();
}
Run Code Online (Sandbox Code Playgroud)

private void startServiceDiscovery() {
    mWifiP2pManager.removeServiceRequest(mWifiP2pChannel, mWifiP2pServiceRequest,
            new WifiP2pManager.ActionListener() {
                @Override
                public void onSuccess() {
                    mWifiP2pManager.addServiceRequest(mWifiP2pChannel, mWifiP2pServiceRequest,
                            new WifiP2pManager.ActionListener() {

                                @Override
                                public void onSuccess() {
                                    mWifiP2pManager.discoverServices(mWifiP2pChannel,
                                            new WifiP2pManager.ActionListener() {

                                                @Override
                                                public void onSuccess() {
                                                    //service discovery started

                                                    mServiceDiscoveringHandler.postDelayed(
                                                            mServiceDiscoveringRunnable,
                                                            SERVICE_DISCOVERING_INTERVAL);
                                                }

                                                @Override
                                                public void onFailure(int error) {
                                                    // react to failure of starting service discovery
                                                }
                                            });
                                }

                                @Override
                                public void onFailure(int error) {
                                    // react to failure of adding service request
                                }
                            });
                }

                @Override
                public void onFailure(int reason) {
                    // react to failure of removing service request
                }
            });
}
Run Code Online (Sandbox Code Playgroud)

mServiceDiscoveringRunnable只是:

private Runnable mServiceDiscoveringRunnable = new Runnable() {
    @Override
    public void run() {
        startServiceDiscovery();
    }
};
Run Code Online (Sandbox Code Playgroud)

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

如果测试这种方法时,一定要告诉我它是如何工作的,你(或者,如果你的作品;)).