如何准确扫描 android 中所有连接到 wifi 的设备的 IP 和 Mac 地址?

How to scan IP and Mac address of all Device Connected to wifi in android accurately?

您好,我正在尝试从 android 中找到连接到我的 WIFI 路由器的所有设备,并且我需要每个设备(包括物联网设备)的设备 Mac 地址和本地 IP 地址, 现在,我正在尝试从 ARP 缓存 table 中查找。但有时在扫描中会丢失一些设备,因此不太准确。

我的代码:

 List<LocalDeviceInfo> devicesInfos = new ArrayList<>();


        BufferedReader bufferedReader = null;

        try {
            bufferedReader = new BufferedReader(new FileReader("/proc/net/arp"));

            String line;
            while ((line = bufferedReader.readLine()) != null) {
                String[] splitted = line.split(" +");
                if (splitted != null && splitted.length >= 4) {
                    String ip = splitted[0];
                    String mac = splitted[3];
                    if (mac.matches("..:..:..:..:..:..")) {
                        LocalDeviceInfo thisNode = new LocalDeviceInfo(ip, mac);
                        devicesInfos.add(thisNode);
                    }
                }
            }

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally{
            try {
                bufferedReader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        // Print Description
        for (LocalDeviceInfo devicesInfo :devicesInfos)
        {
            System.out.print("✅");
            System.out.println("IP : "+devicesInfo.getIp());
            System.out.println("Mac : "+devicesInfo.getMacAddress());
        }

How can i scan all devices (IP address and Mac address) in android accurately .


我找到了我的问题的解决方案,大多数设备不在系统 arp table 中,所以你需要在第一次 Ping 每个设备,一旦你 ping 该设备,它就会存储在系统 ARP Table 存储在 (/proc/net/arp)

使用 ip ping 所有设备:(首先你需要找到你设备的 IP 地址,然后你可以确定子网掩码,你可以从 (0-255) 开始 pining

代码:

public  void startPingService(Context context)
{
  List<LocalDeviceInfo> deviceInfoList  = new ArrayList<LocalDeviceInfo>();
    try {

        WifiManager mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
        WifiInfo mWifiInfo = mWifiManager.getConnectionInfo();
        String subnet = getSubnetAddress(mWifiManager.getDhcpInfo().gateway);


        for (int i=1;i<255;i++){

            String host = subnet + "." + i;

            if (InetAddress.getByName(host).isReachable(timeout)){

                String strMacAddress = getMacAddressFromIP(host);

                Log.w("DeviceDiscovery", "Reachable Host: " + String.valueOf(host) +" and Mac : "+strMacAddress+" is reachable!");

                    LocalDeviceInfo localDeviceInfo = new LocalDeviceInfo(host,strMacAddress);
                    deviceInfoList.add(localDeviceInfo);
             }
            else
            {
                Log.e("DeviceDiscovery", "❌ Not Reachable Host: " + String.valueOf(host));

            }
        }


    }
    catch(Exception e){
        //System.out.println(e);
    }


}


private String getSubnetAddress(int address)
{
    String ipString = String.format(
            "%d.%d.%d",
            (address & 0xff),
            (address >> 8 & 0xff),
            (address >> 16 & 0xff));

    return ipString;
}

从 ARP 缓存中获取 Mac 地址 Table

public String getMacAddressFromIP(@NonNull String ipFinding)
{

    Log.i("IPScanning","Scan was started!");
    List<LocalDeviceInfo> antarDevicesInfos = new ArrayList<>();


    BufferedReader bufferedReader = null;

    try {
        bufferedReader = new BufferedReader(new FileReader("/proc/net/arp"));

        String line;
        while ((line = bufferedReader.readLine()) != null) {
            String[] splitted = line.split(" +");
            if (splitted != null && splitted.length >= 4) {
                String ip = splitted[0];
                String mac = splitted[3];
                if (mac.matches("..:..:..:..:..:..")) {

                    if (ip.equalsIgnoreCase(ipFinding))
                    {
                        return mac;
                    }
                }
            }
        }

    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } finally{
        try {
            bufferedReader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    return "00:00:00:00";
}

您也需要这些权限:

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

实际上,您只需要ping设备网络的广播地址,就可以使ICMP ECHO请求到达网络上的每一台机器。无需单独ping。另一方面,某些设备不会像 "security precaution" 那样响应这些 ping。由你决定。

然后,按照另一个答案中的代码执行操作 - 解析包含 ARP 缓存的 /proc/net/arp。从 procfs 中的那个特殊文件中,您将找到网络中网络设备的 MAC 地址。 (将其发布为答案是因为我还没有足够的声誉将其添加为对其他答案的评论)