获取Android设备在运行时的IP地址,最可靠的方法是什么?不是公共IP。

9
我是一位帮助翻译文本的助手。以下是您需要翻译的内容:

我有一个应用程序,其中包含一个Web服务器,用户将从其家庭局域网访问该服务器。目前,我有两种获取设备IP的方法,我不知道哪种更可能是正确的。

我的正常方式:

  List<NetworkInterface> interfaces = Collections.list(NetworkInterface.getNetworkInterfaces());
        for (NetworkInterface intf : interfaces) {
            List<InetAddress> addrs = Collections.list(intf.getInetAddresses());
            for (InetAddress addr : addrs) {
                if (!addr.isLoopbackAddress()) {
                    String sAddr = addr.getHostAddress().toUpperCase();

我的替代方法:
        WifiInfo connectionInfo = wifiMgr.getConnectionInfo();
        int ip = connectionInfo.getIpAddress();

我认为这个问题一直运作良好,但是我有一些统计数据表明两个IP地址只有大约4%的时间是不同的。

另外,我刚刚在Chromebook上尝试了我的应用程序,发现备选方法实际上是正确的,而不是正常的方法。

那么,我如何知道哪种方法更好,或者是否有更好的替代方案?

5个回答

0

我正在使用以下方法从Android设备获取本地IP地址,它看起来对我很好:

public static String getLocalIpAddress() {
    try {
        for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) {
            NetworkInterface intf = en.nextElement();
            for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();) {
                InetAddress inetAddress = enumIpAddr.nextElement();
                if (!inetAddress.isLoopbackAddress() && inetAddress instanceof Inet4Address) {
                    return inetAddress.getHostAddress();
                }
            }
        }
    } catch (SocketException ex) {
        ex.printStackTrace();
    }
    return null;
} 

这个方式与您的常规方式几乎相同,但稍微改进了一下。希望这能帮到您!


我没有添加所有的代码,我确实检查了ipv4,而且我更喜欢像“wlan0”这样的东西,但至少在chromebook上,这里返回的IP地址都不正确。我猜现在已经没有正确答案了。 - casolorz

0

它们非常不可靠,因为你必须处理许多边缘情况。

我更喜欢使用免费的外部服务;进行网络调用并获取您的正确公共IP。尝试 https://www.ipify.org/


但我不需要公共IP,我需要用户局域网上的IP。 - casolorz
在这种情况下,也许这个能帮到你:https://dev59.com/l2025IYBdhLWcg3wVkif - terencey
所以他们用我主要的方法做,我可能很久以前就复制了他们的代码。但我仍然不知道那是否比我另外一种方式更可靠。 - casolorz

0

扫描网络接口肯定会返回各种结果。您可以从 intf.getName() 更多地了解,例如:

  • wlan0 上的 Wifi 连接
  • rmnet1 上的 3G/4G 连接
  • lo 上的环回 (127.0.0.1) - 您已经排除了这个
  • 某些 Chromebook 上可能有有线以太网连接 eth0

还有更多可能性,比如 VPN 连接。

如果可以安全地说您只想连接到 Wifi 连接上的 Web 服务器,则可以添加一个检查,检查接口名称是否以 wlan 开头,但对于这种情况,您的备选方案似乎更简单。

如果 Chromebook 上也可能有以太网连接,则 Web 服务器可能会在 wlan0eth0 上提供连接。要么从网络接口中选择首选连接,要么准备提供无线和有线 IP。


感谢这些网络名称。我已经在检查'wlan0'了,接下来会检查'eth'。关于Chromebook的问题,我认为是因为Android应用程序有点像模拟或其他什么原因,这就是为什么wifi管理器返回正确的信息而NetworkInterfaces不返回。我并不太想去处理Chromebook的情况,因为这是一个比较容易解决的问题,但其他一些奇怪的设备就需要更多的考虑了。 - casolorz

0
我建议你将IP相关的内容移到服务器/后端部分。这样更可靠,通常也更容易(你不必处理Android API),因为大多数连接属性以头字段的形式传递给你。
你可以在以下标头中查找客户端IP(这取决于你的服务器设置,但在大多数情况下,这将足够):
- "X-Forwarded-For" - "Proxy-Client-IP"(如果服务器在代理后面) - "WL-Proxy-Client-IP" - "HTTP_X_FORWARDED_FOR" - "HTTP_X_FORWARDED" - "HTTP_X_CLUSTER_CLIENT_IP" - "HTTP_CLIENT_IP" - "HTTP_FORWARDED_FOR" - "HTTP_FORWARDED" - "HTTP_VIA" - "REMOTE_ADDR"
由于你说你只从本地网络访问服务器,在某些标头中,你只会得到你的本地IP。

没有外部服务器,安卓应用程序本身就是服务器,客户端在与手机同一网络内,在这种情况下通信全部发生在同一个网络内部。 - casolorz
好的,当我说服务器/后端部分时,我指的是您的后端应用程序,这将适用于外部或内部网络,因为协议是相同的。 - Ivan Milisavljevic
我想我应该澄清一下。我的应用程序是在安卓上的服务器。它只知道手机,没有任何其他组件。它会给用户提供服务器地址(Android手机地址加端口),让用户将其输入到将访问我的服务器的客户端中。我无法控制客户端,客户端不受我控制或编写。这都是在内部网络中完成的,从来不需要外部访问,只需要局域网访问。 - casolorz
啊哈,所以你将你的安卓应用程序暴露为后端部分? - Ivan Milisavljevic
是的,在这整个过程中,Android应用程序是唯一的“服务器”。 - casolorz

-1
建立一个TCP连接到公共互联网上的某个地址,然后检查该套接字的源IP。

/JB


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接