Is Multicast broken for Android 2.0.1 (currently on the DROID) or am I missing something?
- by Gubatron
This code works perfectly in Ubuntu, in Windows and MacOSX, it also works fine with a Nexus-One currently running firmware 2.1.1.
I start sending and listening multicast datagrams, and all the computers and the Nexus-One will see each other perfectly. Then I run the same code on a Droid (Firmware 2.0.1), and everybody will get the packets sent by the Droid, but the droid will listen only to it's own packets.
This is the run() method of a thread that's constantly listening on a Multicast group for incoming packets sent to that group.
I'm running my tests on a local network where I have multicast support enabled in the router.
My goal is to have devices meet each other as they come on line by broadcasting packages to a multicast group.
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);
}
}
Over here, is the code that sends the Multicast Datagram out of every valid network interface available (that's not the loopback interface).
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 (April 2nd 2010)
I found a way to have the Droid's network interface to communicate using Multicast!
_wifiMulticastLock = ((WifiManager) context.getSystemService(Context.WIFI_SERVICE)).createMulticastLock("multicastLockNameHere");
_wifiMulticastLock.acquire();
Then when you're done...
if (_wifiMulticastLock != null && _wifiMulticastLock.isHeld())
_wifiMulticastLock.release();
After I did this, the Droid started sending and receiving UDP Datagrams on a Multicast group.
gubatron