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 地址的

Android 获取网卡ip地址(静态+动态模式,解决有时获取到 IPV6 地址问题)_第1张图片

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 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;
    }

你可能感兴趣的:(Android,笔记相关)