2010-03-10 10 views
5

Questo codice funziona perfettamente in Ubuntu, Windows e Mac OS X. Funziona perfettamente anche con un Nexus One con Android 2.1.1.Multicast è rotto per Android 2.0.1 (attualmente sul DROID) o mi manca qualcosa?

Inizio a inviare e ad ascoltare i datagrammi multicast e tutti i computer e il Nexus One si vedranno perfettamente. Quindi I eseguo lo stesso codice su un Droid (Firmware 2.0.1), e tutti riceveranno i pacchetti inviati dal Droid, ma il droide ascolterà solo i propri pacchetti.

Questo è il metodo run() di un thread che è costantemente in ascolto su un gruppo Multicast per i pacchetti in entrata inviati a quel gruppo.

Sto eseguendo i miei test su una rete locale in cui ho il supporto multicast abilitato nel router. Il mio obiettivo è far sì che i dispositivi si incontrino mentre arrivano online trasmettendo pacchetti a un gruppo multicast.

public void run() { 
    byte[] buffer = new byte[65535]; 
    DatagramPacket dp = new DatagramPacket(buffer, buffer.length); 

    try { 
     MulticastSocket ms = new MulticastSocket(_port); 
     ms.setNetworkInterface(_ni); //non loopback network interface passed 
     ms.joinGroup(_ia); //the multicast address, currently 224.0.1.16 
     Log.v(TAG,"Joined Group " + _ia); 

     while (true) { 
      ms.receive(dp); 
      String s = new String(dp.getData(),0,dp.getLength()); 
      Log.v(TAG,"Received Package on "+ _ni.getName() +": " + s); 
      Message m = new Message(); 
      Bundle b = new Bundle(); 
      b.putString("event", "Listener ("+_ni.getName()+"): \"" + s + "\""); 
      m.setData(b); 
      dispatchMessage(m); //send to ui thread 
     } 
    } catch (SocketException se) { 
     System.err.println(se); 
    } catch (IOException ie) { 
     System.err.println(ie); 
    } 
} 

Questo è il codice che invia il multicast Datagram da ogni interfaccia di rete valida a disposizione (che non è l'interfaccia di loopback).

public void sendPing() { 
    MulticastSocket ms = null; 
    try { 
     ms = new MulticastSocket(_port); 
     ms.setTimeToLive(TTL_GLOBAL); 

     List<NetworkInterface> interfaces = getMulticastNonLoopbackNetworkInterfaces(); 
     for (NetworkInterface iface : interfaces) { 
      //skip loopback 
      if (iface.getName().equals("lo")) 
       continue; 
      ms.setNetworkInterface(iface); 
      _buffer = ("FW-"+ _name +" PING ("+iface.getName()+":"+iface.getInetAddresses().nextElement()+")").getBytes(); 
      DatagramPacket dp = new DatagramPacket(_buffer, _buffer.length,_ia,_port); 
      ms.send(dp); 
      Log.v(TAG,"Announcer: Sent packet - " + new String(_buffer) + " from " + iface.getDisplayName()); 
     } 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } catch (Exception e2) { 
     e2.printStackTrace(); 
    } 
} 

Update (2 aprile 2010) ho trovato un modo per avere l'interfaccia di rete del Droid di comunicare utilizzando Multicast: WifiManager.MulticastLock.

MulticastLock _wifiMulticastLock = ((WifiManager) context.getSystemService(Context.WIFI_SERVICE)).createMulticastLock("multicastLockNameHere"); 
_wifiMulticastLock.acquire(); 

Poi, quando il gioco è fatto ...

if (_wifiMulticastLock != null && _wifiMulticastLock.isHeld()) 
    _wifiMulticastLock.release(); 

Dopo che ho fatto questo, il Droid ha iniziato a inviare e ricevere datagrammi UDP su un gruppo multicast.

Aggiornamento luglio-6-2010

Per richiesta, ecco il mio codice attuale, il metodo successivo esiste una classe astratta che può essere utilizzato per entrambi i ricevitori Broadcast e Multicast.

public void run() { 
    onInit(); 
    try { 
     byte[] data = new byte[65535]; 
     while (isProcessing()) { 
      try { 
       DatagramPacket receivedDatagram = new DatagramPacket(data, data.length); 
       _socket.receive(receivedDatagram); 
       onDatagramReceived(receivedDatagram); 
       data = new byte[65535]; // This pattern is for saving memory allocation. 
      } catch (InterruptedIOException e) { 
       if (!isProcessing()) 
        break; 
      } 
     } // while 

    } catch (Exception e) { 
     Log.e(TAG, e.getMessage(), e); 
    } finally { 
     onStop(); 
     _socket.close(); 
     _socket.disconnect(); 
    } 
} 

Le classi che si estendono dovrebbero attuare onInit() e onDatagramReceived()

Per un ricevitore Multicast, onInit()sembra qualcosa di simile:

_socket = new MulticastSocket(PORT_MULTICAST); 
InetAddress groupAddress = InetAddress.getByAddress(MULTICAST_GROUP_ADDRESS); 
InetAddress groupInetAddress = FrostWireUtils.fastResolveAddress(groupAddress); //reflection hack to not resolve ips 
try { 
    _socket.setSoTimeout(500); 
    _socket.setTimeToLive(MULTICAST_TTL_GLOBAL); 
    _socket.setReuseAddress(true); 
    _socket.setNetworkInterface(
     WifiUtils.getWifiNetworkInterface()); 
    _socket.joinGroup(groupInetAddress); 
    WifiUtils.lockMulticast(); 
} catch (Exception e) { 
    Log.e(TAG, e.getMessage(), e); 
} 
+0

Sto provando a ricevere pacchetti multicast sul mio Nexus-One (firmware 2.1.1). Ho usato il codice sopra, ma finora non ho avuto fortuna. Puoi allegare la tua fonte completa in modo da poterla confrontare con la mia?Grazie, Eyal – Eyal

+0

Eya, ho aggiunto un aggiornamento, spero che aiuti. – Gubatron

risposta

0

Ho implementato un altro test, questa volta utilizzando UDP Broadcast. Funziona.

Conclusione: Nella misura delle mie conoscenze telefoni Motorola Droid su firmware 2.0.1 non supportano il multicast, ma si può sempre utilizzare DatagramPackets regolari l'indirizzo di broadcast.

+0

Vedere l'aggiornamento (2 aprile 2010) su questo thread. Sono riuscito a far sì che il Droid comunichi su Multicast utilizzando il firmware 2.0.1 acquisendo un blocco Multicast. "WifiManager.MulticastLock Consente a un'applicazione di ricevere pacchetti Multicast Wi-Fi Normalmente lo stack Wifi filtra i pacchetti non indirizzati esplicitamente a questo dispositivo. L'acquisizione di un MulticastLock causerà allo stack la ricezione di pacchetti indirizzati a indirizzi multicast. può causare un notevole consumo della batteria e dovrebbe essere disabilitato quando non è necessario. " – Gubatron

Problemi correlati