Android,在网络共享和连接到接入点时检测WiFi的本地IP和子网掩码

我需要在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)。 我错过了什么?

我现在找到的最佳解决方案:

令我感到困惑的是,关于网络共享的信息/界面是如此繁琐/隐藏得到,但是当你从WifiManagerConnectivityManager获取Wifi类型的信息WifiManager没有考虑到:这一切都只适用于WifiManager网络共享中。 我实际上已经失去了那个调查分支。

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

在实验上,Android似乎足够聪明,可以为外部移动网络的网络接口设置为空广播 。 它实际上很有意义,因为Android默默地丢弃涉及外部移动网络的UDP广播。

  // This works both in tethering and when connected to an Access Point Enumeration 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 } } 

对于子网掩码, getNetworkPrefixLength()的结果可以强制转换为子网掩码。 我直接使用了getBroadcast() ,因为这是我的最终目标。

此代码似乎不需要特殊权限(没有ACCESS_WIFI_STATE也没有NETWORK ,只有INTERNET )。

代码段的主要参考: http : //enigma2eureka.blogspot.it/2009/08/finding-your-ip-v4-broadcast-address.html