Why is discovering peers for Android Wi-Fi Direct so unreliable?

倖福魔咒の 提交于 2019-11-30 02:30:35

I've been recently developing an application with a connection system based on WiFi Direct (with WiFi P2P Service Discovery) and the one thing I can most certainly say is that the whole thing is a huge pain in the ... . Mostly because of the lack of documentation but also because when developing a wifi-direct-based solution you need to pay attention to basically everything (especially to all callbacks from listeners) before making any method call.

Two most annoying things were I guess:

I was able to "solve" the problems of some phones not appearing by requesting peer discovery every 10 seconds. I think I was running into this because one phone was always the host and I didn't bother to have it discover peers (because it doesn't try to join them), and the Wifi Direct was going to sleep on the host phone. I don't do anything with the peer results, but it wakes up the Wifi Direct system. There's probably a better method to call but I'm not sure what it is. If I had to guess I'd say I'm wasting some battery life.

From my experience it's reliable. After tons of trying, I got the robust workable flow like this:

...
wifiP2pManager.clearLocalServices(wifiP2pChannel, new WifiP2pManager.ActionListener() {
            @Override
            public void onSuccess() {
                HashMap<String, String> record = new HashMap<>();
                record.put("name", "Amos");
                WifiP2pDnsSdServiceInfo serviceInfo = WifiP2pDnsSdServiceInfo.newInstance(AppConfig.DNS_SD_SERVICE_NAME, AppConfig.DNS_SD_SERVICE_TYPE, record);
                wifiP2pManager.addLocalService(wifiP2pChannel, serviceInfo, new WifiP2pManager.ActionListener() {
                    @Override
                    public void onSuccess() {
                        wifiP2pManager.setDnsSdResponseListeners(wifiP2pChannel, WifiDirectFragment.this, WifiDirectFragment.this);
                        wifiP2pManager.clearServiceRequests(wifiP2pChannel, new WifiP2pManager.ActionListener() {
                            @Override
                            public void onSuccess() {
                                wifiP2pManager.addServiceRequest(wifiP2pChannel, WifiP2pDnsSdServiceRequest.newInstance(), new WifiP2pManager.ActionListener() {
                                    @Override
                                    public void onSuccess() {
                                        wifiP2pManager.discoverPeers(wifiP2pChannel, new WifiP2pManager.ActionListener() {
                                            @Override
                                            public void onSuccess() {
                                                wifiP2pManager.discoverServices(wifiP2pChannel, new WifiP2pManager.ActionListener() {
                                                    @Override
                                                    public void onSuccess() {
                                                        // this is my recursive discovery approach                                                            
                                                        handler.postDelayed(discoveryRunnable, AppConfig.DNS_SD_SERVICE_DISCOVERABLE_DURATION_S * 1000);
                                                    }

                                                    @Override
                                                    public void onFailure(int code) {
                                                    }
                                                });
                                            }

                                            @Override
                                            public void onFailure(int code) {
                                            }
                                        });
                                    }

                                    @Override
                                    public void onFailure(int code) {
                                    }
                                });
                            }

                            @Override
                            public void onFailure(int code) {
                            }
                        });
                    }

                    @Override
                    public void onFailure(int code) {
                    }
                });
            }

            @Override
            public void onFailure(int code) {
            }
        });

I had a really big problem with establishing connection between devices:

  • first device turns on peer discovery
  • second device turns on peer discovery
  • one device tries to establish connection with the second one
  • sometimes it works, sometimes not (I would say 50/50)

I guess the issue was the group owner negotiation (I've tried change groupOwnerIntent param also to force who should be group owner, but it didn't helped).

So, what did I do?

I change flow to:

  • one device creates group (mManager.createGroup(...)), so this device is always a group owner
  • second devices connects with group owner
  • whooala, now is very rare to stuck on invited state.
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!