Goz*_*Man 4 java networking android netmask wifi
我需要在 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);
Run Code Online (Sandbox Code Playgroud)
但当 Android 设备通过网络共享提供接入点时,它不起作用:当 Android 设备是 DCHP 服务器的客户端时,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*/ );
Run Code Online (Sandbox Code Playgroud)
编辑:错误,在我的测试中,即使这仅在不网络共享时才有效。绑定时 IP 始终为 0。
但是没有什么WifiInfo.getNetMask(),在这种情况下我怎样才能获得子网掩码?(这种缺席让我觉得非常奇怪,因为那里还有大量其他信息。我是否遗漏了一些明显的东西?)
另外,理想情况下,我想要一个不需要区分 Android 设备是否提供网络共享的解决方案,并且只需在 WiFi 网络上获取本地 IP 地址和子网掩码,无论如何,无论 Android 设备是接入点的提供者或客户端。
即使是标准的Java(即不是Android特定的)NetworkInterface.getNetworkInterfaces(),似乎也没有办法获取子网掩码(除了不允许区分与WiFi相对应的子网掩码)。我缺少什么?
我目前找到的最佳解决方案:
WifiManager让我感到困惑的是,有关网络共享的信息/界面如何获取起来如此麻烦/隐藏,但当您从或ConnectivityManagerWifi 类型获取信息时却没有考虑到:这一切仅在不处于网络共享时才有效。我实际上迷失了那个调查部门。
目前我发现的最佳解决方案是使用标准 Java NetworkInterface.getNetworkInterfaces(),而不是任何 Android API。
从实验来看,Android 似乎足够聪明,可以将外部移动网络的网络接口设置为空广播。这实际上很有意义,因为 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
}
}
Run Code Online (Sandbox Code Playgroud)
对于子网掩码,可以将结果getNetworkPrefixLength()强制转换为子网掩码。我getBroadcast()直接使用,因为那是我的最终目标。
此代码似乎不需要特殊权限(也不ACCESS_WIFI_STATE是NETWORK,只是INTERNET)。
代码片段的主要参考:http://enigma2eureka.blogspot.it/2009/08/finding-your-ip-v4-broadcast-address.html
| 归档时间: |
|
| 查看次数: |
5508 次 |
| 最近记录: |