关于android:如何获取连接到wifi热点的客户端设备详细信息?

How to get the client device details which is connected to wifi hotspot?

我在我的android应用程序中以编程方式将不同的设备与wifi热点AP连接,如何检测以编程方式连接和断开连接的客户端以及wifi热点AP? Android API中是否有任何回调事件可提供有关单个设备的连接或断开连接事件的信息? 提前致谢。


不幸的是,没有公共API可以提供有关此信息...
但是您可以阅读/ proc / net / arp文件,并查看连接到访问点的客户端。

/ proc / net / arp文件具有6个字段:IP地址,硬件类型,标志,硬件地址,掩码和设备

问题是客户端断开连接时,因为它不会从文件中消失。一个解决方案可能是对每个客户端执行ping操作,然后等待响应,但是对我来说,这不是一个好的解决方案,因为某些客户端不响应ping。如果您喜欢此解决方案,请在GitHub上检查此项目-> https://github.com/nickrussler/Android-Wifi-Hotspot-Manager-Class/tree/master/src/com/whitebyte

我所做的是:读取/ proc / net / arp并检查FLAGS字段,当该值为0x2时表示工作站已连接且0x0断开了连接,但是要刷新此字段,我需要不时清除ARP缓存,并且我用以下命令做到了:ip neigh flush all

我希望我能帮助你


此方法对我有效,但这仅检测4.0版及更高版本;它找不到与热点连接的2.2或2.3版本的设备。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public void getClientList() {
    int macCount = 0;
    BufferedReader br = null;
    try {
        br = new BufferedReader(new FileReader("/proc/net/arp"));
        String line;
        while ((line = br.readLine()) != null) {
            String[] splitted = line.split(" +");
            if (splitted != null ) {
                // Basic sanity check
                String mac = splitted[3];
                System.out.println("Mac : Outside If"+ mac );
                if (mac.matches("..:..:..:..:..:..")) {
                    macCount++;
                   /* ClientList.add("Client(" + macCount +")");
                    IpAddr.add(splitted[0]);
                    HWAddr.add(splitted[3]);
                    Device.add(splitted[5]);*/
                    System.out.println("Mac :"+ mac +" IP Address :"+splitted[0] );
                    System.out.println("Mac_Count " + macCount +" MAC_ADDRESS "+ mac);
                Toast.makeText(
                        getApplicationContext(),
                       "Mac_Count " + macCount +"   MAC_ADDRESS "
                                + mac, Toast.LENGTH_SHORT).show();

                }
               /* for (int i = 0; i < splitted.length; i++)
                    System.out.println("Addressssssss    "+ splitted[i]);*/

            }
        }
    } catch(Exception e) {

    }              
}


Android 10限制了对/ proc / net目录的访问权限,因此上述某些解决方案不再可行,但" ip"命令仍然可用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
private fun getARPIps(): List<Pair<String, String>> {
    val result = mutableListOf<Pair<String, String>>()
    try {
//        val args = listOf("ip","neigh")
//        val cmd = ProcessBuilder(args)
//        val process: Process = cmd.start()
      val process = Runtime.getRuntime().exec("ip neigh")
        val reader = BufferedReader(InputStreamReader(process.inputStream))
        reader.forEachLine {
            if (!it.contains("FAILED")) {
                val split = it.split("\\\\s+".toRegex())
                if (split.size > 4 && split[0].matches(Regex("([0-9]{1,3}\\\\.){3}[0-9]{1,3}"))) {
                    result.add(Pair(split[0], split[4]))
                }
            }
        }
        val errReader = BufferedReader(InputStreamReader(process.errorStream))
        errReader.forEachLine {
            Log.e(TAG, it)
            // post the error message to server
        }
        reader.close()
        errReader.close()
        process.destroy()
    } catch (e: Exception){
        e.printStackTrace()
        // post the error message to server
    }
    return result
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
@SuppressWarnings("ConstantConditions")
public static String getClientMacByIP(String ip)
{
    String res ="";
    if (ip == null)
        return res;

    String flushCmd ="sh ip -s -s neigh flush all";
    Runtime runtime = Runtime.getRuntime();
    try
    {
        runtime.exec(flushCmd,null,new File("/proc/net"));
    }

    BufferedReader br;
    try
    {
        br = new BufferedReader(new FileReader("/proc/net/arp"));
        String line;
        while ((line = br.readLine()) != null)
        {
            String[] sp = line.split(" +");
            if (sp.length >= 4 && ip.equals(sp[0]))
            {Assistance.Log(sp[0]+sp[2]+sp[3],ALERT_STATES.ALERT_STATE_LOG);
                String mac = sp[3];
                if (mac.matches("..:..:..:..:..:..") && sp[2].equals("0x2"))
                {
                    res = mac;
                    break;
                }
            }
        }

        br.close();
    }
    catch (Exception e)
    {}

    return res;
}

// ------------------------------------------------ --------

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
@SuppressWarnings("ConstantConditions")
public static String getClientIPByMac(String mac)
{
    String res ="";
    if (mac == null)
        return res;

    String flushCmd ="sh ip -s -s neigh flush all";
    Runtime runtime = Runtime.getRuntime();
    try
    {
        runtime.exec(flushCmd,null,new File("/proc/net"));
    }

    BufferedReader br;
    try
    {
        br = new BufferedReader(new FileReader("/proc/net/arp"));
        String line;
        while ((line = br.readLine()) != null)
        {
            String[] sp = line.split(" +");
            if (sp.length >= 4 && mac.equals(sp[3]))
            {
                String ip = sp[0];
                if (ip.matches("\\\\d{1,3}\\\\.\\\\d{1,3}\\\\.\\\\d{1,3}\\\\.\\\\d{1,3}") && sp[2].equals("0x2"))
                {
                    res = ip;
                    break;
                }
            }
        }

        br.close();
    }
    catch (Exception e)
    {}

    return res;
}

您可以使用BroadcastReciever" android.net.wifi.WIFI_HOTSPOT_CLIENTS_CHANGED"来检测客户端连接。
在您的AndroidManifest中:

1
2
3
4
5
6
7
8
<receiver
            android:name=".WiFiConnectionReciever"
            android:enabled="true"
            android:exported="true">
            <intent-filter>
               
            </intent-filter>
        </receiver>

和你的活动

1
2
3
4
5
IntentFilter mIntentFilter = new IntentFilter();
mIntentFilter.addAction("android.net.wifi.WIFI_HOTSPOT_CLIENTS_CHANGED");
                        rcv = new WiFiConnectionReciever();
                        registerReceiver(rcv,
                                mIntentFilter);