Android 获取网卡ip地址(静态+动态模式,解决有时获取到 IPV6 地址问题)
·
网上搜索得到的大多方法都是如下方式
添加权限
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
常规方法
public static String getIpAddress() {
try {
NetworkInterface networkInterface;
InetAddress inetAddress;
for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements(); ) {
networkInterface = en.nextElement();
for (Enumeration<InetAddress> enumIpAddr = networkInterface.getInetAddresses(); enumIpAddr.hasMoreElements(); ) {
inetAddress = enumIpAddr.nextElement();
Log.i("LogUtil","inetAddress=="+inetAddress.getHostAddress());
if (!inetAddress.isLoopbackAddress() && !inetAddress.isLinkLocalAddress()) {
return inetAddress.getHostAddress();
}
}
}
return "";
} catch (SocketException ex) {
ex.printStackTrace();
return "";
}
}
此种方法经我测试当以太网设置为 静态IP 时,获取的 ip 地址为 ipv6 格式(当然首先你的路由器首先得支持 ipv6),这样对于我们常见的 ping 包操作或者上报服务器 ip地址就会有错误的风险
通过翻看 Android 系统的 Setting 源码,查看系统是如何获取 ip 地址的

packages\apps\MtkSettings\src\com\android\settings\deviceinfo\Status.java
packages\apps\MtkSettings\src\com\android\settings\Utils.java
private void setIpAddressStatus() {
String ipAddress = Utils.getDefaultIpAddresses(this.mCM);
if (ipAddress != null) {
mIpAddress.setSummary(ipAddress);
} else {
mIpAddress.setSummary(mUnavailable);
}
}
/**
* Returns the default link's IP addresses, if any, taking into account IPv4 and IPv6 style
* addresses.
* @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;
}
直接将上述的两个静态方法复制出来你会发现 getActiveLinkProperties() 和 getAllAddresses() 方法都是 hide 的,我们可以通过反射来调用他们
修改后
public static String getDefaultIpAddresses(Context mContext) {
ConnectivityManager cm = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
//LinkProperties prop = cm.getActiveLinkProperties();
LinkProperties prop = null;
String addres = null;
try {
prop = (LinkProperties) cm.getClass().getMethod("getActiveLinkProperties").invoke(cm);
addres = formatIpAddresses(prop);
}catch (Exception e) {
e.printStackTrace();
}
return addres;
}
private static String formatIpAddresses(LinkProperties prop) throws NoSuchMethodException,
InvocationTargetException, IllegalAccessException {
if (prop == null) return null;
//Iterator<InetAddress> iter = prop.getAllAddresses().iterator();
List<InetAddress> addressesList = (List<InetAddress>) prop.getClass().getMethod("getAllAddresses").invoke(prop);
Iterator<InetAddress> iter = addressesList.iterator();
// If there are no entries, return null
if (!iter.hasNext()) return null;
// Concatenate all available addresses, comma separated
String addresses = "";
while (iter.hasNext()) {
InetAddress inetAddress = iter.next();
//过滤 ipv6 的地址
if (inetAddress instanceof Inet4Address && !inetAddress.isLoopbackAddress() && !inetAddress.isLinkLocalAddress()) {
LogUtils.d("inetAddress=="+inetAddress.getHostAddress());
addresses = inetAddress.getHostAddress();
break;
}
//addresses += iter.next().getHostAddress();
//if (iter.hasNext()) addresses += "\n";
}
LogUtils.d("addresses=="+addresses);
return addresses;
}
更多推荐



所有评论(0)