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

Android中获取WiFi已连接设备IP地址的方法求助(附尝试代码)

Android 获取同WiFi网络下已连接设备IP的解决方案

原代码存在的问题

  1. 废弃API使用:Formatter.formatIpAddress已被官方废弃,高版本Android系统中可能无法正常工作
  2. 主线程阻塞:在UI线程中执行isReachable扫描操作,会直接导致ANR(应用无响应)
  3. 扫描逻辑缺陷:未排除自身IP,且isReachable依赖ICMP请求,部分设备可能禁用ICMP但实际在线
  4. 权限缺失:未声明必要的网络/位置权限,导致无法获取WiFi信息或执行网络扫描
  5. 用户体验差:频繁弹出Toast会严重干扰正常操作

实现步骤及修正代码

1. 声明必要权限

在AndroidManifest.xml中添加权限配置:

<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!-- Android 6+ 需动态申请位置权限 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

注:Android 10及以上版本,扫描WiFi设备必须获取位置权限,需动态申请

2. 修正IP地址转换方法

替换废弃的Formatter.formatIpAddress,用InetAddress实现标准IP转换:

private String getLocalIpAddress(WifiManager wifiManager) {
    WifiInfo wifiInfo = wifiManager.getConnectionInfo();
    int ipInt = wifiInfo.getIpAddress();
    byte[] ipBytes = new byte[]{
            (byte) (ipInt & 0xff),
            (byte) ((ipInt >> 8) & 0xff),
            (byte) ((ipInt >> 16) & 0xff),
            (byte) ((ipInt >> 24) & 0xff)
    };
    try {
        return InetAddress.getByAddress(ipBytes).getHostAddress();
    } catch (UnknownHostException e) {
        e.printStackTrace();
        return null;
    }
}

3. 异步执行扫描任务

使用线程池执行扫描逻辑,避免阻塞主线程:

private void scanConnectedDevices() {
    WifiManager wifiManager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
    String localIp = getLocalIpAddress(wifiManager);
    if (localIp == null) {
        Toast.makeText(this, "无法获取本地IP", Toast.LENGTH_SHORT).show();
        return;
    }

    String ipPrefix = localIp.substring(0, localIp.lastIndexOf(".") + 1);
    String selfIp = localIp;

    // 用线程池并行扫描,提高效率
    ExecutorService executor = Executors.newFixedThreadPool(10);
    List<Future<?>> futures = new ArrayList<>();

    for (int i = 1; i <= 254; i++) {
        final String testIp = ipPrefix + i;
        // 跳过自身IP
        if (testIp.equals(selfIp)) continue;

        futures.add(executor.submit(() -> {
            try {
                InetAddress address = InetAddress.getByName(testIp);
                // 优先用TCP连接检测(端口80),再回退到ICMP,提高准确性
                boolean isReachable = isHostReachable(testIp, 80, 1000) || address.isReachable(1000);
                if (isReachable) {
                    String hostName = address.getCanonicalHostName();
                    // 回到UI线程更新数据
                    runOnUiThread(() -> {
                        ipAddressArray.add(testIp);
                        Log.i("wifi => ", "在线设备: " + hostName + "(" + testIp + ")");
                        Toast.makeText(MainActivity.this, "发现在线设备: " + testIp, Toast.LENGTH_SHORT).show();
                    });
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }));
    }

    // 扫描完成后关闭线程池
    executor.shutdown();
}

// TCP连接检测方法,解决部分设备不响应ICMP的问题
private boolean isHostReachable(String ip, int port, int timeout) {
    Socket socket = null;
    try {
        socket = new Socket();
        socket.connect(new InetSocketAddress(ip, port), timeout);
        return true;
    } catch (IOException e) {
        return false;
    } finally {
        if (socket != null) {
            try {
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

4. 动态申请权限(Android 6+)

调用扫描前检查并申请必要权限:

private static final int PERMISSION_REQUEST_CODE = 100;

private void checkPermissionsAndScan() {
    String[] permissions = {
            Manifest.permission.ACCESS_WIFI_STATE,
            Manifest.permission.INTERNET,
            Manifest.permission.ACCESS_FINE_LOCATION
    };

    List<String> needPermissions = new ArrayList<>();
    for (String perm : permissions) {
        if (ContextCompat.checkSelfPermission(this, perm) != PackageManager.PERMISSION_GRANTED) {
            needPermissions.add(perm);
        }
    }

    if (!needPermissions.isEmpty()) {
        ActivityCompat.requestPermissions(this, needPermissions.toArray(new String[0]), PERMISSION_REQUEST_CODE);
    } else {
        scanConnectedDevices();
    }
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == PERMISSION_REQUEST_CODE) {
        boolean allGranted = true;
        for (int result : grantResults) {
            if (result != PackageManager.PERMISSION_GRANTED) {
                allGranted = false;
                break;
            }
        }
        if (allGranted) {
            scanConnectedDevices();
        } else {
            Toast.makeText(this, "权限不足,无法扫描设备", Toast.LENGTH_SHORT).show();
        }
    }
}

实现效果

  1. 兼容高版本Android系统,能正确获取本地WiFi IP地址
  2. 异步扫描避免UI阻塞,彻底解决ANR问题
  3. 结合TCP+ICMP检测,大幅提高在线设备识别准确率
  4. 自动排除自身IP,避免无效数据
  5. 权限流程合规,符合Android系统权限要求

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 22:05:26