Android - jmdns doesn't discover devices

后端 未结 2 1794
慢半拍i
慢半拍i 2020-12-23 12:22

I\'m trying to implement a class to discover services on the network. I\'ve tried working with Android\'s NSD and it does discover the services fine, but it supports only AP

2条回答
  •  不思量自难忘°
    2020-12-23 13:07

    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.

      
      
      
      
    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);
      

提交回复
热议问题