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

Android 如何获取连接到wifi热点的客户端设备详细信息?,android,android-wifi,Android,Android Wifi,在我的android应用程序中,我以编程方式使用wifi热点AP连接不同的设备,如何检测连接和断开的客户端以及以编程方式连接到wifi热点AP的客户端?Android API中是否存在任何回调事件来提供有关单个设备的连接或断开事件的信息?提前感谢。此方法对我有效,但仅检测4.0及以上版本;找不到与hotspot连接的版本为2.2或2.3的设备 public void getClientList() { int macCount = 0; BufferedReader br = n

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

此方法对我有效,但仅检测4.0及以上版本;找不到与hotspot连接的版本为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) {

    }               
}
public void getClientList(){
int macCount=0;
BufferedReader br=null;
试一试{
br=新的BufferedReader(新的文件读取器(“/proc/net/arp”);
弦线;
而((line=br.readLine())!=null){
String[]splitted=line.split(“+”);
如果(已拆分!=null){
//基本健康检查
字符串mac=splitted[3];
System.out.println(“Mac:如果“+Mac”,则为外部);
如果(mac.matches(“…:”)){
macCount++;
/*添加(“客户端(“+macCount+”);
IpAddr.add(拆分为[0]);
HWAddr.add(拆分[3]);
设备。添加(拆分[5])*/
System.out.println(“Mac:+Mac+”IP地址:“+splitted[0]);
System.out.println(“Mac_计数”+macCount+“Mac_地址”+Mac);
Toast.makeText(
getApplicationContext(),
“Mac_计数”+Mac计数+“Mac_地址”
+mac,Toast.LENGTH_SHORT).show();
}
/*对于(int i=0;i
不幸的是,没有公共API提供有关此的信息。。。 但是您可以读取/proc/net/arp文件并查看连接到您的接入点的客户端

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

问题是当客户端断开连接时,因为它不会从文件中消失。一个解决方案可能是对每个客户端执行ping并等待响应,但对我来说这不是一个好的解决方案,因为有些客户端不响应ping。如果您喜欢此解决方案,请在GitHub上检查此项目-->

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


我希望我能帮助您

您可以使用BroadcastReceiver“android.net.wifi.wifi\u HOTSPOT\u client\u 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>
//--------------------------------------------------------

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

安卓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
}
private fun getARPIps():列表{
val result=mutableListOf()
试一试{
//val args=列表(“ip”、“neigh”)
//val cmd=ProcessBuilder(args)
//val进程:进程=cmd.start()
val process=Runtime.getRuntime().exec(“ip neigh”)
val reader=BufferedReader(InputStreamReader(process.inputStream))
读写器{
如果(!it.contains(“失败”)){
val split=it.split(“\\s+”.toRegex())
if(split.size>4&&split[0]。匹配(Regex(([0-9]{1,3}\\){3}[0-9]{1,3}”)){
结果.添加(对(拆分[0],拆分[4]))
}
}
}
val errReader=BufferedReader(InputStreamReader(process.errorStream))
errReader.forEachLine{
Log.e(标记,it)
//将错误消息发布到服务器
}
reader.close()
errReader.close()
process.destroy()
}捕获(e:例外){
e、 printStackTrace()
//将错误消息发布到服务器
}
返回结果
}

您只能使用
BroadcastReceiver
目标指向
连接
来控制运行应用程序的设备。重复的。但这个问题并没有答案。您是否实现了清除ARP的代码,以及您是否能够获得每个连接的客户端的更新状态?如果是,请与我分享代码。。。提前感谢。截至目前(API 23、24和26)每个列出的设备的标志是
0x2
,即使设备断开连接。正如所提到的,即使在我读取/proc/net/arp时断开连接,它也会显示断开连接的设备,正如在回答中提到的,我们必须传递命令ip neigh flush all。我如何做到这一点?是否需要根目录来发出此命令?有人知道吗仅获取连接的客户端的答案是什么?是否可以写入此arp文件?(如断开连接到热点的设备)WifiConnectionReceiver类别在哪里?Wifi_hotspot_Client_CHANGED不再可供订阅这些只是注册广播接收器的两种方式,在写入Hi Prabhu时应在它们之间添加“或”,是否有方法获取不仅连接到热点而且在范围内可用的客户端设备详细信息?是否有方法断开它们的连接?权限被拒绝,错误13您使用什么电话,您可以在shell中运行“ip neigh”吗?我可以使用exec命令(您已注释掉)运行它,但不使用进程。我使用的是Redmi Note 8 Pro“ip neigh”从Android 11开始似乎不再有效(而你的应用程序是针对SDK的)
@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;
}
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
}