核心概念
在开始之前,先明确几个关键概念:

- IP 地址:设备在网络中的唯一标识,分为 IPv4(如
168.1.101)和 IPv6`(如2001:0db8:85a3:0000:0000:8a2e:0370:7334),Android 开发中需要同时兼容两者。 - Wi-Fi 和移动数据:Android 设备可以通过多种方式连接网络,最常见的是 Wi-Fi 和移动蜂窝网络(如 4G/5G),获取 IP 地址时需要考虑当前活动的网络类型。
- 网络接口:设备上的每个网络连接(如 Wi-Fi、以太网)都是一个网络接口,每个接口都有自己的 IP 地址。
- 权限:从 Android 6.0 (API 23) 开始,部分网络相关权限需要动态请求,但获取本机 IP 地址不需要任何特殊权限。
如何获取本机设备的 IP 地址
获取本机 IP 地址是最常见的需求,通常用于网络调试、设备发现等场景。
获取 Wi-Fi IP 地址
这是最常用的场景,我们可以通过 WifiManager 来获取。
步骤:
-
添加权限:在
AndroidManifest.xml中声明ACCESS_WIFI_STATE权限。
(图片来源网络,侵删)<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
-
获取
WifiManager并查询 IP 地址:import android.content.Context; import android.net.wifi.WifiManager; import android.text.format.Formatter; // ... public String getWifiIpAddress(Context context) { WifiManager wifiManager = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE); if (wifiManager != null && wifiManager.isWifiEnabled()) { // 获取 WifiInfo 对象 android.net.wifi.WifiInfo wifiInfo = wifiManager.getConnectionInfo(); // 获取 IP 地址的整数表示 int ipAddress = wifiInfo.getIpAddress(); // 将整数 IP 地址格式化为字符串 (IPv4) return Formatter.formatIpAddress(ipAddress); } return "Wi-Fi is disabled or not available"; }
注意:
getIpAddress()返回的是一个int,168.1.101会被表示为整数3232235781。Formatter.formatIpAddress()会帮我们把它转换回点分十进制的字符串。- 这种方法只支持 IPv4,对于现代设备,如果连接的是 IPv6 网络,此方法将无法工作。
- 从 Android 10 (API 29) 开始,对非前台应用访问 Wi-Fi 信息有了更多限制,确保你的应用在前台时调用此方法或处理可能的
SecurityException。
获取移动数据 (蜂窝网络) IP 地址
获取移动网络的 IP 地址没有直接的 API,因为它通常由运营商动态分配,我们可以通过查询网络接口来实现。
使用 ConnectivityManager 和 Network API (推荐 - Android 7.0+)

这是现代 Android 开发推荐的方式,可以同时处理 IPv4 和 IPv6。
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
import android.os.Build;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Collections;
import java.util.List;
// ...
public String getMobileIpAddress(Context context) {
ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
if (connectivityManager == null) {
return "ConnectivityManager is null";
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// 获取当前活动的网络
Network network = connectivityManager.getActiveNetwork();
if (network == null) {
return "No active network";
}
// 获取网络能力
NetworkCapabilities capabilities = connectivityManager.getNetworkCapabilities(network);
if (capabilities == null || !capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
return "Not on a mobile network";
}
try {
// 从网络获取所有 IP 地址列表
List<InetAddress> addresses = Collections.list(network.getSocketFactory().getInetAddress());
for (InetAddress address : addresses) {
// 排回环地址 (127.0.0.1)
if (!address.isLoopbackAddress()) {
String hostAddress = address.getHostAddress();
// 确保返回的是 IPv4 或 IPv6 地址,而不是 % 后缀的接口名
if (hostAddress != null && (hostAddress.indexOf(':') < 0)) {
return hostAddress;
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
return "Unable to get mobile IP";
}
通用方法:获取当前活动网络的 IP 地址
我们可以将上述方法结合,写一个通用的方法来获取当前活动网络(无论是 Wi-Fi 还是移动数据)的 IP 地址。
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
import android.os.Build;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Collections;
import java.util.List;
// ...
public String getActiveNetworkIpAddress(Context context) {
ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
if (connectivityManager == null) {
return "ConnectivityManager is null";
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
Network network = connectivityManager.getActiveNetwork();
if (network == null) {
return "No active network";
}
try {
List<InetAddress> addresses = Collections.list(network.getSocketFactory().getInetAddress());
for (InetAddress address : addresses) {
if (!address.isLoopbackAddress()) {
String hostAddress = address.getHostAddress();
// 返回第一个非回环的 IP 地址
if (hostAddress != null) {
return hostAddress;
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
} else {
// 对于旧版本,可以尝试分别查询 Wi-Fi 和移动网络
// ... (略)
}
return "Unable to get IP";
}
如何获取远程服务器的 IP 地址
获取远程服务器的 IP 地址非常简单,就是标准的 Java 网络编程。
使用 InetAddress 类
import java.net.InetAddress;
import java.net.UnknownHostException;
// ...
public String getServerIpAddress(String domainName) {
try {
// 通过域名获取 IP 地址
InetAddress inetAddress = InetAddress.getByName(domainName);
// 获取主机地址 (IPv4 或 IPv6)
return inetAddress.getHostAddress();
} catch (UnknownHostException e) {
e.printStackTrace();
return "Unable to resolve host: " + domainName;
}
}
// 使用示例
String serverIp = getServerIpAddress("www.google.com");
Log.d("ServerIP", serverIp); // 输出类似: 142.250.199.100 或 2a00:1450:4001:80a::2004
高级主题:获取本机所有 IP 地址和 MAC 地址
有时候你可能需要获取设备所有网络接口的详细信息。
获取所有网络接口信息 (使用 NetworkInterface)
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Collections;
import java.util.List;
// ...
public void getAllNetworkInterfacesInfo() {
try {
List<NetworkInterface> networkInterfaces = Collections.list(NetworkInterface.getNetworkInterfaces());
for (NetworkInterface ni : networkInterfaces) {
// 排除虚拟接口
if (ni.isUp() && !ni.isLoopback()) {
byte[] macBytes = ni.getHardwareAddress();
if (macBytes != null) {
StringBuilder macString = new StringBuilder();
for (byte b : macBytes) {
macString.append(String.format("%02X:", b));
}
if (macString.length() > 0) {
macString.deleteCharAt(macString.length() - 1);
}
Log.d("NetworkInfo", "Name: " + ni.getName() + ", Display Name: " + ni.getDisplayName() + ", MAC: " + macString.toString());
}
List<InetAddress> inetAddresses = Collections.list(ni.getInetAddresses());
for (InetAddress inetAddress : inetAddresses) {
if (!inetAddress.isLoopbackAddress()) {
String ipHostAddress = inetAddress.getHostAddress();
// 筛选出 IPv4 或 IPv6
if (ipHostAddress.indexOf(':') < 0) { // IPv4
Log.d("NetworkInfo", "IPv4: " + ipHostAddress);
} else { // IPv6
Log.d("NetworkInfo", "IPv6: " + ipHostAddress);
}
}
}
}
}
} catch (SocketException e) {
e.printStackTrace();
}
}
获取 Wi-Fi MAC 地址
import android.content.Context;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
// ...
public String getWifiMacAddress(Context context) {
WifiManager wifiManager = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
if (wifiManager != null) {
WifiInfo info = wifiManager.getConnectionInfo();
if (info != null) {
return info.getMacAddress();
}
}
return "02:00:00:00:00:00"; // 如果获取失败,返回一个默认的 MAC 地址
}
⚠️ 重要提醒 (Android 10+):
从 Android 10 开始,为了增强用户隐私,系统会为所有应用随机化设备的 MAC 地址,除非你的应用被授予 ACCESS_FINE_LOCATION 权限并且位置服务已开启,在 Android 10 及以上版本,即使不请求位置权限,getMacAddress() 返回的也可能是随机地址或 02:00:00:00:00:00 这样的空地址,获取 MAC 地址的正确方式是请求位置权限。
常见问题与最佳实践
-
主线程网络操作:永远不要在主线程(UI 线程)上执行网络请求或 IP 查询等耗时操作,否则会抛出
NetworkOnMainThreadException,应使用AsyncTask、Thread、ExecutorService或现代的Coroutines/RxJava。 -
网络权限:
INTERNET:允许应用程序打开网络套接字,几乎所有网络应用都需要。ACCESS_NETWORK_STATE:允许应用程序查看网络状态,推荐用于检测网络连接变化。ACCESS_WIFI_STATE:允许应用程序访问 Wi-Fi 网络状态信息,如需获取 Wi-Fi 的 IP 或 MAC 地址,需要此权限。ACCESS_FINE_LOCATION:在 Android 10+ 上,获取真实的 Wi-Fi MAC 地址需要此权限和用户授权。
-
IPv6 的普及:新项目应默认支持 IPv6,使用
ConnectivityManager和NetworkAPI 可以很好地处理双栈网络,而旧的WifiManager方法仅支持 IPv4。 -
处理无网络情况:在获取 IP 之前,务必检查网络是否可用。
ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); Network activeNetwork = cm.getActiveNetwork(); NetworkCapabilities caps = cm.getNetworkCapabilities(activeNetwork); boolean isConnected = caps != null && (caps.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) || caps.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)); if (!isConnected) { // 处理无网络逻辑 }
| 需求 | 推荐方法 | 关键 API/类 | 备注 |
|---|---|---|---|
| 获取 Wi-Fi IPv4 | WifiManager |
WifiManager, WifiInfo, Formatter |
仅限 IPv4,旧方法。 |
| 获取活动网络 IP | ConnectivityManager + Network |
ConnectivityManager, Network, InetAddress |
现代推荐方法,支持 IPv4/IPv6。 |
| 获取服务器 IP | InetAddress |
InetAddress.getByName() |
标准 Java 网络编程。 |
| 获取 MAC 地址 | WifiManager (旧) 或 NetworkInterface (新) |
WifiInfo.getMacAddress(), NetworkInterface |
Android 10+ 需位置权限才能获取真实 MAC。 |
| 获取所有接口信息 | NetworkInterface |
NetworkInterface |
可用于调试,获取所有 IP 和 MAC。 |
希望这份详细的指南能帮助你更好地处理 Android 中的网络 IP 相关问题!
