Est Multicast cassé pour Android 2.0.1 (actuellement sur le DROID) ou suis-je manque quelque chose?

StackOverflow https://stackoverflow.com/questions/2414453

Question

Ce code fonctionne parfaitement dans Ubuntu, Windows et Mac OS X. Il fonctionne aussi bien avec un Nexus One sous Android 2.1.1.

Je commence à envoyer et à l'écoute des datagrammes multicast, et tous les ordinateurs et le Nexus On verra parfaitement. Ensuite, I exécuter le même code sur un Droid (Firmware 2.0.1), et tout le monde va obtenir les paquets envoyés par le Droid, mais le droïde écoutera seulement à ses propres paquets .

Ceci est la méthode run() d'un fil qui est constamment à l'écoute sur un groupe Multicast pour les paquets entrants envoyés à ce groupe.

Je suis en cours d'exécution mes tests sur un réseau local où j'ai le soutien de multidiffusion activé dans le routeur. Mon objectif est d'avoir des appareils se rencontrent comme ils viennent en ligne par paquets de diffusion à un groupe de multidiffusion.

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

Ceci est le code qui envoie des datagrammes multicast sur chaque interface réseau valide disponible (ce n'est pas l'interface de réalimentation).

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

Mise à jour (2e Avril 2010) J'ai trouvé un moyen d'avoir l'interface réseau du Droid de communiquer en utilisant Multicast: WifiManager.MulticastLock .

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

Ensuite, lorsque vous avez terminé ...

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

Après avoir fait cela, le Droid a commencé à envoyer et recevoir des datagrammes UDP sur un groupe Multicast.

Mise à jour Jul-6-2010

Par demande, voici mon code actuel, la méthode suivante existe sur une classe abstraite qui peut être utilisé aussi bien pour les récepteurs de diffusion et de multidiffusion.

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

Vos cours s'étendant devraient mettre en œuvre onInit() et onDatagramReceived()

Pour Multicast récepteur, onInit() ressemble à quelque chose comme ceci:

_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);
}
Était-ce utile?

La solution

J'ai mis en place un autre test, cette fois en utilisant UDP Diffusion . Il fonctionne.

Conclusion:. Dans la mesure de mes connaissances Motorola Droid téléphones sur le firmware 2.0.1 ne prend pas en charge la multidiffusion, mais vous pouvez toujours utiliser DatagramPackets régulièrement sur l'adresse de diffusion

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top