Ответ 1
WifiP2p
(в общем):
Некоторое время назад я разрабатывал приложение с довольно сложной системой сетевого подключения на основе WifiP2p
с Service Broadcasting/Discovery
. И основываясь на этом опыте, я уже писал несколько сообщений здесь о SO о том, как сложно, носят и проблемны. Вот два из них (они полны внутренних знаний, которые я приобрел около WifiP2p
с помощью Service Discovery
и WifiP2p
):
Почему обнаружение сверстников для Android WifiDirect настолько ненадежное
Wi-fi P2P. Сообщите всем одноранговым узлам о каком-либо событии
Я бы посоветовал вам прочитать оба моих ответа (хотя они больше ориентированы на WifiP2p
). Они должны дать вам некоторое представление о том, что вам нужно искать при работе с WifiP2p Service Discovery
.
Я могу легко сказать, что если вы хотите создать эффективную, относительно надежную и надежную систему соединения WifiP2p
(особенно с Service Discovery
), вам придется отключить свою задницу.
WifiP2p Service Discovery
:
Чтобы лучше ответить на ваш точный вопрос, я расскажу вам, что я сделал (отличное от вас), чтобы сделать мою работу Service Discovery
довольно надежной.
1. Трансляция Service
:
Прежде всего: перед тем, как зарегистрировать свой Service
(с помощью метода addLocalService
), вы должны использовать метод WifiP2pManager
clearLocalServices
. И важно, чтобы вы < только вызывали 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
}
});
}
где 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);
}
};
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();
}
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
}
});
}
mServiceDiscoveringRunnable
был просто:
private Runnable mServiceDiscoveringRunnable = new Runnable() {
@Override
public void run() {
startServiceDiscovery();
}
};
Все это заставило мою систему работать хорошо. Это еще не было совершенным, но из-за отсутствия документации по этому вопросу я думаю, что не мог сделать больше, чтобы улучшить его.
Если вы протестируете этот подход, обязательно расскажите мне, как он работает для вас (или если он работает для вас;)).