14

I have a prototype Android app that is listening for multicast packets to 'discover' clients to communicate with. The socket set up is similar to this:

InetAddress group = InetAddress.getByName("228.1.2.3");
MulticastSocket s = new MulticastSocket(4000);
s.joinGroup(group);

This works very well when all the devices are connected via WiFi. I would like to support this with the phone acting as a portable hotspot. However, while all my devices appear to connect to the hotspot correctly I no longer receive multicast data. I'm wondering if there are restrictions that disallow this type of communication in hotspot mode, or if there are is any additional network configuration required to enable this? I've tried this on a couple different devices running Gingerbread and Froyo with no luck.

Gilles D.
  • 1,167
  • 6
  • 16
Sarge
  • 141
  • 1
  • 4
  • 1
    I'd love to hear if you've managed to solve this problem. The way I understand it is that you require a multicastlock in order to get multicast to work at all. And the only way to aquire one is though the wifimanager. Unfortunately with the device set up as a hotspot it appears that the multicast lock is created on the eth0 interface, while the actual communication is happening at wl0.1 This is as far as I've got with this problem, not sure if I'm on the right track. – Petrus Aug 13 '11 at 18:25
  • Pretty much the same thing here. Both devices are broadcasting, but they can't "see" eachother. – Quint Stoffers Nov 12 '11 at 08:48
  • I'd love to tell you guys that i am finished with the solution. :) Multicast over Hotspot. – K. Gandhi Jul 11 '16 at 09:06
  • 3
    Care to post it here Mr. Gandhi? – GPS Sep 21 '16 at 11:16

4 Answers4

3

As this article show: https://plus.google.com/+Chainfire/posts/9NMemrKYnCd

MulticastSocket::setNetworkInterface()

would be the answer

you can find the wlan0 eth by :

public static NetworkInterface getWlanEth() {
    Enumeration<NetworkInterface> enumeration = null;
    try {
        enumeration = NetworkInterface.getNetworkInterfaces();
    } catch (SocketException e) {
        e.printStackTrace();
    }
    NetworkInterface wlan0 = null;
    StringBuilder sb = new StringBuilder();
    while (enumeration.hasMoreElements()) {
        wlan0 = enumeration.nextElement();
        sb.append(wlan0.getName() + " ");
        if (wlan0.getName().equals("wlan0")) {
            //there is probably a better way to find ethernet interface
            Log.i(TAG, "wlan0 found");
            return wlan0;
        }
    }

    return null;
}

Have a try and lemme know if it works or not in Hotspot mode...

DirtyBit
  • 16,613
  • 4
  • 34
  • 55
user707606
  • 61
  • 7
  • This makes a wrong assumption that there is an interface on each possible phone type that is named "wlan0" and that it is the correct interface to use. I think a better approach would be to get _all_ interfaces that [support multicast](https://developer.android.com/reference/java/net/NetworkInterface#supportsMulticast()), create a new multicast socket for each and send/receive on each concurrently. One should probably also periodically refresh the list of available interfaces and add/remove new multicast sockets accordingly. – Peter Jankuliak Sep 09 '22 at 17:00
0

I've had the same problem and came up with a solution by the combination of @braden, @user707606 and the mainly the post by Chainfire in this Link.

Post in the link is nice but doesn't really offer any code samples but here it's. First you need to Acquire Multicast Lock, this is needed for some Android devices, didn't try in most of them but it was mentioned in some other posts, so I've included it in my code.

Permission is required, so first, add the permissions into your Manifest file.

<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />

Then the second step is to acquire multicast lock in your method.

/* Acquire MultiCast Lock */
WifiManager wifi = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
WifiManager.MulticastLock multicastLock = wifi.createMulticastLock("multicastLock");
multicastLock.setReferenceCounted(true);
multicastLock.acquire();

And then, find your Wifi Network Interface

/**
 * Finds Network Interface of Wifi Ethernet.
 *
 * @return
 */
public static NetworkInterface findWifiNetworkInterface() {

    Enumeration<NetworkInterface> enumeration = null;

    try {
        enumeration = NetworkInterface.getNetworkInterfaces();
    } catch (SocketException e) {
        e.printStackTrace();
    }

    NetworkInterface wlan0 = null;

    while (enumeration.hasMoreElements()) {

        wlan0 = enumeration.nextElement();

        if (wlan0.getName().equals("wlan0")) {
            return wlan0;
        }
    }

    return null;
}

Later, create a Multicast socket with an available port and set your Wifi NetworkInterface.

MulticastSocket multicastSocket = new MulticastSocket();

/* Set NetworkInterface of MultiCast Socket */
NetworkInterface wifiNetworkInterface = findWifiNetworkInterface();
if (wifiNetworkInterface != null) multicastSocket.setNetworkInterface(wifiNetworkInterface);

Then the rest of your implementation remains the same. And once you are done with Multicast Lock, it's recommended to release it.

osayilgan
  • 5,873
  • 7
  • 47
  • 68
0

@Peter Jankuliak This is a good idea. Here is a simpler way.

    private fun findWifiNetworkInterface(): NetworkInterface? {
        var enumeration: Enumeration<NetworkInterface?>? = null
        try {
            enumeration = NetworkInterface.getNetworkInterfaces()
        } catch (e: SocketException) {
            e.printStackTrace()
        }
        var wlan0: NetworkInterface? = null
        if (enumeration != null) {
            while (enumeration.hasMoreElements()) {
                wlan0 = enumeration.nextElement()
                if (wlan0 != null) {
                    val list = wlan0.interfaceAddresses.requireNoNulls()
                    for (interfaceAddress in list) {
                        if(interfaceAddress.broadcast!=null){
                            return wlan0
                        }
                    }
                }
            }
        }
        return null
    }
roy
  • 13
  • 3
0

Do you have the manifest permission and are you creating a lock?

For permission please see: 'CHANGE_WIFI_MULTICAST_STATE' in http://developer.android.com/reference/android/Manifest.permission.html

Also, to create a multicast lock... please see: http://developer.android.com/reference/android/net/wifi/WifiManager.MulticastLock.html

braden
  • 1,496
  • 17
  • 31