转载文章,文章原始出处:http://ticktick.blog.51cto.com/823160/1707858
Socket广播包经常被用于局域网内的两台设备之间互相发现和消息传递,在Android应用开发过程中,也经常会遇到这样的需求,例如:两台Android设备之间、Android与手环等智能硬件之间、Android与Windows电脑之间等等。
本文主要介绍在Android中使用Socket开发广播包程序时需要注意的编程事项,以及解决方法。
首先给出一段Android发送广播包的示例代码:
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);
下面分析其中需要注意的地方:
1. 不要在主线程中发送广播包
当然,这个做Android开发的人应该都知道,不能在UI线程中执行任何网络访问相关的操作,由于广播包的发送也属于网络操作,因此必须放到单独的线程中执行。
2. 广播地址不建议使用“255.255.255.255”
上述代码中,广播包的目标地址设置为了“255.255.255.255”,其实,这并不是一种推荐的做法。
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热点时的广播地址
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,因此,我们需要通过反射的方式来得到,另外,注意添加权限:
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />