7

First time trying to do IP Discovery in Android. I used the http://developer.android.com/training/connect-devices-wirelessly/nsd.html#discover and wrote the code. I am not registering the device, just Discovering Services in the network. When I run the project in emulator or device the onDiscoveryStarted() gets called, but the onServiceFound() is never called. Please find my Code below. Any input is much appreciated. Thanks!

public class MainActivity extends AppCompatActivity {

    private Button discoverButton;

    Context mContext;

    NsdManager mNsdManager;
    NsdManager.ResolveListener mResolveListener;
    NsdManager.DiscoveryListener mDiscoveryListener;
    NsdManager.RegistrationListener mRegistrationListener;

    public static final String SERVICE_TYPE = "_http._tcp.";
    public static final String TAG = "MyApp_MAIN_CLIENT";
    public String mServiceName = "MyApp";

    /*
    * public static final String SERVICE_TYPE = "_http._tcp.";
    public static final String TAG = "NsdHelper";
    public String mServiceName = "NsdChat";
    * */

    NsdServiceInfo mService;
    private Handler mUpdateHandler;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mNsdManager = (NsdManager) this.getSystemService(Context.NSD_SERVICE);
        discoverButton = (Button) findViewById(R.id.netButton);
        discoverButton.setOnClickListener(new View.OnClickListener() {
            public void onClick(android.view.View v) {
                initializeDiscoveryListener();
                initializeResolveListener();
                discoverServices();

            }
        });

    }

    public void discoverServices() {
        mNsdManager.discoverServices(
                SERVICE_TYPE, NsdManager.PROTOCOL_DNS_SD, mDiscoveryListener);
    }


    public void initializeDiscoveryListener() {

        // Instantiate a new DiscoveryListener
        mDiscoveryListener = new NsdManager.DiscoveryListener() {

            //  Called as soon as service discovery begins.
            @Override
            public void onDiscoveryStarted(String regType) {
                Log.d(TAG, "Service discovery started");
            }

            @Override
            public void onServiceFound(NsdServiceInfo service) {
                // A service was found!  Do something with it.
                Log.d(TAG, "Service discovery success" + service);
                if (!service.getServiceType().equals(SERVICE_TYPE)) {
                    // Service type is the string containing the protocol and
                    // transport layer for this service.
                    Log.d(TAG, "Unknown Service Type: " + service.getServiceType());
                } /*else if (service.getServiceName().equals(mServiceName)) {
                    // The name of the service tells the user what they'd be
                    // connecting to. It could be "Bob's Chat App".
                    Log.d(TAG, "Same machine: " + mServiceName);
                }
                //else if (service.getServiceName().contains("NsdChat")){*/
                else{
                    mNsdManager.resolveService(service, mResolveListener);
                }
            }

            @Override
            public void onServiceLost(NsdServiceInfo service) {
                // When the network service is no longer available.
                // Internal bookkeeping code goes here.
                Log.e(TAG, "service lost" + service);
            }

            @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);
            }
        };
    }// end of initializeListener()


    public void initializeResolveListener() {
        mResolveListener = new NsdManager.ResolveListener() {

            @Override
            public void onResolveFailed(NsdServiceInfo serviceInfo, int errorCode) {
                Log.e(TAG, "Resolve failed" + errorCode);
            }

            @Override
            public void onServiceResolved(NsdServiceInfo serviceInfo) {
                Log.e(TAG, "Resolve Succeeded. " + serviceInfo);

                if (serviceInfo.getServiceName().equals(mServiceName)) {
                    Log.d(TAG, "Same IP.");
                    return;
                }
                mService = serviceInfo;
                int port = mService.getPort();
                InetAddress host = mService.getHost();
                Log.d(TAG,host.toString());
            }
        };
    }//end of initializeResolveListener


    @Override
    protected void onPause() {
        super.onPause();
        stopDiscovery();
        tearDown();

    }

    @Override
    protected void onResume() {
        super.onResume();
        discoverServices();
    }

    @Override
    protected void onDestroy() {
        tearDown();
        super.onDestroy();
    }

    public void stopDiscovery() {
        mNsdManager.stopServiceDiscovery(mDiscoveryListener);
    }


    public void tearDown() {
        mNsdManager.unregisterService(mRegistrationListener);
    }
}
Mahesh Babariya
  • 4,560
  • 6
  • 39
  • 54
pws35
  • 101
  • 1
  • 2
  • _"I am not registering the device, just Discovering Services in the network"_. That's the reason. You can't discover a service that hasn't been registered. One device should register the service which other devices will discover... (An advice regarding the `NSD` sample: don't register and discover the service on the same device) – Onik Apr 22 '16 at 21:10
  • Android NSD documentation specifically says that 'Registering' step is optional. If you don't want to register your device, go to step 2: Discovering other services – pws35 Apr 23 '16 at 03:44
  • Try to remove last dot from "_http._tcp." -> "_http._tcp"; – Dmitry Oct 25 '16 at 10:10

4 Answers4

7

From NdsManager documentation page:

The API currently supports DNS based service discovery and discovery is currently limited to a local network over Multicast DNS.

From this Local networking limitations emulator docs page:

Currently, the emulator does not support IGMP or multicast.

Hope this will help you

sourcerebels
  • 5,140
  • 1
  • 32
  • 52
5

Probably due to the age of this post, I hope you already found a solution.

If not, my experience is that the Android Emulator (API level 25) does not provide a full network stack and the service discovery through NSD isn't working.

I switched to debugging on a real device (like an Android TV or tablet) and then my whole NSD/Bonjour-like setup was working. The methods of the DiscoveryListener and the ResolveListener were called and an IP and port (in my case) were retrieved.

1

After some hours working with Android NSD, I discovered that this library does not work with routers that don't support Multicast. While the other answers may are correct, this could also be the cause of your problem. Possible solutions: enable Multicast on your router if possible, or use another network library.

M Nijzink
  • 11
  • 3
-1

The Network Service Discovery Manager class provides the API to discover services on a network. This will work when your device is connected to the same WIFI network as that of the device providing the service. Hope this helps!! Happy Coding!!

Rajan
  • 292
  • 2
  • 10