Как заставить работать обнаружение одноранговой сети Wi-Fi?

Я пытаюсь построить серверно-клиентскую архитектуру, используя два устройства Android с одноранговым WiFi-соединением. У меня есть четкое различие между клиентом и сервером, поэтому я пытаюсь удалить ненужный код. Использование указаний с http://developer.android.com/training/connect-devices-wireless/nsd-wifi-direct.html У меня есть...

одноранговая служба

public class PeerToPeerService {
    private static final Logger LOG = LoggerFactory.getLogger(PeerToPeerService.class);

    private WifiP2pManager mManager;
    private WifiP2pManager.Channel mChannel;
    private final Context mContext;
    private final WifiP2pDnsSdServiceInfo mService;

    public PeerToPeerService(Context context, String name) {
        mContext = context;

        Map<String, String> record = new HashMap<String, String>();
        record.put(Constants.SERVICE_PROPERTY_NAME, name);
        record.put(Constants.SERVICE_PROPERTY_PORT, "12345");

        mService = WifiP2pDnsSdServiceInfo.newInstance(
                "_test", "_presence._tcp", record);
    }

    public void start() {
        mManager = (WifiP2pManager) mContext.getSystemService(Context.WIFI_P2P_SERVICE);
        mChannel = mManager.initialize(mContext, mContext.getMainLooper(), null);

        mManager.addLocalService(mChannel, mService, new ActionListener() {
            @Override
            public void onSuccess() {
                LOG.info("Started Service");
            }

            @Override
            public void onFailure(int error) {
                LOG.warn("Failed to Start Service: {}", error);
            }
        });
    }

    public void stop() {
        mManager.removeLocalService(mChannel, mService, null);
        mManager = null;
        LOG.info("Stopped Service");
    }
}

одноранговый клиент

public class PeerToPeerClient {
    private static final Logger LOG = LoggerFactory.getLogger(PeerToPeerClient.class);

    private WifiP2pManager mManager;
    private WifiP2pManager.Channel mChannel;
    private final Context mContext;

    public PeerToPeerClient(Context context) {
        mContext = context;
    }

    public void findServices() {
        mManager = (WifiP2pManager) mContext.getSystemService(Context.WIFI_P2P_SERVICE);
        mChannel = mManager.initialize(mContext, mContext.getMainLooper(), null);

        mManager.setDnsSdResponseListeners(mChannel,
                new DnsSdServiceResponseListener() {
                    @Override
                    public void onDnsSdServiceAvailable(String instanceName,
                            String registrationType, WifiP2pDevice device) {
                        LOG.info("A");
                        LOG.info("Service Found: {}:{}", instanceName, registrationType);
                    }
                }, 
                new DnsSdTxtRecordListener() {
                    @Override
                    public void onDnsSdTxtRecordAvailable(String fullDomainName, Map<String, String> record,
                            WifiP2pDevice device) {
                        LOG.info("B");
                        LOG.info("{}:{} is {}", device.deviceName, 
                                record.get(Constants.SERVICE_PROPERTY_PORT), record.get(Constants.SERVICE_PROPERTY_NAME));
                    }
                });

        WifiP2pDnsSdServiceRequest serviceRequest = WifiP2pDnsSdServiceRequest.newInstance();
        mManager.addServiceRequest(mChannel, serviceRequest,
                new ActionListener() {
                    @Override
                    public void onSuccess() {
                        LOG.info("Added service discovery request");
                    }

                    @Override
                    public void onFailure(int error) {
                        LOG.info("Failed adding service discovery request: {}", error);
                    }
                });

        mManager.discoverServices(mChannel, new ActionListener() {
            @Override
            public void onSuccess() {
                LOG.info("Service discovery initiated");
            }

            @Override
            public void onFailure(int arg0) {
                LOG.info("Service discovery failed");
            }
        });
    }
}

У каждого ActionListener вызывается onSuccess, нигде нет сбоев. Но я никогда не получаю никаких обратных вызовов setDnsSdResponseListeners. Есть идеи, где я мог ошибиться?


