我正在开发一个需要发现同一个Wi-Fi网络中所有设备的项目。为了实现这一点,我使用了Jmdns库。
它向我提供了注册到当前网络的设备列表,但是当设备取消注册时,它应该调用serviceRemoved ServiceListener方法。但是,当设备未注册时,它不会调用serviceRemoved
。
这是我的代码:
public class LanService {
private static LanService instance = new LanService();
private final String TYPE = "_sample._tcp.local.";
private JmDNS jmdns = null;
private ServiceInfo serviceInfo;
private WifiManager.MulticastLock lock;
private ServiceListener listener;
public static LanService getInstance() {
return instance;
}
public void startDiscovery() {
WifiManager wifi = (WifiManager) AppBase.getAppContext().getSystemService(Context.WIFI_SERVICE);
if (wifi.isWifiEnabled()) {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
Thread startDiscoveryThread = new Thread(new Runnable() {
@Override
public void run() {
if (serviceInfo != null) {
stopScan();
}
setUp();
}
});
startDiscoveryThread.start();
}
}, 2000);
}
}
@Override
public void stopDiscovery() {
Thread stopDiscoveryThread = new Thread(new Runnable() {
@Override
public void run() {
stopScan();
}
});
stopDiscoveryThread.start();
}
private void setUp() {
try {
WifiManager wifi = (WifiManager) AppBase.getAppContext().getSystemService(Context.WIFI_SERVICE);
if (!wifi.isWifiEnabled()) {
wifi.setWifiEnabled(true);
}
// get the device ip address
final InetAddress deviceIpAddress = getLocalIpAddress();
if (deviceIpAddress != null) {
lock = wifi.createMulticastLock(getClass().getName());
lock.setReferenceCounted(true);
lock.acquire();
jmdns = JmDNS.create(deviceIpAddress);
serviceInfo = ServiceInfo.create(TYPE, Build.MODEL, 3129, "plain test service from android");
jmdns.registerService(serviceInfo);
jmdns.addServiceListener(TYPE, listener = new ServiceListener() {
@Override
public void serviceResolved(ServiceEvent ev) {
Log.d(TAG, "Service Resolved : " + ev.getInfo().getQualifiedName() + " ipAddr : " + ev.getInfo().getInetAddresses()[0]);
}
@Override
public void serviceRemoved(ServiceEvent ev) {
Log.d(TAG, "Service Removed : " + ev.getInfo().getQualifiedName() + " ipAddr : " + ev.getInfo().getInetAddresses()[0]);
}
@Override
public void serviceAdded(ServiceEvent ev) {
try {
// Required to force serviceResolved to be called again (after the first search)
Log.d(TAG, "Service Added : " + ev.getInfo().getQualifiedName());
jmdns.requestServiceInfo(ev.getType(), ev.getName(), 1000);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
} catch (IOException ex) {
ex.printStackTrace();
Log.e(TAG, ex.getMessage(), ex);
}
Log.i(TAG, "Started ZeroConf probe....");
}
private void stopScan() {
try {
if (jmdns != null) {
Log.i(TAG, "Stopping ZeroConf probe....");
jmdns.removeServiceListener(TYPE, listener);
jmdns.unregisterService(serviceInfo);
jmdns.unregisterAllServices();
jmdns.close();
jmdns = null;
}
if (lock != null) {
Log.i(TAG, "Releasing Mutlicast Lock...");
if (lock.isHeld())
lock.release();
lock = null;
}
} catch (Exception ex) {
Log.e(TAG, ex.getMessage(), ex);
}
}
}
为什么在从网络注销设备时不会调用serviceRemoved
?任何建议表示赞赏。
答案 0 :(得分:0)
为什么要在处理程序的runnable中打开一个线程? Handler在单独的线程上运行runnable。你做的是:
- 处理程序在一个线程上运行runnable,然后打开另一个线程并执行你的操作。也许那是你的问题。
而不是:
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
Thread startDiscoveryThread = new Thread(new Runnable() {
@Override
public void run() {
if (serviceInfo != null) {
stopScan();
}
setUp();
}
});
startDiscoveryThread.start();
}
}, 2000);
试试这个:
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
if (serviceInfo != null) {
stopScan();
}
setUp();
}
}, 2000);