Android 2.0.1(目前在DROID上)的组播功能是否存在问题?还是我漏掉了什么?

5

这段代码在Ubuntu、Windows和Mac OS X上完美运行。它还可以在运行Android 2.1.1的Nexus One上正常工作。

我开始发送和监听多播数据包,所有计算机和Nexus One都能完美地看到彼此。然后,我在一个Droid(固件版本为2.0.1)上运行了相同的代码,每个人都可以接收到Droid发送的数据包,但是Droid只会听取自己的数据包

这是一个线程的run()方法,它不断监听一个多播组中传入的数据包。

我在启用了路由器中的多播支持的本地网络上进行测试。

我的目标是通过向多播组广播数据包使设备在上线时相互认识。

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

这是发送多播数据报的代码,它会通过所有有效的网络接口发送(不包括回环接口)。
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();
    }
}

更新(2010年4月2日) 我找到了一种方法,可以使用WifiManager.MulticastLock使Droid的网络接口进行组播通信。

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

然后当你完成时...

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

在我完成这个操作后,Droid开始在多播组上发送和接收UDP数据包。

更新于2010年7月6日

根据请求,这是我的当前代码,next方法存在于一个抽象类中,可用于广播和多播接收器。

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

你的扩展类应该实现 onInit()onDatagramReceived()

对于一个多播接收器,onInit() 看起来像这样:

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

我正在尝试在我的Nexus-One(固件2.1.1)上接收多播数据包。 我使用了上述代码,但到目前为止没有成功的运行。 你能否请提供完整的源代码,以便我可以与我的进行对比?谢谢, Eyal - Eyal
嗨,我已经添加了一个更新,希望它可以帮到你。 - Gubatron
1个回答

0

我实现了另一个测试,这次是使用UDP 广播。它有效。

结论:据我所知,Motorola Droid手机固件2.0.1不支持多播,但您始终可以在广播地址上使用常规的DatagramPackets。


请参见此主题的更新(2010年4月2日)。我已经成功地通过获取多播锁定,使Droid在固件2.0.1上进行多播通信。“WifiManager.MulticastLock允许应用程序接收Wifi多播数据包。通常,Wifi堆栈会过滤掉未明确寻址到该设备的数据包。获取多播锁将导致堆栈接收寻址到多播地址的数据包。处理这些额外的数据包可能会导致明显的电池耗尽,并且在不需要时应禁用它们。” - Gubatron

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接