【问题标题】:How to get the client device details which is connected to wifi hotspot?如何获取连接到 wifi 热点的客户端设备详细信息?
【发布时间】:2014-02-03 08:48:20
【问题描述】:

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

【问题讨论】:

标签: android android-wifi


【解决方案1】:

不幸的是,没有公共 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

希望对你有帮助

【讨论】:

  • 您是否实现了清除 ARP 的代码,并且您是否能够获取每个连接的客户端的更新状态?如果是,请与我分享代码...提前致谢。
  • 到目前为止(在 API 23、24 和 26 上)每个列出的设备的标志都是 0x2,即使设备已断开连接
  • 嘿,正如我所提到的,即使在我在阅读 /proc/net/arp 时断开连接后,它也会显示设备已断开连接,因此在回答中提到我们必须通过命令 ip neigh flush all。我该怎么做这个?然后发出这个命令需要root吗?
  • 有人知道只获取连接的客户端吗?
  • 这个arp文件可以写吗? (比如断开连接到热点的设备)
【解决方案2】:

此方法适用于我,但仅检测 4.0 及更高版本;无法找到与热点连接的2.2或2.3版本的设备。

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) {

    }               
}

【讨论】:

  • 嗨,Prabhu,有没有办法获取不仅连接到热点而且在范围内可用的客户端设备详细信息?
  • 有没有办法断开它们?
【解决方案3】:

Android 10限制了访问/proc/net目录的权限,所以上面的一些方案已经不可行了,但是'ip'命令还是可以的

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
}

【讨论】:

  • 权限被拒绝,错误 13
  • 你用什么手机,能在shell中运行“ip neigh”吗?
  • 我可以使用 exec 命令(您已将其注释掉)运行它,但不能使用进程。我正在使用红米 Note 8 Pro
  • "ip neigh" 从 Android 11 开始似乎不再有效(并且您的应用针对 SDK 30 或更高版本)。
【解决方案4】:
@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;
}

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

@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;
}

【讨论】:

    【解决方案5】:

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

    <receiver
                android:name=".WiFiConnectionReciever"
                android:enabled="true"
                android:exported="true" >
                <intent-filter>
                    <action android:name="android.net.wifi.WIFI_HOTSPOT_CLIENTS_CHANGED" />
                </intent-filter>
            </receiver>
    

    在你的活动中

    IntentFilter mIntentFilter = new IntentFilter();
    mIntentFilter.addAction("android.net.wifi.WIFI_HOTSPOT_CLIENTS_CHANGED");
                            rcv = new WiFiConnectionReciever();
                            registerReceiver(rcv,
                                    mIntentFilter);
    

    【讨论】:

    • WiFiConnectionReciever 课程在哪里
    • WIFI_HOTSPOT_CLIENTS_CHANGED 不再可供订阅
    • 这只是注册广播接收器的两种方式,在编写时应该在它们之间添加“或”
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-09-01
    • 1970-01-01
    • 2012-04-12
    • 1970-01-01
    • 2013-11-21
    • 2023-01-25
    • 1970-01-01
    相关资源
    最近更新 更多