Android hotspot opens to send broadcast Socket for communication

Socket broadcast packets are often used for mutual discovery and message transfer between two devices in a local area network. In the process of Android application development, such requirements are often encountered, such as: between two Android devices, between Android and a bracelet Between other smart hardware, between Android and Windows computers, and so on.

This article mainly introduces the programming matters that need to be paid attention to when using Socket to develop broadcast package programs in Android, and the solutions.

First give a sample code for Android to send broadcast packets:

DatagramSocket socket = new DatagramSocket(8000);
socket.setBroadcast(true);
InetAddress addr = InetAddress.getByName("255.255.255.255");
byte[] buffer = "Hello World".getBytes();
DatagramPacket packet = new DatagramPacket(buffer,buffer.length);
packet.setAddress(addr);
packet.setPort(8086);
socket.send(packet);

The following points need to be paid attention to:

1. Do not send broadcast packets in the main thread

Of course, this Android developer should know that any network access-related operations cannot be performed in the UI thread. Since the sending of broadcast packets is also a network operation, it must be executed in a separate thread.

2. "255.255.255.255" is not recommended for broadcast address

In the above code, the destination address of the broadcast packet is set to "255.255.255.255". In fact, this is not a recommended practice.

"255.255.255.255" is a restricted broadcast address. It is often used when the computer does not know its own IP address. For example, when the device starts, it asks the DHCP server for an address, etc. Under normal circumstances, the router will not forward the target to the recipient. Broadcast packets restricted to broadcast addresses.

Moreover, some routers/Wi-Fi hotspots do not support this broadcast address (for example, when using an Android phone as a Wi-Fi hotspot), so an exception of "ENETUNREACH (Network is unreachable)" will appear in the program. Therefore, in order to ensure If the program successfully sends the broadcast packet, it is recommended to use the direct broadcast address. For example, when the current IP address is 192.168.1.100 and the subnet mask is 255.255.255.0, the broadcast address is: 192.168.1.255. (The specific calculation method is not listed here. Expanded, you can refer to computer network related books).

So, how to get the direct broadcast address of this network segment, the following is the code shared by a big cow on stackoverflow:

public static InetAddress getBroadcastAddress(Context context) throws UnknownHostException {
    WifiManager wifi = (WifiManager)context.getSystemService(Context.WIFI_SERVICE);
    DhcpInfo dhcp = wifi.getDhcpInfo();
    if(dhcp==null) {
        return InetAddress.getByName("255.255.255.255");
    }
    int broadcast = (dhcp.ipAddress & dhcp.netmask) | ~dhcp.netmask;
    byte[] quads = new byte[4];
    for (int k = 0; k < 4; k++)
        quads[k] = (byte) ((broadcast >> k * 8) & 0xFF);
    return InetAddress.getByAddress(quads);
}

直接使用该函数即可得到正确的“广播地址”,通过setAddress函数设置到DatagramPacket对象中即可。

3. Android设置为Wi-Fi热点时的广播地址

这是个比较大的坑,当Android设备被设置为Wi-Fi热点的时候,上面的函数得到的地址是"0.0.0.0",因此,我们需要探究当Android设备被设置为Wi-Fi热点的时候,它的IP地址究竟是多少?

有人研究了Android底层源码发现,当Android设备被设置为Wi-Fi热点的时候,其IP地址是hardcode写死在源码中的,地址是:“192.168.43.1”,对应的广播地址是:"192.168.43.255"

为此,我们需要写个函数来判断一下当前Android手机是否处于Wi-Fi热点模式下,如果是,则应该使用上面给出的这个广播地址,这里给出代码示例:

protected static Boolean isWifiApEnabled(Context context) {
    try {
        WifiManager manager = (WifiManager)context.getSystemService(Context.WIFI_SERVICE);  
        Method method = manager.getClass().getMethod("isWifiApEnabled");
        return (Boolean)method.invoke(manager);
    }
    catch (NoSuchMethodException e) {
        e.printStackTrace();
    }
    catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e)  {
        e.printStackTrace();
}
    return false;
}

Android SDK并没有开放判断是否处于热点模式的API,因此,我们需要通过反射的方式来得到,另外,注意添加权限: 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325565845&siteId=291194637