You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET MAUI获取Android/iOS设备IP地址首次启动有效后续失效问题

问题背景

使用.NET MAUI开发Android端应用,目标框架为net6.0-android,测试设备为三星S10+(运行Android 12),需要实现获取设备IP地址的功能。
现有实现存在稳定复现的异常:应用首次启动时可正常获取IP,后续启动均无法获取正确地址,必须重启手机才能恢复。
原有实现代码如下:

private void GetIPAddressClicked(object sender, EventArgs e)
{

    string interfaceDescription = string.Empty;
    var result = new List<IPAddress>();
    try
    {
        var upAndNotLoopbackNetworkInterfaces = NetworkInterface.GetAllNetworkInterfaces().Where(n => n.NetworkInterfaceType != NetworkInterfaceType.Loopback
                                                                                                      && n.OperationalStatus == OperationalStatus.Up);

        foreach (var networkInterface in upAndNotLoopbackNetworkInterfaces)
        {
            var iPInterfaceProperties = networkInterface.GetIPProperties();

            var unicastIpAddressInformation = iPInterfaceProperties.UnicastAddresses.FirstOrDefault(u => u.Address.AddressFamily == AddressFamily.InterNetwork);
            if (unicastIpAddressInformation == null) continue;

            result.Add(unicastIpAddressInformation.Address);

            interfaceDescription += networkInterface.Description + "---";
        }
    }
    catch (Exception ex)
    {
        Debug.WriteLine($"Unable to find IP: {ex.Message}");
    }
    finally
    {
        string allIpInfo = string.Empty;
        foreach (var item in result)
        {
            allIpInfo += item.ToString() + "---";
        }
        IPAddress.Text = allIpInfo;

        InterfaceName.Text = interfaceDescription;
    }
}

两种场景的返回结果:

  • 正常运行(首次启动):
    • interfaceDescription = "------"
    • allIpInfo = "192.168.50.112---127.0.0.1---"
  • 异常运行(非首次启动):
    • interfaceDescription = "rmnet_data0"
    • allIpInfo = "192.0.0.2"
问题根因

原有实现存在三个核心缺陷,导致高版本Android上获取结果不稳定:

  1. 接口类型过滤逻辑完全不可靠:Android系统存在大量虚拟网卡、系统预留网卡,NetworkInterfaceType枚举对这些接口的识别不准,既无法完全过滤回环接口(正常返回里包含127.0.0.1就是证据),也会把移动数据虚拟接口rmnet_data0误判为有效接口。
  2. IP有效性校验缺失:异常返回的192.0.0.2属于192.0.0.0/24段,是Android系统用于captive portal(网络连通性检测)的内部预留地址,根本不是设备的真实局域网/公网IP;除此之外回环地址、链路本地地址(169.254段)都属于无效地址,原有逻辑完全没有过滤。
  3. 取数逻辑依赖接口枚举顺序:原有代码用FirstOrDefault取第一个匹配的IPv4地址,而Android系统枚举网络接口的顺序不固定,首次启动时WiFi接口排序靠前可以拿到正确IP,后续启动时移动虚拟接口排序靠前就会拿到无效地址。同时NetworkInterface.GetAllNetworkInterfaces()在Android 12及以上版本不会主动关联当前活跃网络,会返回所有系统存在的接口,包含大量无用的预留接口。
修复方案

第一步:补全权限

在Android项目的AndroidManifest.xml中添加必要权限:

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

第二步:替换获取逻辑

优先通过Android原生ConnectivityManager获取当前真正处于活跃连通状态的网络,再从对应网络属性中提取IP,同时增加严格的IP有效性校验,兜底逻辑保留网卡枚举但增加接口类型过滤。
修复后的完整代码如下:

private void GetIPAddressClicked(object sender, EventArgs e)
{
    string interfaceDescription = string.Empty;
    var result = new List<IPAddress>();
    try
    {
        // IP有效性校验规则:过滤所有系统预留、无实际通信意义的IPv4地址
        bool IsValidIp(IPAddress ip)
        {
            if (ip.AddressFamily != AddressFamily.InterNetwork) return false;
            byte[] ipBytes = ip.GetAddressBytes();
            // 过滤127.0.0.0/8 回环地址
            if (ipBytes[0] == 127) return false;
            // 过滤169.254.0.0/16 链路本地自动分配地址
            if (ipBytes[0] == 169 && ipBytes[1] == 254) return false;
            // 过滤192.0.0.0/24 系统连通性检测预留地址
            if (ipBytes[0] == 192 && ipBytes[1] == 0 && ipBytes[2] == 0) return false;
            return true;
        }

#if ANDROID
        // Android平台优先通过系统服务获取当前活跃网络,避免枚举无效虚拟网卡
        var connectivityManager = (ConnectivityManager)Platform.CurrentActivity
            .GetSystemService(Android.Content.Context.ConnectivityService);
        Network activeNetwork = connectivityManager.ActiveNetwork;
        if (activeNetwork != null)
        {
            LinkProperties linkProps = connectivityManager.GetLinkProperties(activeNetwork);
            if (linkProps != null)
            {
                foreach (LinkAddress addr in linkProps.LinkAddresses)
                {
                    if (addr.Address is Inet4Address ipv4Addr)
                    {
                        IPAddress ip = IPAddress.Parse(ipv4Addr.HostAddress);
                        if (IsValidIp(ip))
                        {
                            result.Add(ip);
                            interfaceDescription += linkProps.InterfaceName + "---";
                        }
                    }
                }
            }
        }
#endif
        // 平台逻辑获取失败时,兜底枚举网卡,增加严格过滤
        if (result.Count == 0)
        {
            var validInterfaces = NetworkInterface.GetAllNetworkInterfaces()
                .Where(n => n.OperationalStatus == OperationalStatus.Up)
                // 仅保留真实物理/拨号接口:WiFi、有线以太网、移动数据PPP接口,过滤虚拟网卡
                .Where(n => n.NetworkInterfaceType is NetworkInterfaceType.Wireless80211 
                    or NetworkInterfaceType.Ethernet 
                    or NetworkInterfaceType.Ppp);

            foreach (NetworkInterface iface in validInterfaces)
            {
                IPInterfaceProperties ipProps = iface.GetIPProperties();
                foreach (UnicastIPAddressInformation unicastAddr in ipProps.UnicastAddresses)
                {
                    if (IsValidIp(unicastAddr.Address))
                    {
                        result.Add(unicastAddr.Address);
                        interfaceDescription += iface.Description + "---";
                    }
                }
            }
        }
    }
    catch (Exception ex)
    {
        Debug.WriteLine($"获取IP失败: {ex.Message}");
    }
    finally
    {
        string allIpInfo = result.Any() ? string.Join("---", result.Select(ip => ip.ToString())) + "---" : string.Empty;
        IPAddress.Text = allIpInfo;
        InterfaceName.Text = interfaceDescription;
    }
}

补充说明

  • 上述方法获取的是设备当前网络下的局域网IP,如果需要获取设备的公网出口IP,无法通过本地接口枚举得到,必须通过公网HTTP服务查询获取。
  • 不要使用FirstOrDefault直接取第一个匹配的IP,部分场景下设备可能同时连接多个有效网络(比如同时连WiFi和有线网),需要根据业务场景选择对应IP。

内容的提问来源于stack exchange,提问作者Owen Lee

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.31 10:18:17