功能如题所述,查询出连接了相同wifi的手机的品牌信息,可以使用作为检测蹭网功能的核心功能。
首先介绍一下实现原理,安卓系统采用ARP协议,ARP协议即地址解析协议,是一种根据IP地址获取物理地址(MAC地址)的协议。主机发送报文信息到指定的IP地址病获得返回信息后写入到本地的ARP缓存,结果信息在本地ARP文件中保存一定时间。查询品牌功能的实现基于arp协议。当对于局域网中一个IP发送报文后,安卓会将返回的信息写入本地的ARP文件中,而返回的信息中包括了设备的mac地址信息。由于mac地址的前六位都是唯一对应厂商的,所以根据IEEE提供的mac地址文档即可查找出对应的厂商信息,做好中文适配即可。
代码实现分为以下步骤:
1.读取手机当前IP地址
2.读取当前子网掩码
3.根据子网掩码和IP地址即可计算当前wifi的有效IP地址集合
4.对生成的IP集合中的每一个IP发送udp报文
5.读取本地ARP表格获取有效的mac地址信息
6.根据mac地址信息查找对应厂商信息
给出各个步骤关键代码实现,后续会给出demo以供下载。
1.读取手机当前IP地址
/**
* 获取本机ip地址
*
* @return
*/
public static String getLocalIPAddress() {
String ip = "";
try {
for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces();
en.hasMoreElements(); ) {
NetworkInterface intf = en.nextElement();
for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses();
enumIpAddr.hasMoreElements(); ) {
InetAddress inetAddress = enumIpAddr.nextElement();
if (!inetAddress.isLoopbackAddress() && inetAddress instanceof Inet4Address) {
ip = inetAddress.getHostAddress();
break;
}
}
if (!TextUtils.isEmpty(ip)) break;
}
} catch (Exception e) {
ip = "";
}
return ip;
}
2.读取当前子网掩码
/**
* 获取本机子网掩码
*
* @return
*/
public static String getNetMask() {
try {
Enumeration<NetworkInterface> eni = NetworkInterface
.getNetworkInterfaces();
while (eni.hasMoreElements()) {
NetworkInterface networkCard = eni.nextElement();
List<InterfaceAddress> ncAddrList = networkCard
.getInterfaceAddresses();
for (InterfaceAddress networkCardAddress : ncAddrList) {
InetAddress address = networkCardAddress.getAddress();
if (!address.isLoopbackAddress()) {
String hostAddress = address.getHostAddress();
if (hostAddress.indexOf(":") <= 0) {
return calcMaskByPrefixLength(networkCardAddress.getNetworkPrefixLength());
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return "not found";
}
3.根据子网掩码和IP地址即可计算当前wifi的有效IP地址集合
public static List<String> parseIpMaskRange(String ip, String MASK) {
String mask = getNetMask(MASK) + "";
Log.i("scanner", mask);
List<String> list = new ArrayList<String>();
if ("32".equals(mask)) {
list.add(ip);
} else {
String startIp = getBeginIpStr(ip, mask);
String endIp = getEndIpStr(ip, mask);
if (!"31".equals(mask)) {
String subStart = startIp.split("\\.")[0] + "." + startIp.split("\\.")[1] + "." + startIp.split("\\.")[2] + ".";
String subEnd = endIp.split("\\.")[0] + "." + endIp.split("\\.")[1] + "." + endIp.split("\\.")[2] + ".";
startIp = subStart + (Integer.valueOf(startIp.split("\\.")[3]) + 1);
endIp = subEnd + (Integer.valueOf(endIp.split("\\.")[3]) - 1);
}
list = parseIpRange(startIp, endIp);
}
return list;
}
public static List<String> parseIpRange(String ipfrom, String ipto) {
List<String> ips = new ArrayList<String>();
String[] ipfromd = ipfrom.split("\\.");
String[] iptod = ipto.split("\\.");
int[] int_ipf = new int[4];
int[] int_ipt = new int[4];
for (int i = 0; i < 4; i++) {
int_ipf[i] = Integer.parseInt(ipfromd[i]);
int_ipt[i] = Integer.parseInt(iptod[i]);
}
for (int A = int_ipf[0]; A <= int_ipt[0]; A++) {
for (int B = (A == int_ipf[0] ? int_ipf[1] : 0); B <= (A == int_ipt[0] ? int_ipt[1]
: 255); B++) {
for (int C = (B == int_ipf[1] ? int_ipf[2] : 0); C <= (B == int_ipt[1] ? int_ipt[2]
: 255); C++) {
for (int D = (C == int_ipf[2] ? int_ipf[3] : 0); D <= (C == int_ipt[2] ? int_ipt[3]
: 255); D++) {
ips.add(new String(A + "." + B + "." + C + "." + D));
}
}
}
}
return ips;
}
4.对生成的IP集合中的每一个IP发送udp报文private class UDPThread extends Thread { private String target_ip = ""; final byte[] NBREQ = {(byte) 0x82, (byte) 0x28, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x1, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x20, (byte) 0x43, (byte) 0x4B, (byte) 0x41, (byte) 0x41, (byte) 0x41, (byte) 0x41, (byte) 0x41, (byte) 0x41, (byte) 0x41, (byte) 0x41, (byte) 0x41, (byte) 0x41, (byte) 0x41, (byte) 0x41, (byte) 0x41, (byte) 0x41, (byte) 0x41, (byte) 0x41, (byte) 0x41, (byte) 0x41, (byte) 0x41, (byte) 0x41, (byte) 0x41, (byte) 0x41, (byte) 0x41, (byte) 0x41, (byte) 0x41, (byte) 0x41, (byte) 0x41, (byte) 0x41, (byte) 0x41, (byte) 0x41, (byte) 0x0, (byte) 0x0, (byte) 0x21, (byte) 0x0, (byte) 0x1}; static final short NBUDPP = 137; UDPThread(String target_ip) { this.target_ip = target_ip; } @Override public synchronized void run() { if (target_ip == null || target_ip.equals("")) return; DatagramSocket socket = null; InetAddress address = null; DatagramPacket packet = null; try { address = InetAddress.getByName(target_ip); packet = new DatagramPacket(NBREQ, NBREQ.length, address, NBUDPP); socket = new DatagramSocket(); socket.setSoTimeout(200); socket.send(packet); socket.close(); } catch (Exception se) { se.printStackTrace(); } finally { if (socket != null) { socket.close(); } } } }
5.读取本地ARP表格获取有效的mac地址信息6.根据mac地址信息查找对应厂商信息/** * 读取arp信息 */ private void readArp() { macListFromRead = new ArrayList<TerminalBean>(); try { BufferedReader br = new BufferedReader( new FileReader("/proc/net/arp")); String line = ""; String ip = ""; String flag = ""; String mac = ""; String gateWay = new WifiInfoUtil(getApplicationContext()).getGateWay(); Log.i("wangguan", "网关" + gateWay); while ((line = br.readLine()) != null) { try { line = line.trim(); Log.i("scanner", line); if (line.length() < 63) continue; if (line.toUpperCase(Locale.US).contains("IP")) continue; ip = line.substring(0, 17).trim(); flag = line.substring(29, 32).trim(); mac = line.substring(41, 63).trim(); if (mac.contains("00:00:00:00:00:00")) continue; if (gateWay.equals(ip)) continue;//过滤网关 Log.i("scanner", "readArp: mac= " + mac + " ; ip= " + ip + " ;flag= " + flag); TerminalBean terminalBean = new TerminalBean(); terminalBean.setMac(mac); terminalBean.setIp(ip); macListFromRead.add(terminalBean);//读出的所有mac地址信息保存 } catch (Exception e) { e.printStackTrace(); } } br.close(); } catch (Exception e) { e.printStackTrace(); } Log.i("scanner", "end"); }
后续给出实现demo。效果如下:/** * 根据mac地址从txt文件中查询品牌信息 * * @param mac mac地址 * @return 品牌信息 */ private static String findCompanyFromTxt(Context context, String mac, int id) { InputStream inputStream = context.getResources().openRawResource(id); InputStreamReader inputStreamReader = null; inputStreamReader = new InputStreamReader(inputStream); BufferedReader reader = null; reader = new BufferedReader(inputStreamReader); String line; try { while ((line = reader.readLine()) != null) { if (line.contains(mac)) { return line;//获取到型号行 } } } catch (IOException e) { e.printStackTrace(); } return null; }
![]()