I\'m trying to run an application using Android Native Service Discovery but sometimes when I run the application, it doesn\'t discover all services from my network. I\'m runnin
I tend to think the whole NSD implementation in Android must be a bit flaky. I also have a simple Activity just to demonstrate the lifecycle (no Sockets are opened), and sometimes it works, and sometimes it does not work. I simply don't get it. Here is the Activity if anybody has some insight:
https://github.com/mholzel/Dump/blob/master/NetworkServiceDiscoveryViaWifi.java
On the other hand, Wifi Direct based NSD seems to be very reliable for me:
https://github.com/mholzel/Dump/blob/master/NetworkServiceDiscoveryViaWifiDirect.java
Note that neither of these Activities have any resources, so just add the Activities to your Manifest with the proper permissions.
I was seeing the same issue with devices not being discovered and was able to fix it by acquiring the WifiManager Multicast lock prior to discovering services:
val multicastLock: WifiManager.MulticastLock = (mContext.getSystemService(Context.WIFI_SERVICE) as WifiManager).createMulticastLock(TAG)
multicastLock.setReferenceCounted(true)
multicastLock.acquire()
mNsdManager.discoverServices(SERVICE_TYPE, NsdManager.PROTOCOL_DNS_SD, mDiscoveryListener)
And later releasing the lock when done discovering services:
mNsdManager.stopServiceDiscovery(mDiscoveryListener)
multicastLock.release()
To discover all services of the connected network just change the service type you are discovering,
public static final String SERVICE_TYPE = "_services._dns-sd._udp";
I had the same issue, reinstall helped. Try to use:)
It may be little late for the answer, but I found a good solution for NSD for android give on their developer site. I made a few modification and it works perfectly fine.
public class NsdClient {
private Context mContext;
private NsdManager mNsdManager;
NsdManager.DiscoveryListener mDiscoveryListener;
//To find all the available networks SERVICE_TYPE = "_services._dns-sd._udp"
public static final String SERVICE_TYPE = "_hap._tcp.";
public static final String TAG = "NsdClient";
private static ArrayList<NsdServiceInfo> ServicesAvailable = new ArrayList<>();
public NsdClient(Context context) {
mContext = context;
mNsdManager = (NsdManager) context.getSystemService(Context.NSD_SERVICE);
}
public void initializeNsd() {
initializeDiscoveryListener();
}
public void initializeDiscoveryListener() {
mDiscoveryListener = new NsdManager.DiscoveryListener() {
@Override
public void onDiscoveryStarted(String regType) {
Log.d(TAG, "Service discovery started " + regType);
}
@Override
public void onServiceFound(NsdServiceInfo service) {
Log.d(TAG, "Service discovery success " + service);
AVAILABLE_NETWORKS.add(service);
if (!service.getServiceType().equals(SERVICE_TYPE)) {
Log.d(TAG, "Unknown Service Type: " + service.getServiceType());
} else if (service.getServiceName().equals(mServiceName)) {
Log.d(TAG, "Same Machine: " + mServiceName);
} else if (service.getServiceName().contains(mServiceName)) {
Log.d(TAG, "Resolving Services: " + service);
mNsdManager.resolveService(service, new initializeResolveListener());
}
}
@Override
public void onServiceLost(NsdServiceInfo service) {
Log.e(TAG, "service lost" + service);
if (ServicesAvailable.equals(service)) {
ServicesAvailable = null;
}
}
@Override
public void onDiscoveryStopped(String serviceType) {
Log.i(TAG, "Discovery stopped: " + serviceType);
}
@Override
public void onStartDiscoveryFailed(String serviceType, int errorCode) {
Log.e(TAG, "Discovery failed: Error code:" + errorCode);
mNsdManager.stopServiceDiscovery(this);
}
@Override
public void onStopDiscoveryFailed(String serviceType, int errorCode) {
Log.e(TAG, "Discovery failed: Error code:" + errorCode);
mNsdManager.stopServiceDiscovery(this);
}
};
}
public class initializeResolveListener implements NsdManager.ResolveListener {
@Override
public void onResolveFailed(NsdServiceInfo serviceInfo, int errorCode) {
Log.e(TAG, "Resolve failed " + errorCode);
switch (errorCode) {
case NsdManager.FAILURE_ALREADY_ACTIVE:
Log.e(TAG, "FAILURE ALREADY ACTIVE");
mNsdManager.resolveService(serviceInfo, new initializeResolveListener());
break;
case NsdManager.FAILURE_INTERNAL_ERROR:
Log.e(TAG, "FAILURE_INTERNAL_ERROR");
break;
case NsdManager.FAILURE_MAX_LIMIT:
Log.e(TAG, "FAILURE_MAX_LIMIT");
break;
}
}
@Override
public void onServiceResolved(NsdServiceInfo serviceInfo) {
Log.e(TAG, "Resolve Succeeded. " + serviceInfo);
if (serviceInfo.getServiceName().equals(mServiceName)) {
Log.d(TAG, "Same IP.");
return;
}
}
}
public void stopDiscovery() {
mNsdManager.stopServiceDiscovery(mDiscoveryListener);
}
public List<NsdServiceInfo> getChosenServiceInfo() {
return ServicesAvailable;
}
public void discoverServices() {
mNsdManager.discoverServices(
SERVICE_TYPE, NsdManager.PROTOCOL_DNS_SD, mDiscoveryListener);
}
}
Hope it this helps
I'm afraid that there are still bugs in the implementation that cause it to miss services. I've done a couple days of testing with multiple Android devices and a MacBook, and it just doesn't work all the time. I documented my findings on a bug report over in the Android bug tracker: https://code.google.com/p/android/issues/detail?id=178080