2011-01-11 12 views
26

Ich versuche Bonjour/Zero Conf auf meiner Android-App zu implementieren. Ich benutze jmDns-Bibliothek für die Suche nach allen verfügbaren Geräten. Hier ist der Code, den ich für die Suche, die Geräte im gleichen Netzwerk bin mit:Bonjour Implementierung auf Android

public class ListDevices extends ListActivity { 
    JmDNS jmdns; 
    JmDNSImpl impl; 
    MulticastLock lock; 
    protected ServiceListener listener; 
    protected ServiceInfo info; 
    public ListView lv; 
    public ArrayList<String> deviceList; 
    public int cancel = 0; 
    public final static String TAG = "ListDevices"; 

    /** Called when the activity is first created. */ 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 

     deviceList = new ArrayList<String>(); 
     showAllPrinters(); 

     setListAdapter(new ArrayAdapter<String>(this, 
       android.R.layout.simple_list_item_1, deviceList)); 

     lv = getListView(); 
     lv.setTextFilterEnabled(true); 

     lv.setOnItemClickListener(new OnItemClickListener() { 
      public void onItemClick(AdapterView<?> parent, View view, 
        int position, long id) { 
       // When clicked, show a toast with the TextView text 
       Toast.makeText(getApplicationContext(), 
         ((TextView) view).getText(), Toast.LENGTH_SHORT).show(); 
      } 
     }); 
     this.listener = new ServiceListener() { 
      public void serviceAdded(ServiceEvent event) { 
       deviceList.add("Service added : " + event.getName() + "." 
         + event.getType()); 
       Log.v(TAG, "Service added : " + event.getName() + "." 
         + event.getType()); 
      } 

      public void serviceRemoved(ServiceEvent event) { 
       deviceList.add("Service removed : " + event.getName() + "." 
         + event.getType()); 
       Log.v(TAG, "Service removed : " + event.getName() + "." 
         + event.getType()); 
      } 

      public void serviceResolved(ServiceEvent event) { 
       deviceList.add("Service resolved: " + event.getInfo()); 
       Log.v(TAG, "Service resolved: " + event.getInfo()); 
      } 
     }; 
    } 

    public void showAllPrinters() { 
     Log.d("ListDevices", "in showAllPrinters"); 
     try { 

      WifiManager wifi = (WifiManager) 
           getSystemService(Context.WIFI_SERVICE); 
      lock = wifi.createMulticastLock("fliing_lock"); 
      lock.setReferenceCounted(true); 
      lock.acquire(); 

      InetAddress inetAddress = getLocalIpAddress(); 
      jmdns = JmDNS.create(inetAddress, "TEST"); 

      ServiceInfo[] infos = jmdns.list("_http._tcp.local."); 

      if (infos != null && infos.length > 0) { 
       for (int i = 0; i < infos.length; i++) { 
        deviceList.add(infos[i].getName()); 
       } 
      } else { 
       deviceList.add("No device found."); 
      } 
      impl = (JmDNSImpl) jmdns; 

     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 

    public InetAddress getLocalIpAddress() { 
     try { 
      for (Enumeration<NetworkInterface> en = NetworkInterface 
        .getNetworkInterfaces(); en.hasMoreElements();) { 
       NetworkInterface intf = (NetworkInterface) en.nextElement(); 
       for (Enumeration<InetAddress> enumIpAddr = intf 
         .getInetAddresses(); enumIpAddr.hasMoreElements();) { 
        InetAddress inetAddress = (InetAddress) enumIpAddr 
          .nextElement(); 
        if (!inetAddress.isLoopbackAddress()) { 
         return inetAddress; 
        } 
       } 
      } 
     } catch (SocketException ex) { 
      Log.e("ListDevices", ex.toString()); 
     } 
     return null; 
    } 

    @Override 
    protected void onPause() { 
     super.onPause(); 
     if (isFinishing()) { 
      lock.release(); 
     } 
    } 
} 

Grundsätzlich ich sie in einer Liste bin hinzugefügt, so dass ich eine Liste aller verfügbaren Geräte anzeigen kann. Jetzt, wenn ich diesen Code ausführe, bekomme ich keine Ausnahme/nichts wie Fehler. Aber auf der anderen Seite wird meiner Liste nichts hinzugefügt [PS: dort sind mindestens 5-6 PCs und Macs im Netzwerk vorhanden.

Ich habe auch versucht die Liste von diesem Code zu erhalten:

jmdns.addServiceListener("_http._tcp.local.", listener); 

listener im onCreate der Aktivität definiert ist. Aber das hat auch kein Gerät zurückgegeben.

Bitte helfen Sie, schlagen Sie vor, was ich hier falsch mache. Jede Hilfe wird geschätzt!

+0

Sollten Sie diesen Code nicht verwenden: if (! InetAddress.isLoopbackAddress() &&! InetAddress.isLinkLocalAddress() && inetAddress.isSiteLocalAddress()) – Radu

+0

@mudit.Ich verstehe, dass einige Zeit vergangen ist, seit du auf dieses Problem gestoßen bist. Haben Sie versucht, mit "_http._tcp" anstatt mit "_http._tcp.local." Aufzulisten. Ich kann nicht erklären warum, aber es macht einen Unterschied in meinem Fall. Bisher macht es nur bei Verwendung von NsdManager (Standard Android Discovery) einen Unterschied. Ich werde wissen, wie es JmDNS Lookup später beeinflussen könnte, sobald unser Benutzer mit dem Problem es versuchen wird ... – vladimir

Antwort

4

Haben Sie für eine Tatsache, dass Multicast auf Ihrem Telefon aktiviert ist? Siehe http://home.heeere.com/tech-androidjmdns.html.

Und Sie sollten wahrscheinlich nach "_ipp._tcp.local" (oder etwas ähnliches) statt "_http.tcp" -Dienste suchen. Aber das ist nur zum Testen, oder? :-)

17

Android 4.1 fügt Network Service Discovery hinzu, das scheint, den Bonjour-Stapel in anderen Begriffen nur aufzuwickeln. Ich sehe auch eine untergeordnete API namens android.net.wifi.p2p.WifiP2pManager, die DNS-SD (sowie UPnP?) Direkt verfügbar macht.

Beachten Sie, dass der zugrunde liegende mDNSResponder-Daemon nicht ständig ausgeführt wird und nicht für systemweite DNS-Suchvorgänge (z. B. von einem Browser) verwendet wird, soweit ich das jetzt beurteilen kann.

+0

Sowohl Network Service Discovery und Bonjour sind Implementierungen von [Zeroconf] (http://www.zeroconf.org/) den anderen nicht einwickeln. – Trisped

+5

Bitte verwenden Sie dies nicht bis Android lösen Network Service Discovery Probleme. Diese Probleme werden wie folgt erwähnt: 1) .http: //code.google.com/p/android/issues/detail?id=39583 2) .https: //code.google.com/p/android/issues/detail ? ID = 35585 3) .http: //code.google.com/p/android/issues/detail?id=39750 –

+0

Ich habe festgestellt, dass Android NDS besser funktioniert als mdnsjava, auf das in einigen der anderen Kommentare hier verwiesen wird (mit Android 5). Es gibt mir immer noch nicht die gleichen Ergebnisse, die ich in der Bonjour Browser App leider sehe. – Bill

2

Sie können ein vorhandenes Tool aus dem Play Store von Android verwenden, um zuerst das lokale Netzwerk zu scannen, z. B. "bonjour browser", um sicherzustellen, dass die zu scannenden Dienste vorhanden sind. Dann können Sie das Schlüsselwort jmDNS überprüfen, um das Netzwerk zu scannen.

Es gibt jedoch ein bekanntes Problem, dass jmDns auf einigen Android 4.x-Geräten nicht funktioniert.

+0

Hallo @Zephyr. Sie haben gesagt, dass es bekannt ist, dass jmDns auf einigen Android 4.x-Geräten nicht funktioniert. Weißt du mehr Details? Was sind Gründe? Wir haben einen Benutzer mit diesem Problem. Bonjour Browser funktioniert gut für ihn, aber nichts konnte über die jmDns-Bibliothek entdeckt werden. Bis jetzt Ihr Kommentar hier - die einzige Bestätigung, dass ich nicht nur dieses Problem mit jmDns habe ... – vladimir

+1

Hallo @vladimir, während der Entwicklung haben wir bestätigt, dass JmDNS auf einigen Android 4.1-Geräten nicht funktioniert, es funktioniert auf Geräten unter 4.1 Ausführung. Der Grund liegt vielleicht in der Implementierung von JmDNS auf Android-Plattform, denn die ursprüngliche Implementierung von Bonjour war auf der iOS-Plattform, nur nicht so nutzbar wie die von iOS. Übrigens ist die Android native NSD auch auf den frühen 4.x Versionen nicht verlässlich, es stürzt viel ab. – Zephyr

+0

@Zyphyr, welche Bibliothek benutzt du also, um sie endlich zu entdecken? Ich denke, durch JmDNS und NSD zu entdecken und dann einige Summenergebnisse dem Benutzer zu zeigen. Denkst du, dass es jetzt bessere Möglichkeiten gibt? – vladimir

3

Wie in den Kommentaren oben erwähnt, funktioniert die native Android-Unterstützung nicht und/oder ist nicht vollständig implementiert, um den Abruf von TXT-Datensätzen zu ermöglichen (ab Android v5.1). Ich konnte auch nicht die jmDns-Bibliothek für die Entdeckung arbeiten. Ich fand schließlich die mdnsjava project und es funktionierte sehr leicht für mich. Beachten Sie, dass der Beispielcode nicht korrekt ist. Hier einige Beispiel-Code I verwendet, um synchron alle IPP-Drucker zu finden:

String type[] = {"_ipp._tcp.local."}; 
    Lookup resolve = null; 
    try { 
     resolve = new Lookup(type, Type.ANY, DClass.IN); 
     ServiceInstance[] records = resolve.lookupServices(); 
     for (ServiceInstance record : records) { 
      Log.d(TAG, record.toString()); 
      Map txtMap = record.getTextAttributes(); 
     } 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 

Beachten Sie auch, dass Sie die dnsjava library zu Ihrem libs Ordner und Ihre build.gradle hinzufügen müssen. Ich habe Version 2.1.7 benutzt.