获取本机开启热点、连接 WIFI 时的 IP

最近在做一个Android关于的无线局域网项目,需要获取本机在所连接局域网上的IP地址。手机可以通过WIFI连接已知的局域网,也可通过打开手机热点去组建一个局域网。

在通过WIFI连接局域网时,本机的 IP 地址可以通过 “ WifiManager ” 和“ WifiInfo ”获得,如下:

public static String getIP(Context context) {
        WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
        if (wifiManager.isWifiEnabled()) {
            // 若已经开启了 WIFI
            WifiInfo wifiInfo = wifiManager.getConnectionInfo();
            int ip = wifiInfo.getIpAddress();
            return (ip & 0xFF) + "." + ((ip >> 8) & 0xFF) + "." + ((ip >> 16) & 0xFF) + "." + ((ip >> 24) & 0xFF);
        } else {
            // 未打开 WIFI
            return null;
        }
    }

但是如果通过“便携式热点”的方式自己开启局域网时,本机的 IP 一时想不到方案怎么获取(上述方式就不管用了,因为手机开启热点后WIFI会被关闭)。终于通过这篇文章有了可行的解决办法:

Android 中获取本机热点ip地址_android 获取usb共享网络设备的ip-CSDN博客

大致的原理是通过遍历所有已知的网络接口,最后找到名为“ wlan0 ”(或“eth0”或“ap0”)的无线局域网接口即可。我通过下面代码大致输出了一下它的遍历结果(因为我的Android Studio不知道为什么在打 log 输出时,IP地址会显示为 “********”,因此我把‘.’ 替换成了 ‘@’,有知道的小伙伴告诉我一下,谢谢!):
 

public static InetAddress getApIpAddress2() {
    try {
        Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
        while (networkInterfaces.hasMoreElements()) {
            NetworkInterface networkInterface = networkInterfaces.nextElement();
            Log.d("test", "networkInterface: " + networkInterface.getDisplayName());
 
            // getInetAddresses
            Enumeration<InetAddress> ipAddresses = networkInterface.getInetAddresses();
            while (ipAddresses.hasMoreElements()) {
                InetAddress inetAddress = ipAddresses.nextElement();
                Log.d("test", "    inetAddress: " + inetAddress.toString().replace('.','@'));
            }
            // getInterfaceAddresses
            List<InterfaceAddress> interfaceAddressList = networkInterface.getInterfaceAddresses();
            for (InterfaceAddress interfaceAddress : interfaceAddressList) {
                Log.d("test", "    interfaceAddress: " + interfaceAddress.getAddress().toString().replace('.','@') + "   " + interfaceAddress.getNetworkPrefixLength());
            }
        }
    } catch (SocketException e) {
        e.printStackTrace();
    }
    return null;
}

上面的代码得到的结果是(此时我手机连上了另一台手机的热点):

可以看到,在名为“ wlan0 ”(或“eth0”或“ap0”)的网络接口中,找到了我所需要的 IP 地址甚至是网络前缀。但是同时也存在了一个 Ipv6 的输出(链路本地地址 LinkLocalAddress),这个我不需要,等一下在正式代码中我可以将其过滤掉。因此,结论: 找到DisplayName 为 “wlan0”(或“eth0”或“ap0”)的网络接口,再对 “wlan0”(或“eth0”或“ap0”)内的地址做过滤即可。
下面是正式代码:

public static String getApIpAddress2() {
    try {
        Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
        while (networkInterfaces.hasMoreElements()) {
            NetworkInterface networkInterface = networkInterfaces.nextElement();
            if (networkInterface.getDisplayName().contains("wlan0") ||
                        networkInterface.getDisplayName().contains("eth0") ||
                        networkInterface.getDisplayName().contains("ap0")) {
                // getInterfaceAddresses
                List<InterfaceAddress> interfaceAddressList = networkInterface.getInterfaceAddresses();
                for (InterfaceAddress interfaceAddress : interfaceAddressList) {
                    InetAddress inetAddress = interfaceAddress.getAddress();
                    if (!inetAddress.isLinkLocalAddress()) { // 过滤掉 链路本地地址
                        // 获取网络前缀(子网掩码)
                        int prefix = interfaceAddress.getNetworkPrefixLength();
                        // 输出:192.168.43.197/24
                        return inetAddress.toString().substring(1) + "/" + prefix;
                    }
                }
            }
        }
    } catch (SocketException e) {
        e.printStackTrace();
    }
    return null;
}

说明:

正式代码经过测试,可以获取到连接 WIFI 时本机的 IP 地址,也可以获取到作为热点源时 本机的 IP 地址。
代码中,返回时为什么要subString(1)呢?是因为InetAddress.toString()时会加上“/”,比如“/192.168.43.197”,因此需要将这个斜杠去掉。
什么原因结果会返回 null 呢?返回 null 是因为找不到 “wlan0”(或“eth0”或“ap0”),找不到“wlan0”(或“eth0”或“ap0”)大概率是因为没有打开 WIFI 或 热点。
上述代码只是从我观察到的现象来写出的,可靠性仍不清楚,比如对于不同手机中 “wlan0”的名字是否唯一、是否都叫这个名等等的不确定性,仍然需要结合实际去使用。本文只是记录一下这个方法而已😂。
若有其他的更好更可靠的方式的话,欢迎交流指导,同时本文若有错误,敬请各位指出,作为新人表示十分感谢!

————————————————
版权声明:本文为CSDN博主「养马的农民」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_45204138/article/details/133946381

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值