首页 文章

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

提问于
浏览
3

我需要在Android设备上检测WiFi网络上的本地IP地址 and subnet mask (为了正确计算本地子网的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*/ );

EDIT :错误,在我的测试中,即使这只适用于不绑定 . 绑定IP始终为0 .

但是没有什么像 WifiInfo.getNetMask() ,在这种情况下如何获得子网掩码? (这种缺席让我觉得非常奇怪,因为那里有太多的其他信息 . 我错过了一些明显的东西吗?)

此外,理想情况下,我想要一个解决方案,无论是Android设备是提供网络共享还是无需区分,只需获取WiFi网络上的本地IP地址和子网掩码,无论如何,当Android设备是提供接入点或客户端 .

即使是标准的Java(即不是特定于Android的) NetworkInterface.getNetworkInterfaces() ,似乎也没有办法获得子网掩码(除了不允许区分哪个对应于WiFi) . 我错过了什么?

1 回答

  • 4

    Best solution I found at the moment:

    令我感到困惑的是,关于网络共享的信息/界面是如此繁琐/隐藏得到,但是当你从 WifiManagerConnectivityManager 获取Wifi类型的信息时却没有考虑到:它只在不在网络共享时起作用 . 我实际上已经失去了那个调查分支 .

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

    Experimentally, Android seems smart enough to set to null broadcast for network interfaces to the external mobile network . 它实际上很有意义,因为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                
            }
        }
    

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

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

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

相关问题