You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android13执行ip neigh show返回退出码1,求热点连接设备IP获取方案

Android 13+ 获取热点连接设备IP的替代方案

问题背景

我开发了一款简易自定义应用,用于查询连接到手机本地热点的自定义设备的温度、速度等信息。在Android 12及以下系统中,通过runtime.exec('ip neigh show')命令,配合compileSdkVersion 29、buildToolsVersion '29.0.3'、minSdkVersion 21和targetSdkVersion 27的配置,可完美获取连接设备的IP地址。

但在Android 13设备上调试时,执行runtime.exec('ip neigh show')返回ExitCode = 1,推测是Android 13对该命令读取的/proc/net/arp文件施加了严格限制。

补充信息1

目前在Android 13设备上仅能通过以下代码获取热点IP:

wifiManager = (WifiManager) getActivity().getApplicationContext().getSystemService(Context.WIFI_SERVICE);
wifiInfo = wifiManager.getConnectionInfo();
ipAddress = Formatter.formatIpAddress( wifiInfo.getIpAddress() );

能否通过该IP查询连接设备的IP,而无需使用ip neigh show?

补充信息2

尝试使用以下代码检查CONNECTIVITY_MANAGER:

Network[] allNetworks = connectivityManager.getAllNetworks();
for (Network network: allNetworks) {
    NetworkInfo networkInfo = connectivityManager.getNetworkInfo(network);
    LinkProperties lp = connectivityManager.getLinkProperties(network);
    String id = lp.getInterfaceName();
    Log.d("IdInfo", "id: " + id);
}

调试中仅看到MOBILE[LTE]连接,热点是否应被视为连接主机?


解决方案

1. 使用WifiManager的getDhcpLeases()方法(Android 13+)

Android 13(API 33)新增了WifiManager.getDhcpLeases()方法,可直接获取连接到热点的设备的DHCP租赁信息,其中包含设备IP、MAC地址等关键数据。

示例代码:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
    WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
    List<DhcpLease> leases = wifiManager.getDhcpLeases();
    for (DhcpLease lease : leases) {
        String deviceIp = lease.getIpAddress().getHostAddress();
        String deviceMac = lease.getHardwareAddress();
        // 处理设备信息
    }
}

注意:需要在Manifest中声明ACCESS_WIFI_STATE权限,Android 13+中该权限为普通权限,无需动态申请。

2. 遍历热点子网IP进行ping探测(兼容方案)

如果需要兼容更低版本,或者无法使用getDhcpLeases(),可以通过热点IP推算子网范围,然后逐个ping探测在线设备:

  • 先通过已有代码获取热点IP(Android热点默认网关IP通常为192.168.43.1)
  • 子网范围一般是192.168.43.2到192.168.43.254
  • 使用多线程对每个IP执行ping操作,判断设备是否在线

示例代码片段:

String hotspotIp = Formatter.formatIpAddress(wifiInfo.getIpAddress());
// 拆分IP,生成子网前缀
String[] parts = hotspotIp.split("\\.");
String subnetPrefix = parts[0] + "." + parts[1] + "." + parts[2] + ".";

// 遍历子网内的IP
for (int i = 2; i <= 254; i++) {
    String targetIp = subnetPrefix + i;
    new Thread(() -> {
        try {
            Process process = Runtime.getRuntime().exec("ping -c 1 -W 1 " + targetIp);
            int exitCode = process.waitFor();
            if (exitCode == 0) {
                // 该IP设备在线,记录信息
                Log.d("OnlineDevice", "IP: " + targetIp);
            }
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }
    }).start();
}

注意:这种方法效率较低,需要INTERNET权限,且部分设备可能禁用ping响应导致漏检。

3. 关于CONNECTIVITY_MANAGER的问题

热点作为AP模式时,属于本地网络,不会被getAllNetworks()标记为"连接"状态(设备本身是热点提供者而非连接者)。可以通过LinkProperties的getInterfaceName()识别热点接口,通常热点接口名为wlan0或ap0,结合WifiManager.isWifiApEnabled()判断热点状态后筛选对应接口。

示例代码:

WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
if (wifiManager.isWifiApEnabled()) {
    ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    Network[] allNetworks = connectivityManager.getAllNetworks();
    for (Network network : allNetworks) {
        LinkProperties lp = connectivityManager.getLinkProperties(network);
        if (lp != null) {
            String ifName = lp.getInterfaceName();
            // 热点接口通常包含"ap"或"wlan"关键词
            if (ifName.contains("ap") || ifName.contains("wlan")) {
                Log.d("HotspotInterface", "Interface: " + ifName);
                // 获取该接口的IP信息
                List<InetAddress> addresses = lp.getAddresses();
                for (InetAddress addr : addresses) {
                    Log.d("HotspotIP", "IP: " + addr.getHostAddress());
                }
            }
        }
    }
}

内容的提问来源于stack exchange,提问作者Luigino

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 16:40:41