2011-01-11 10 views
26

Estoy tratando de implementar bonjour/zero conf en mi aplicación de Android. Estoy usando la biblioteca jmDns para buscar todos los dispositivos disponibles. Aquí está el código que estoy usando para buscar los dispositivos en la misma red:Implementación de Bonjour en 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(); 
     } 
    } 
} 

Básicamente, los estoy añadiendo en una lista para que pueda mostrar una lista de todos los dispositivos disponibles. Ahora cuando estoy ejecutando este código, no obtengo ninguna excepción/nada como el error. Pero, por otro lado, no se agrega nada a mi lista [PD: al menos 5-6 PC y Mac están ahí en la red.

También trataron de obtener la lista de este código:

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

listener se define en el onCreate de la actividad. Pero esto tampoco devolvió ningún dispositivo.

Por favor, ayuda, sugiere lo que estoy haciendo mal aquí. ¡Cualquier ayuda es apreciada!

+0

No debería estar utilizando este código: if (! InetAddress.isLoopbackAddress() &&! InetAddress.isLinkLocalAddress() && inetAddress.isSiteLocalAddress()) – Radu

+0

@mudit.Entiendo que ha pasado un tiempo desde que te encuentras con este problema. ¿Ha intentado enumerar por "_http._tcp" en lugar de "_http._tcp.local". No puedo explicar por qué, pero hace la diferencia en mi caso. Hasta ahora, solo hace la diferencia cuando se usa NsdManager (descubrimiento estándar de Android). Sabré cómo podría afectar la búsqueda de JmDNS más adelante, tan pronto como nuestro usuario con el problema lo intente ... – vladimir

Respuesta

4

¿Usted sabe a ciencia cierta que multidifusión está activado en su teléfono? Ver http://home.heeere.com/tech-androidjmdns.html.

Y probablemente debería buscar servicios "_ipp._tcp.local" (o algo similar) en lugar de "_http.tcp". Pero eso es solo para probar, ¿verdad? :-)

17

Android 4.1 agrega Network Service Discovery que parece estar terminando la pila de Bonjour en diferentes términos. También veo una API de nivel inferior llamada android.net.wifi.p2p.WifiP2pManager que expone DNS-SD (¿y UPnP?) Directamente.

Tenga en cuenta que el daemon mDNSResponder subyacente no parece funcionar todo el tiempo, y no se utiliza para las búsquedas de todo el sistema de DNS (por ejemplo, desde un navegador) hasta donde puedo decir en este momento.

+0

Tanto Network Service Discovery como Bonjour son implementaciones de [Zeroconf] (http://www.zeroconf.org/) , no envolviendo al otro. – Trisped

+5

No use esto hasta que Android resuelva problemas relacionados con Network Service Discovery. Estos problemas se mencionan como: 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

Descubrí que Android NDS funciona mejor que mdnsjava al que se hace referencia en algunos de los otros comentarios aquí (usando Android 5). Todavía no me da los mismos resultados que veo en la aplicación del navegador Bonjour, lamentablemente. – Bill

2

Puede usar una herramienta existente de Play Store de Android para escanear primero la red local, como "bonjour browser" para asegurarse de que estén los servicios que desea escanear. Luego puede verificar la palabra clave jmDNS para escanear la red.

Pero existe un problema conocido de que jmDns no funciona en algunos dispositivos Android 4.x.

+0

Hola @Zephyr. Dijiste que es un problema conocido que jmDns no funciona en algunos dispositivos Android 4.x. ¿Conoces más detalles? ¿Cuáles son las razones? Tenemos un usuario con este problema. El navegador Bonjour funciona bien para él, pero no se pudo descubrir nada a través de la biblioteca jmDns. Hasta aquí su comentario aquí - la única confirmación de que no solo estoy teniendo este problema con jmDns ... – vladimir

+1

Hola @vladimir, durante el desarrollo, confirmamos que JmDNS no funciona en algunos dispositivos con Android 4.1, funciona en dispositivos con 4.1 versión. la razón quizás esté en la implementación de JmDNS en la plataforma Android, porque la implementación original de Bonjour estaba en la plataforma de iOS, pero no tan utilizable como la de iOS. Por cierto, el NSD nativo de Android tampoco es confiable en las primeras versiones 4.x, se bloquea mucho. – Zephyr

+0

@Zyphyr, entonces, ¿qué biblioteca está utilizando para descubrir finalmente? Estoy pensando en descubrir a través de JmDNS y NSD y luego mostrar algunos resultados de suma para el usuario. ¿Crees que hay mejores opciones por ahora? – vladimir

3

Como se señaló en los comentarios anteriores, el soporte nativo de Android no funciona y/o no se implementa completamente para permitir la recuperación de registros TXT (a partir de Android v5.1). Tampoco pude obtener la biblioteca jmDns para trabajar en el descubrimiento. Finalmente encontré el mdnsjava project y funcionó muy fácilmente para mí. Tenga en cuenta que su código de muestra no es correcto. Aquí hay alguna muestra de código Solía ​​encontrar sincrónicamente todas las impresoras IPP:

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

También tenga en cuenta que es necesario añadir el dnsjava library a sus bibliotecas de carpeta y su build.gradle. Usé la versión 2.1.7.

Cuestiones relacionadas