2014-05-22 14 views
9

Ich versuche, eine Klasse zu implementieren, um Dienste im Netzwerk zu erkennen. Ich habe versucht, mit Android's NSD arbeiten und es entdeckt die Dienste gut, aber es unterstützt nur API-Ebenen 16 und höher, und ich kann nicht scheinen, das TxtRecord Feld innerhalb der Service-Info abrufen (es gibt aus irgendeinem Grund Null). Stellt sich heraus it's a known problem...Android - jmdns erkennt keine Geräte

So jetzt versuche ich mit jMDns arbeiten, die Dienste überhaupt nicht zu finden scheint. hier ist meine Klasse (ich arbeite mit dem AndroidAnnotations Framework) 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()); 
} 
} 

Und in meiner app Ich nenne:

init(getActivity()); 

Und dann startDiscovery(); Scanvorgang zu starten und stopDiscovery(); Scannen zu stoppen.

Und natürlich gab ich der App die erforderlichen Berechtigungen in der Manifest ... Was fehlt mir hier? Wenn Sie mich brauchen, um zusätzlichen Code/info zur Verfügung zu stellen - fragen Sie einfach. danke !!

Antwort

26

Ich bin der Autor von ZeroConf Browser für Android und ich benutze die Open-Source-Bibliothek JmDNS für alle meine Auflösung. Es funktioniert gut, aber es gibt ein paar Tricks, um es richtig funktionieren zu lassen.

  1. In Ihrem Android manifest.xml stellen Sie sicher, dass Sie mindestens diese Berechtigungen haben.

    <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. Bevor die Aktivität beginnen müssen Sie Multicast-Pakete erlauben durch einen Multicast-Lock zu erwerben.

    @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. Und vergessen Sie nicht die Scan Stoppen der Multicast-Sperre zu entriegeln und JmDNS herunterzufahren.

  4. Am wichtigsten ist, verwenden Sie nicht den Standardkonstruktor. Sie müssen den IP-Adressenkonstruktor verwenden. Ich habe bemerkt, dass du in deinem Code nur JmDNS.create() machst. Ich denke, aus irgendeinem Grund funktioniert Android nur unter Verwendung des folgenden Konstruktors.

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

Works! Es stellte sich heraus, dass ich den falschen Konstruktor verwendet habe, also war es der Punkt 4, der das Problem gelöst hat. Tausend Dank!! :) – orenk86

+0

Eine Sache, die mich umbringt, ist, wie man schnell Geräte im lokalen Netzwerk finden kann, wobei einige Diensttypen verfügbar sind. Ihr Browser ist schnell! Kannst du einen Hinweis geben, wie du es machst? Ich arbeite an einer Fernbedienung für IoT-Geräte und muss alles wissen, was im lokalen Netzwerk schnell ist (und Geräteinformationen im Prozess bekommen). – German

+0

Also sagen Sie, dass Ihr Code die Dienste nicht schnell genug von meinem ZeroConf Browser findet App ist? Alles, was ich benutze, ist der obige Code, also solltest du so schnell wie meins sein? – Melloware