3

I'm developing an application, which uses wifi-direct to create groups of maximum 4 devices ( 1 host + 3 peers). I read manuals of wifi-direct from developer.android.com, found this wonderful answer: https://stackoverflow.com/a/31641302/3106249 - and still, I have couple of issues which I don't know how to handle.

First problem step by step:

  1. Registering local service and creating group on host device.

    Map<String, String> record = new HashMap<String, String>();
    record.put(TXTRECORD_PROP_AVAILABLE, "visible");
    record.put(Core.SESSION_KEY, Core.SESSION_KEY_VALUE);
    record.put(Core.SERVICE_INSTANCE_KEY, SERVICE_INSTANCE);
    localService = WifiP2pDnsSdServiceInfo.newInstance(SERVICE_INSTANCE, Core.SERVICE_REG_TYPE, record);
    
    manager.clearLocalServices(channel, new WifiP2pManager.ActionListener() {
        @Override
        public void onSuccess() {
            Log.d(TAG, "clearLocalServices success");
    
            manager.addLocalService(channel, localService, new WifiP2pManager.ActionListener() {
                @Override
                public void onSuccess() {
                    Log.d(TAG, "addLocalService success");
    
                    manager.createGroup(channel, new WifiP2pManager.ActionListener() {
                        @Override
                        public void onSuccess() {
                            Log.d(TAG, "createGroup success");
                        }
    
                        @Override
                        public void onFailure(int reason) {
                            Log.d(TAG, "createGroup fail: " + reason);
                        }
                    });
                }
    
                @Override
                public void onFailure(int reason) {
                    Log.d(TAG, "addLocalService fail: " + reason);
                }
            });
        }
    
        @Override
        public void onFailure(int reason) {
            Log.d(TAG, "clearLocalServices fail: " + reason);
        }
    });
    
  2. Discovering required peed by host device with 10 seconds interval.

    manager.removeServiceRequest(channel, serviceRequest, new WifiP2pManager.ActionListener() {
            @Override
            public void onSuccess() {
                Log.d(TAG, "discovering, removeServiceRequest success");
    
                manager.stopPeerDiscovery(channel, new WifiP2pManager.ActionListener() {
                    @Override
                    public void onSuccess() {
                        Log.d(TAG, "discovering, stopPeerDiscovery success");
    
                        manager.discoverPeers(channel, new WifiP2pManager.ActionListener() {
                            @Override
                            public void onSuccess() {
                                Log.d(TAG, "discovering, discoverPeers success");
    
                                manager.addServiceRequest(channel, serviceRequest, new WifiP2pManager.ActionListener() {
                                    @Override
                                    public void onSuccess() {
                                        Log.d(TAG, "discovering, addServiceRequest success");
    
                                        manager.discoverServices(channel, new WifiP2pManager.ActionListener() {
                                            @Override
                                            public void onSuccess() {
                                                //Log.d(TAG, "discoverServices success");
                                            }
    
                                            @Override
                                            public void onFailure(int reason) {
                                                Log.d(TAG, "discoverServices fail: " + reason);
                                            }
                                        });
                                    }
    
                                    @Override
                                    public void onFailure(int reason) {
                                        Log.d(TAG, "addServiceRequest fail: " + reason);
                                    }
                                });
                            }
    
                            @Override
                            public void onFailure(int reason) {
                                Log.d(TAG, "discoverPeers fail: " + reason);
                            }
                        });
                    }
    
                    @Override
                    public void onFailure(int reason) {
                        Log.d(TAG, "stopPeerDiscovery fail: " + reason);
                    }
                });
            }
    
            @Override
            public void onFailure(int reason) {
                Log.d(TAG, "clearServiceRequests fail: " + reason);
            }
        });
    
  3. Sending connection invite (by calling WiFiP2pManager#connect())

    WifiP2pConfig config = new WifiP2pConfig();
    config.deviceAddress = device.deviceAddress;
    config.wps.setup = WpsInfo.PBC;
    
    manager.connect(channel, config, new WifiP2pManager.ActionListener() {
        @Override
        public void onSuccess() {
            Log.d(TAG, "manger.onSuccess with " + device.deviceName);
        }
    
        @Override
        public void onFailure(int errorCode) {
            Log.d(TAG, "Failed connecting to service " + errorCode);
        }
    });
    

  4. Connection prompt dialog appears on peer. Accepting connection.
  5. Connection prompt dialog NEVER appears on host device.
Second problem is, that when I call WiFiP2pManager#connect(), it returns in ActionListenter's onFailure method, with error code 2. Then, I call connect again after 5-10 seconds, and it returns in onSuccess method. Despite this, on connected device does not appear connection prompt dialog, which means that no connection invite is received I suppose.

These two issues are the main problems that makes application totally unusable. Can anybody explain to me what I'm doing wrong or how to handle these issues?

UPD

Attaching logs for small discovery session.
Host log (nexus 7): http://pastebin.com/ycfqRE4m
Peer log (nexus 10): http://pastebin.com/5kbp6e7A

Community
  • 1
  • 1
Niakros
  • 236
  • 1
  • 3
  • 14
  • It would be helpful if you could please provide details on the devices you are using. Some Wi-Fi Direct issues have their source in the manufacturer drivers. – Stephen Naicken Mar 25 '16 at 14:29
  • 1
    `public static final int BUSY = 2;` - So this error value from the onFailure(int errorCode) method is that substrate is busy and you should reissue the call, this is why the method call is successful after 5-10 seconds. – Stephen Naicken Mar 25 '16 at 14:34
  • @StephenNaicken i'm using nexus 7. nexus 10, lenovo vibe s1, samsung galaxy a5, htc one. I undertand that error code BUSY means that framework doing something that does not allow to perform connect. But what exatcly could it be? And is it right to handle this issue just re-calling WiFiP2pManager.connect() after some delay ? – Niakros Mar 25 '16 at 14:51
  • There is no guidance in the documentation, so I think re-calling connect() is fine. You could repeat the call until it works using exponential backoff or just retry every 10 seconds until your application decides to give up. – Stephen Naicken Mar 25 '16 at 14:55
  • BUSY is returned when the a method is called but the system can not process it for some reason. For example, if the device is in the process of creating a group and then the application calls discoverPeers(), or if an application calls stopDiscovery without ever starting it. – Stephen Naicken Mar 25 '16 at 15:06
  • @StephenNaicken calling connect maximum 4 times with 15 seconds timeout is what i'm doing now. It helps with the second problem, but not solves the first one. – Niakros Mar 25 '16 at 15:36
  • If there is any logcat output of the devices from the devices, it would be good to see that. The connect code in the third code block looks fine. My advice is to try to connect two devices without invoking the discovery code. The deviceAddress is constant, so make a note of this and explicitly try to connect to it without discovery. – Stephen Naicken Mar 25 '16 at 15:56
  • @StephenNaicken i'm not sure wich logs exatly you want to see, so i attached logs for host and peer for short discovery session in update to the question. I will also try to stop discovery on a peer and try to connect than. May be discovering process on peer (which causes peer to broadcast self information) interfere connection process. – Niakros Mar 25 '16 at 17:09
  • if you look at lines 419-421 of the host log, you will see that WPS PIN is being used and authentication is failing. Try removing `config.wps.setup = WpsInfo.PBC;` to see if that helps. – Stephen Naicken Mar 29 '16 at 13:43
  • @StephenNaicken if you'll take a look into `WiFiP2pConfig` constructor you will see that `WpsInfo.PBC` is setted up bu default. This probably won't help, but i'll try it. – Niakros Mar 29 '16 at 16:27
  • Indeed. It likely won't work. All I can say is that I have had issues with the original Nexus 7 device and Wi-Fi Direct, but not the newer version. My advice would be to try to a different device as the host and if necessary, try a different client. For some reason, in the current setup it is using WPS PIN. – Stephen Naicken Mar 29 '16 at 16:38
  • @StephenNaicken the point is that i already tried diefferent devices - nexus 7. nexus 10, lenovo vibe s1, samsung galaxy a5, htc one. And this issue always appears. One more intresting issues that no matter what WPSsetup i'm using - keypad, display, label or pbc, nothing changes. The same confirm dialog. – Niakros Mar 29 '16 at 16:50
  • @StephenNaicken didnt you never see before `WifiP2pService: Invitation result INFORMATION_IS_CURRENTLY_UNAVAILABLE` ? - this is what i see in logs when acceptance dialog doesn't appear on host device. – Niakros Mar 30 '16 at 13:00

1 Answers1

0

this is my solution for your second problem i use a thread for discovery and doesn't use Intent receiver and third problem, don't use stopDiscovery until connection is finished

ConnectHelper.manager.discoverPeers(ConnectHelper.channel, null);
    new WiFiDirectScanner().start();

private class WiFiDirectScanner extends Thread {
    @Override
    public void run() {
        while (context != null) {
            try {
                ConnectHelper.manager.requestPeers(ConnectHelper.channel, peerList -> {
                    Collection<WifiP2pDevice> refreshedPeers = peerList.getDeviceList();
                    if (!refreshedPeers.equals(peers)) {
                        peers.clear();
                        peers.addAll(refreshedPeers);

                        scanSuccessWD();
                    }
                });
            } catch (Exception e) {
                e.printStackTrace();
            }

            try {
                Thread.sleep(3000);
            } catch (InterruptedException ignored) {
            }
        }
    }
}