2014-05-22 16 views
9

Sto cercando di implementare una classe per scoprire i servizi sulla rete. Ho provato a lavorare con Android's NSD e rileva bene i servizi, ma supporta solo i livelli API 16 e successivi, e non riesco a recuperare il campo txtRecord all'interno delle informazioni sul servizio (restituisce null per qualche motivo). Risulta it's a known problem...Android - jmdns non rileva i dispositivi

Così ora sto provando a lavorare con jMDns, che non sembra affatto trovare servizi. ecco la mia classe (sto lavorando con il quadro AndroidAnnotations) MDnsHelper:

@EBean 
public class MDnsHelper implements ServiceListener { 

public static final String SERVICE_TYPE = "_http._tcp.local"; 

Activity activity; 
private JmDNS jmdns; 
private MulticastLock multicastLock; 
WifiManager wm; 
InetAddress bindingAddress; 
boolean isDiscovering; 

public void init(Activity activity) { 
    this.activity = activity; 
    isDiscovering = false; 
    wm = (WifiManager) activity.getSystemService(Context.WIFI_SERVICE); 
    multicastLock = wm.createMulticastLock(activity.getPackageName()); 
    multicastLock.setReferenceCounted(false); 
} 

@Background 
public void startDiscovery() { 
    if (isDiscovering) 
     return; 
    System.out.println("starting..."); 
    multicastLock.acquire(); 
    try { 
     System.out.println("creating jmdns"); 
     jmdns = JmDNS.create(); 
     System.out.println("jmdns created"); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } finally { 
     if (jmdns != null) { 
      jmdns.addServiceListener(SERVICE_TYPE, MDnsHelper.this); 
      isDiscovering = true; 
      System.out.println("discovering services of type: " + SERVICE_TYPE); 
     } 
    } 
} 

@Background 
public void stopDiscovery() { 
    if (!isDiscovering || jmdns == null) 
     return; 
    System.out.println("stopping..."); 
    multicastLock.release(); 
    jmdns.removeServiceListener(SERVICE_TYPE, MDnsHelper.this); 
    System.out.println("listener for " + SERVICE_TYPE + " removed"); 
    try { 
     jmdns.close(); 
     isDiscovering = false; 
     System.out.println("jmdns closed"); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
} 

@Override 
public void serviceAdded(ServiceEvent service) { 
    System.out.println("found: " + service.getInfo().toString()); 
} 

@Override 
public void serviceRemoved(ServiceEvent service) { 
    System.out.println("lost: " + service.getInfo().toString()); 
} 

@Override 
public void serviceResolved(ServiceEvent service) { 
    System.out.println("resolved: " + service.getInfo().toString()); 
} 
} 

E nella mia app che io chiamo:

init(getActivity()); 

E poi startDiscovery(); per avviare la scansione e stopDiscovery(); per fermare la scansione.

E ovviamente, ho dato all'app le autorizzazioni necessarie nel manifest ... Cosa mi manca qui? Se hai bisogno di me per fornire codice/informazioni aggiuntive - basta chiedere. grazie !!

risposta

26

Io sono l'autore di ZeroConf Browser per Android e utilizzo la libreria JmDNS open source per tutte le mie risoluzioni. Funziona benissimo ma ci sono alcuni trucchi per farlo funzionare correttamente.

  1. Nel tuo manifest manifest.xml Android assicurati di avere almeno queste autorizzazioni.

    <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. Prima di iniziare l'attività è necessario consentire i pacchetti multicast con l'acquisizione di un blocco multicast.

    @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. E non dimenticate di fermarsi la scansione per sbloccare la serratura multicast e spegnere 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. Principalmente non utilizzare il costruttore predefinito. È necessario utilizzare il Costruttore indirizzo IP. Ho notato nel tuo codice che stai facendo JmDNS.create(). Penso che per qualche ragione l'unico modo in cui funziona su Android è quello di utilizzare il contructor qui sotto.

    jmdns = JmDNS.create(deviceIpAddress, HOSTNAME); 
    
+2

Opere! È venuto fuori che ho usato il costruttore sbagliato, quindi il proiettile 4 è stato quello che l'ha risolto. Grazie mille!! :) – orenk86

+0

Una cosa che mi uccide è come si può trovare rapidamente i dispositivi nella rete locale con alcuni tipi di servizio disponibili. Il tuo browser è veloce! Puoi dare un suggerimento su come lo fai? Sto lavorando a un telecomando per dispositivi IoT e ho bisogno di sapere tutto ciò che vive sulla rete locale velocemente (e ottenere informazioni sul dispositivo nel processo) – German

+0

Quindi stai dicendo che il tuo codice non sta trovando abbastanza velocemente i servizi dal mio browser ZeroConf l'app è? Tutto quello che sto usando è il codice sopra così teoricamente il tuo dovrebbe essere veloce come il mio? – Melloware

Problemi correlati