获取我的Android设备的wifi IP地址

49

当我的手机连接到Wi-Fi时,我该如何获取它的IP地址?

我在这里发现了一个方法(链接),但是它返回的是类似于24.182.239.255这样的东西,即使我在Wi-Fi下也是如此,而我期望的是类似于192.168.1.10这样的东西。

我希望得到类似以下的结果:

if (you are under wifi)
    String ip4 = getWifiIP()
else
    String ip4 = getIPAddress with the method linked before

非常感谢!


你似乎期望获取私有IP地址。这个链接可能对你有帮助:https://dev59.com/l2025IYBdhLWcg3wVkif - siddharthsn
9个回答

81

需要考虑的一点是,Formatter.formatIpAddress(int) 已被弃用:

此方法在API级别12中已弃用。 使用 getHostAddress(),它支持IPv4和IPv6地址。该方法不支持IPv6地址。

因此,在长期解决方案方面,使用 formatIpAddress(int) 可能并不是一个好选择,尽管它可以正常工作。

如果你想要获取WiFi接口的IP地址,这里有一个潜在的解决方案:

protected String wifiIpAddress(Context context) {
    WifiManager wifiManager = (WifiManager) context.getSystemService(WIFI_SERVICE);
    int ipAddress = wifiManager.getConnectionInfo().getIpAddress();

    // Convert little-endian to big-endianif needed
    if (ByteOrder.nativeOrder().equals(ByteOrder.LITTLE_ENDIAN)) {
        ipAddress = Integer.reverseBytes(ipAddress);
    }

    byte[] ipByteArray = BigInteger.valueOf(ipAddress).toByteArray();

    String ipAddressString;
    try {
        ipAddressString = InetAddress.getByAddress(ipByteArray).getHostAddress();
    } catch (UnknownHostException ex) {
        Log.e("WIFIIP", "Unable to get host address.");
        ipAddressString = null;
    }

    return ipAddressString;
}

如前面的回复所述,您需要在AndroidManifest.xml中设置以下内容:

<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />

请注意,这只是一个示例解决方案。 您应该花时间检查空值等等,以确保用户体验顺畅。

具有讽刺意味的是,一方面Google正在淘汰formatIpAddress(int),但仍然使用getIpAddress()返回整数值。 IP地址作为整数也排除了它符合IPv6的可能性。

接下来的问题是大小端可能会成为问题,也可能不是问题。 我只测试过三个设备,它们都是小端。尽管我们在虚拟机中运行,但硬件可能会出现大小端的差异。因此,为了安全起见,我在代码中添加了一个大小端检查。

getByAddress(byte[])似乎希望整数值为大端。 从研究中发现,网络字节序是大端。 这很有道理,因为像192.168.12.22这样的地址是一个大端数字。


请查看HammerNet GitHub项目。 它实现了上面的代码以及一堆健全性检查,处理AVD的默认值的能力,单元测试以及其他功能。 我不得不为我的应用程序实施这个库,并决定开源它。


无法在Android Studio中导入BigInteger,我知道这很奇怪,但确实发生了。 - 10101010
3
端序转换对于Nexus 5和更多设备实际上非常重要。谢谢! - Danpe
1
WifiManager wifiManager = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE)。这样还是稍微好一点。 - Greelings
这会导致反向IP地址...还有其他人吗? - ElliotM
@ElliotM 不,结果是一个正确的可读性强的IP地址。你是在特定/奇异设备上进行测试的吗? - Darkendorf
@Darkendorf 是的 - ElliotM

51

如果你想获取设备连接到Wi-Fi时的私有IP地址,可以尝试以下方法。

WifiManager wifiMgr = (WifiManager) getSystemService(WIFI_SERVICE);
WifiInfo wifiInfo = wifiMgr.getConnectionInfo();
int ip = wifiInfo.getIpAddress();
String ipAddress = Formatter.formatIpAddress(ip);

一定要添加权限

<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />

到您的清单。


15
formatIpAddress()已经被弃用。请参考Digital Rounin的解决方案,改用InetAddress.getHostAddress()。 - Emmanuel
1
仅适用于新手:应该是getSystemService(Context.WIFI_SERVICE)。 - 10101010
字节序是一个重要的考虑因素,上述代码将在小端硬件上返回反转的IP地址。请查看Digital Rounin的答案以获取正确的方法。或者访问https://dev59.com/l4rda4cB1Zd3GeqPKEWv以获取更简短的方法(该方法以正确的顺序返回IP地址作为整数)。 - Abraham Philip
请看我以下的答案。它将获取活动链接的IP地址,无论是WiFi还是移动网络。 - Yong
感谢您的回答,它也帮助我解决了我的问题。我正在寻找相同的答案,但是使用Cordova。要使用Cordova获取设备的IP地址,请尝试使用以下模块:https://www.npmjs.com/package/cordova-plugin-android-wifi-manager - user3067533

