Android - jmdns doesn't discover devices

I am the author of ZeroConf Browser for Android and I use the open source Library JmDNS for all my resolving. It works great but there are a few tricks to getting it to work properly.

  1. In your Android manifest.xml make sure you have these permissions at least.

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />
    
  2. Before starting the activity you must allow multi-cast packets by acquiring a multicast lock.

    @Override
    protected void onStart() {
        Log.i(TAG, "Starting ServiceActivity...");
        super.onStart();
        try {
            Log.i(TAG, "Starting Mutlicast Lock...");
            WifiManager wifi = (WifiManager) this.getSystemService(Context.WIFI_SERVICE);
            // get the device ip address
            final InetAddress deviceIpAddress = getDeviceIpAddress(wifi);
            multicastLock = wifi.createMulticastLock(getClass().getName());
            multicastLock.setReferenceCounted(true);
            multicastLock.acquire();
            Log.i(TAG, "Starting ZeroConf probe....");
            jmdns = JmDNS.create(deviceIpAddress, HOSTNAME);
            jmdns.addServiceTypeListener(this);
        } catch (IOException ex) {
            Log.e(TAG, ex.getMessage(), ex);
        }
        Log.i(TAG, "Started ZeroConf probe....");
    }
    
    private InetAddress getDeviceIpAddress(WifiManager wifi) {
       InetAddress result = null;
       try {
          // default to Android localhost
          result = InetAddress.getByName("10.0.0.2");
    
          // figure out our wifi address, otherwise bail
          WifiInfo wifiinfo = wifi.getConnectionInfo();
          int intaddr = wifiinfo.getIpAddress();
          byte[] byteaddr = new byte[] { (byte) (intaddr & 0xff), (byte) (intaddr >> 8 & 0xff),
              (byte) (intaddr >> 16 & 0xff), (byte) (intaddr >> 24 & 0xff) };
          result = InetAddress.getByAddress(byteaddr);
       } catch (UnknownHostException ex) {
          Log.w(TAG, String.format("getDeviceIpAddress Error: %s", ex.getMessage()));
       }
    
       return result;
    }
    
  3. And don't forget on stopping the scan to unlock the multicast lock and shut down JmDNS.

    @Override
    protected void onStop() {
        Log.i(TAG, "Stopping ServiceActivity...");
        super.onStop();
    
        stopScan();
    }
    
    private static void stopScan() {
        try {
            if (jmdns != null) {
                Log.i(TAG, "Stopping ZeroConf probe....");
                jmdns.unregisterAllServices();
                jmdns.close();
                jmdns = null;
            }
            if (multicastLock != null) {
                Log.i(TAG, "Releasing Mutlicast Lock...");
                multicastLock.release();
                multicastLock = null;
            }
        } catch (Exception ex) {
            Log.e(TAG, ex.getMessage(), ex);
        }
    }
    
  4. Most importanty don't use the default constructor. You must use the IP Address Constructor. I noticed in your code you are just doing JmDNS.create(). I think for some reason the only way it works on Android is to use the contructor below.

    jmdns = JmDNS.create(deviceIpAddress, HOSTNAME);