person Hounshell    schedule 12.02.2014    source источник
comment
Обратите внимание, что образец Android, демонстрирующий это, отлично работает между моими устройствами.   -  person Hounshell    schedule 12.02.2014


Ответы (4)


У меня есть некоторый опыт работы с Wi-Fi Direct на устройствах Android, я пишу приложение для специального подключения устройств и позволяю общаться в чате по этой ссылке.

Чтобы быть обнаруженными в Wi-Fi Direct, оба устройства должны сканировать, т.е. mWifiP2pManager.discoverPeers(). Как ни странно, это также влияет на обнаружение DnsTxtRecordServices. Таким образом, я обнаружил, что это работает, если вы запустите scanning( discoverPeers()) на обоих устройствах, а затем запустите discoverPeers().

Надеюсь это поможет! :)

person Daniel Schoonwinkel    schedule 09.01.2015
comment
не могли бы вы посмотреть на этот вопрос http://stackoverflow.com/questions/28252866/inconsistency-in-getting-wifip2pinfo-in-wifidirect - person Hunt; 01.02.2015
comment
Чтобы их можно было обнаружить в Wi-Fi Direct, оба устройства должны сканироваться, т. е. mWifiP2pManager.discoverPeers()... Вы спасли мой день! - person Massimo; 29.10.2015

Я думаю, что вы упустили некоторые моменты:

PeerToPeerService : код сервера

1. реализовать обнаружение клиентов

PeerToPeerClient: клиентский код

1. внедрить дополнительную клиентскую локальную службу

которые будут обнаружены серверами

Пиртопирсервис:

    // after adding local service
    manager.setDnsSdResponseListeners(channel,
            new DnsSdServiceResponseListener() {
             ...
    }

Одноранговый клиент:

mChannel = mManager.initialize(mContext, mContext.getMainLooper(), null);
// add  client local service
mManager.addLocalService(mChannel, mService, new ActionListener() {
            @Override
            public void onSuccess() {
                LOG.info("Started Service");
            }

            @Override
            public void onFailure(int error) {
                LOG.warn("Failed to Start Service: {}", error);
            }
        });

После этого кода вы сможете получить обратный вызов onDnsSdResponseListener и сможете подключиться

После подключения вы можете проверить, являетесь ли вы сервером или клиентом, с помощью WifiP2pInfo.isGroupOwner — true для сервера и false для клиента.

person Kushal    schedule 02.04.2015

Как для клиента, так и для сервера вы должны вызвать addLocalService и discoverServices для работы WifiP2p.

Map record = new HashMap();
record.put("name","your_app_anme");

WifiP2pDnsSdServiceInfo serviceInfo = WifiP2pDnsSdServiceInfo.newInstance("_test", "_presence.tcp", record);
wifiP2pManager.addLocalService(wifiP2pChannel, serviceInfo, null);


wifiP2pManager.setDnsSdResponseListeners(wifiP2pChannel, new WifiP2pManager.DnsSdServiceResponseListener() {
    @Override
    public void onDnsSdServiceAvailable(String s, String s1, WifiP2pDevice wifiP2pDevice) {
        Log.wtf("WTF", "device "+wifiP2pDevice.deviceName + "/"+wifiP2pDevice.deviceAddress);
    }
}, new WifiP2pManager.DnsSdTxtRecordListener() {
    @Override
    public void onDnsSdTxtRecordAvailable(String s, Map<String, String> map, WifiP2pDevice wifiP2pDevice) {
        Log.wtf("WTF", "got txt "+map.get("name") );
    }
});

WifiP2pDnsSdServiceRequest serviceRequest = WifiP2pDnsSdServiceRequest.newInstance();
wifiP2pManager.addServiceRequest(wifiP2pChannel, serviceRequest, null);
wifiP2pManager.discoverServices(wifiP2pChannel, null);
person user1884811    schedule 27.08.2015

После тонны попыток я получил надежный работоспособный поток, подобный этому:

...
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) {
            }
        });
person Amos    schedule 04.11.2016