Java Android,检测WiFi的本地IP和子网掩码,同时连接到接入点

Java Android,检测WiFi的本地IP和子网掩码,同时连接到接入点,java,android,networking,wifi,netmask,Java,Android,Networking,Wifi,Netmask,我需要在Android设备上检测WiFi网络上的本地IP地址和子网掩码(以便严格计算本地子网的UDP广播地址) 当设备连接到接入点时,以下各项正常工作: // Only works when NOT tethering WifiManager wifi = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); DhcpInfo dhcp = wifi.getDhcpInfo(); if (dhcp == null)

我需要在Android设备上检测WiFi网络上的本地IP地址和子网掩码(以便严格计算本地子网的UDP广播地址)

当设备连接到接入点时,以下各项正常工作:

// Only works when NOT tethering
WifiManager wifi = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);

DhcpInfo dhcp = wifi.getDhcpInfo();
if (dhcp == null)
    throw new IOException("No DHCPInfo on WiFi side.");

foo(dhcp.ipAddress, dhcp.netmask);
但当android设备通过连接提供接入点时,它就不起作用:当android设备是它的客户端时,DhcpInfo似乎包含DCHP服务器设置的信息,而不是当android设备本身提供DHCP服务时。在栓系中,我能找到的最有希望的解决方案是:

// No way to get subnet mask
WifiManager wifi = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);

WifiInfo info = wifi.getConnectionInfo();
if (info == null)
   throw new IOException("No connection info on WiFi side.");

foo(info.getIpAddress(), info.??? /* netmask*/ );
编辑:错误,在我的测试中,即使这样也只能在不系留的情况下工作。在栓系时,IP始终为0

但是没有什么比WifiInfo.getNetMask()更好的了,在这种情况下,我如何获得子网掩码?(这种缺席让我觉得很奇怪,因为那里有太多的其他信息。我是否遗漏了一些明显的信息?)

另外,理想情况下,我想要一个解决方案,它不需要区分Android设备是否提供栓系,并且在任何情况下都只需要在WiFi网络上获取本地IP地址和子网掩码,无论是在Android设备提供栓系时还是在接入点的客户端


即使是标准Java(即非特定于Android的)
NetworkInterface.getNetworkInterfaces()
,似乎也无法获取子网掩码(除了不允许区分哪个对应于WiFi)。我遗漏了什么?

目前我找到的最佳解决方案:

让我困惑的是,当您从
WifiManager
ConnectivityManager
获取Wifi类型的信息时,如何获取有关栓系的信息/接口如此繁琐/隐藏,但却未将其考虑在内:这一切仅在不在栓系中时才起作用。事实上,我被调查部门弄丢了

目前我找到的最佳解决方案是使用标准Java
NetworkInterface.getNetworkInterfaces()
,而不是任何Android API

从实验上看,安卓似乎足够聪明,可以将外部移动网络的网络接口设置为空广播。这实际上很有意义,因为Android会悄悄地删除涉及外部移动网络的UDP广播

    // This works both in tethering and when connected to an Access Point

    Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();

    while (interfaces.hasMoreElements()) 
    {
        NetworkInterface networkInterface = interfaces.nextElement();

        if (networkInterface.isLoopback())
            continue; // Don't want to broadcast to the loopback interface

        for (InterfaceAddress interfaceAddress : networkInterface.getInterfaceAddresses()) 
        {
                InetAddress broadcast = interfaceAddress.getBroadcast();

                // InetAddress ip = interfaceAddress.getAddress();                  
                // interfaceAddress.getNetworkPrefixLength() is another way to express subnet mask

                // Android seems smart enough to set to null broadcast to
                //  the external mobile network. It makes sense since Android
                //  silently drop UDP broadcasts involving external mobile network.
                if (broadcast == null)
                    continue;

                ... // Use the broadcast                
        }
    }
//这在栓系和连接到接入点时都有效
枚举接口=NetworkInterface.getNetworkInterfaces();
while(interfaces.hasMoreElements())
{
NetworkInterface NetworkInterface=interfaces.nextElement();
if(networkInterface.isLoopback())
continue;//不希望广播到环回接口
对于(InterfaceAddress InterfaceAddress:networkInterface.GetInterfaceAddress())
{
InetAddress广播=interfaceAddress.getBroadcast();
//InetAddress ip=interfaceAddress.getAddress();
//getNetworkPrefixLength()是表示子网掩码的另一种方法
//Android似乎足够聪明,可以将广播设置为空
//外部移动网络。自从安卓以来,它是有意义的
//静默删除涉及外部移动网络的UDP广播。
如果(广播==null)
继续;
…//使用广播
}
}
对于子网掩码,
getNetworkPrefixLength()
的结果可以强制为子网掩码。我直接使用了
getBroadcast()
,因为这是我的最终目标

此代码似乎不需要特殊权限(无
访问WIFI\u状态
网络
,只需
互联网


代码片段的主要参考:

请将您的解决方案作为您自己问题的答案发布()。然后将其标记为已接受答案。这将帮助其他UISER更快地找到解决方案。如果有更好的解决方案,您可以随时更新答案,或者发布第二个答案并将其标记为有效答案。这将保留有关旧版本的信息。完成。谢谢你的提示。