NsdManager не останавливает обнаружение службы
В приложении Android
, которое я сейчас разрабатываю, я хочу подключить нулевые сети с помощью NsdManager
.
Мне удалось запустить обнаружение сетевых сервисов и подключиться к нужной сети, но после остановки обнаружения поток NsdManager
все еще запущен. Это приводит к ситуации, когда после нескольких поворотов экрана существует много потоков NsdManager
, которые просматривают соединение.
![enter image description here]()
Когда какая-либо сеть доступна, устройство пытается синхронизировать много раз, поэтому каждый NsdManager
по-прежнему активен, несмотря на прекращение обнаружения службы.
Ниже показан мой код:
package dtokarzewsk.nsdservicetest;
import android.content.Context;
import android.net.nsd.NsdManager;
import android.net.nsd.NsdServiceInfo;
import android.util.Log;
import java.net.InetAddress;
public class NsdTest {
private static final String NSD_SERVICE_NAME = "TestService";
private static final String NSD_SERVICE_TYPE = "_http._tcp.";
private int mPort;
private InetAddress mHost;
private Context mContext;
private NsdManager mNsdManager;
private android.net.nsd.NsdManager.DiscoveryListener mDiscoveryListener;
private android.net.nsd.NsdManager.ResolveListener mResolveListener;
public NsdTest(Context context) {
mContext = context;
}
public void startListening() {
initializeResolveListener();
initializeDiscoveryListener();
mNsdManager = (NsdManager) mContext.getSystemService(Context.NSD_SERVICE);
mNsdManager.discoverServices(NSD_SERVICE_TYPE, NsdManager.PROTOCOL_DNS_SD, mDiscoveryListener);
}
public void stopListening() {
mNsdManager.stopServiceDiscovery(mDiscoveryListener);
}
private void initializeResolveListener() {
mResolveListener = new NsdManager.ResolveListener() {
@Override
public void onResolveFailed(NsdServiceInfo serviceInfo, int errorCode) {
Log.d("NSDService test","Resolve failed");
}
@Override
public void onServiceResolved(NsdServiceInfo serviceInfo) {
NsdServiceInfo info = serviceInfo;
Log.d("NSDService test","Resolve failed");
mHost = info.getHost();
mPort = info.getPort();
Log.d("NSDService test","Service resolved :" + mHost + ":" + mPort);
}
};
}
private void initializeDiscoveryListener() {
mDiscoveryListener = new NsdManager.DiscoveryListener() {
@Override
public void onStartDiscoveryFailed(String serviceType, int errorCode) {
Log.d("NSDService test","Discovery failed");
}
@Override
public void onStopDiscoveryFailed(String serviceType, int errorCode) {
Log.d("NSDService test","Stopping discovery failed");
}
@Override
public void onDiscoveryStarted(String serviceType) {
Log.d("NSDService test","Discovery started");
}
@Override
public void onDiscoveryStopped(String serviceType) {
Log.d("NSDService test","Discovery stopped");
}
@Override
public void onServiceFound(NsdServiceInfo serviceInfo) {
NsdServiceInfo info = serviceInfo;
Log.d("NSDService test","Service found: " + info.getServiceName());
if (info.getServiceName().equals(NSD_SERVICE_NAME))
mNsdManager.resolveService(info, mResolveListener);
}
@Override
public void onServiceLost(NsdServiceInfo serviceInfo) {
NsdServiceInfo info = serviceInfo;
Log.d("NSDService test","Service lost: " + info.getServiceName());
}
};
}
}
И в главном Activity
:
private NsdTest mNsdTest;
@Override
protected void onResume() {
super.onResume();
mNsdTest = new NsdTest(this);
mNsdTest.startListening();
}
@Override
protected void onPause() {
mNsdTest.stopListening();
super.onPause();
}
Как я могу исправить эту проблему?
Ответы
Ответ 1
Мое текущее решение для этого - сделать класс, содержащий NsdManager (NsdTest в приведенном выше примере) синглтон с изменяющимся контекстом.
Это не меняет того факта, что поток NSdManager постоянно работает даже после остановки обнаружения службы, но по крайней мере есть только один активный поток NsdManager после возобновления приложения.
Возможно, это не самый изящный способ, но для меня это достаточно.
public class NsdTest {
private static NsdTest mInstance;
private static final String NSD_SERVICE_NAME = "TestService";
private static final String NSD_SERVICE_TYPE = "_http._tcp.";
private int mPort;
private InetAddress mHost;
private Context mContext;
private NsdManager mNsdManager;
private android.net.nsd.NsdManager.DiscoveryListener mDiscoveryListener;
private android.net.nsd.NsdManager.ResolveListener mResolveListener;
private static NsdTest mInstance;
private NsdTest(Context context) {
mContext = context;
}
public static NsdTest getInstance(Context context) {
if (mInstance == null) {
mInstance = new NsdTest(context);
} else {
mContext = context;
}
return mInstance;
}
...}
Если кто-нибудь знает лучшее решение, отправьте его.
Ответ 2
Причина в том, что NsdManager.stopServiceDiscovery
является асинхронным. Из документации вы должны дождаться завершения onDiscoveryStopped(String)
для завершения сеанса обнаружения.
То, что вы делаете паузу сразу после отправки асинхронного запроса, вероятно, означает, что обратный вызов, который был бы запущен, получил "потерянный", поскольку ваше приложение было в фоновом режиме. Асинхронные обратные вызовы имеют привычку не работать в фоновом режиме.