8
这将为您获取WiFi的IPv4、IPv6或两者。
public static Enumeration<InetAddress> getWifiInetAddresses(final Context context) {
    final WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
    final WifiInfo wifiInfo = wifiManager.getConnectionInfo();
    final String macAddress = wifiInfo.getMacAddress();
    final String[] macParts = macAddress.split(":");
    final byte[] macBytes = new byte[macParts.length];
    for (int i = 0; i< macParts.length; i++) {
        macBytes[i] = (byte)Integer.parseInt(macParts[i], 16);
    }
    try {
        final Enumeration<NetworkInterface> e =  NetworkInterface.getNetworkInterfaces();
        while (e.hasMoreElements()) {
            final NetworkInterface networkInterface = e.nextElement();
            if (Arrays.equals(networkInterface.getHardwareAddress(), macBytes)) {
                return networkInterface.getInetAddresses();
            }
        }
    } catch (SocketException e) {
        Log.wtf("WIFIIP", "Unable to NetworkInterface.getNetworkInterfaces()");
    }
    return null;
}

@SuppressWarnings("unchecked")
public static<T extends InetAddress> T getWifiInetAddress(final Context context, final Class<T> inetClass) {
    final Enumeration<InetAddress> e = getWifiInetAddresses(context);
    while (e.hasMoreElements()) {
        final InetAddress inetAddress = e.nextElement();
        if (inetAddress.getClass() == inetClass) {
            return (T)inetAddress;
        }
    }
    return null;
}

使用方法:

final Inet4Address inet4Address = getWifiInetAddress(context, Inet4Address.class);
final Inet6Address inet6Address = getWifiInetAddress(context, Inet6Address.class);

不要忘记:

<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />

7

发现了一个好的答案,https://gist.github.com/stickupkid/1250733

WifiManager wifiManager = (WifiManager) getSystemService(WIFI_SERVICE);
WifiInfo wifiInfo = wifiManager.getConnectionInfo();
int ipAddress = wifiInfo.getIpAddress();
String ipString = String.format(“%d.%d.%d.%d”, (ip & 0xff), (ip >> 8 & 0xff), (ip >> 16 & 0xff), (ip >> 24 & 0xff));

我无法编辑它,因为它少于6个字符,所以对于任何尝试这样做的人:你必须用普通引号替换String.format中的引号。 - Bowi

3
根据我的崩溃日志,似乎并非每个设备都返回WiFi mac地址。
以下是最常见回复的简化版本。
final WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
final ByteBuffer byteBuffer = ByteBuffer.allocate(4);
byteBuffer.order(ByteOrder.LITTLE_ENDIAN);
byteBuffer.putInt(wifiInfo.getIpAddress());
try {
final InetAddress inetAddress = InetAddress.getByAddress(null, byteBuffer.array());
} catch (UnknownHostException e) {
    //TODO: Return null?
}

缺少WifiInfo wifiInfo = wifiManager.getConnectionInfo(); - Java42

1
如果终端中已安装adb,则执行以下操作:

Runtime.getRuntime.exec("adb", "shell", "getprop", "dhcp.wlan0.ipaddress");

由于:java.io.IOException: 无法运行程序 "adb":error=2,没有那个文件或目录。 - Vsevolod
安装Android SDK。 - Thejus Krishna
在哪里?在智能手机上吗?在电脑上没有SDK是不可能编译应用程序的。 - Vsevolod

0

添加以下权限。

 <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />

在onCreate中初始化WifiManager。

 WifiManager wifiMgr = (WifiManager) getContext().getSystemService(context.WIFI_SERVICE);

请使用以下函数。
 public void WI-FI_IP() {
    WifiInfo wifiInfo = wifiMgr.getConnectionInfo();
    int ip = wifiInfo.getIpAddress();
    String ipAddress = Formatter.formatIpAddress(ip);
    }

0
以下代码来自AOSP设置。它获取活动链接的IP,无论是wifi还是移动网络。这是最常见的方法。

http://androidxref.com/8.0.0_r4/xref/packages/apps/Settings/src/com/android/settings/deviceinfo/Status.java#251

/**  
 * Returns the default link's IP addresses, if any, taking into account IPv4 and IPv6 style
 * addresses.
 * @param context the application context
 * @return the formatted and newline-separated IP addresses, or null if none.
 */
public static String getDefaultIpAddresses(ConnectivityManager cm) {                                                                      
    LinkProperties prop = cm.getActiveLinkProperties();
    return formatIpAddresses(prop);
}    

private static String formatIpAddresses(LinkProperties prop) {
    if (prop == null) return null;
    Iterator<InetAddress> iter = prop.getAllAddresses().iterator();
    // If there are no entries, return null
    if (!iter.hasNext()) return null;
    // Concatenate all available addresses, comma separated
    String addresses = "";
    while (iter.hasNext()) {
        addresses += iter.next().getHostAddress();
        if (iter.hasNext()) addresses += "\n";
    }
    return addresses;
}

-1

Formatter.formatIpAddress(int)已被弃用:

WifiManager wm = (WifiManager) getSystemService(WIFI_SERVICE);
String ipAddress = BigInteger.valueOf(wm.getDhcpInfo().netmask).toString();

是的,它不支持IPv6。 - aclowkay

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接