NsdManager 不会停止服务发现
NsdManager doesn't stop service discovery
在我目前正在开发的 Android
应用程序中,我想使用 NsdManager
连接做零配置网络。
我设法 运行 网络服务发现并连接到所需的网络,但在停止发现后 NsdManager
线程仍然 运行ning。这会导致这样的情况,即在屏幕旋转几次后,有许多 NsdManager
线程正在浏览连接。
当任何网络可用时,设备会多次尝试同步,因此尽管停止了服务发现,但每个 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();
}
我该如何解决这个问题?
我目前的解决方案是使包含 NsdManager(上例中的 NsdTest)的 class 成为上下文不断变化的单例。
即使在停止服务发现后,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;
}
...}
如果有人知道更好的解决方案,请post。
原因是因为NsdManager.stopServiceDiscovery
是异步的。从 documentation 开始,您必须等待 onDiscoveryStopped(String)
发现会话真正结束。
您在发送异步请求后立即暂停可能意味着当您的应用程序在后台时,本应触发的回调得到了 "lost"。异步回调有一个习惯,不能很好地处理在后台。
在我目前正在开发的 Android
应用程序中,我想使用 NsdManager
连接做零配置网络。
我设法 运行 网络服务发现并连接到所需的网络,但在停止发现后 NsdManager
线程仍然 运行ning。这会导致这样的情况,即在屏幕旋转几次后,有许多 NsdManager
线程正在浏览连接。
当任何网络可用时,设备会多次尝试同步,因此尽管停止了服务发现,但每个 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();
}
我该如何解决这个问题?
我目前的解决方案是使包含 NsdManager(上例中的 NsdTest)的 class 成为上下文不断变化的单例。
即使在停止服务发现后,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;
}
...}
如果有人知道更好的解决方案,请post。
原因是因为NsdManager.stopServiceDiscovery
是异步的。从 documentation 开始,您必须等待 onDiscoveryStopped(String)
发现会话真正结束。
您在发送异步请求后立即暂停可能意味着当您的应用程序在后台时,本应触发的回调得到了 "lost"。异步回调有一个习惯,不能很好地处理在后台。