9

I have an app that has a web server that the user will access from their home LAN. Currently I have two ways of getting the device IP and I don't know which is more likely to be the right one.

My normal way:

  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();

My alternate way:

        WifiInfo connectionInfo = wifiMgr.getConnectionInfo();
        int ip = connectionInfo.getIpAddress();

This I think has been working OK but I do have some statistics on it and it seems like the two ips are different only about 4% of the time.

Also I just tried my app on a Chromebook and the alternate way is actually the correct one, not the normal way.

So how can I know which way is better or is there a better alternative?

Zoe
  • 27,060
  • 21
  • 118
  • 148
casolorz
  • 8,486
  • 19
  • 93
  • 200

5 Answers5

0

They are highly unreliable as you have to deal with a lot of edge cases.

I prefer using a free external service instead; do a network call and get your proper public facing IP. Try https://www.ipify.org/

terencey
  • 3,282
  • 4
  • 32
  • 40
  • But I don't need the public IP, I need the IP on the user's LAN. – casolorz Jun 05 '18 at 20:09
  • In that case, perhaps this can help you: https://stackoverflow.com/questions/6064510/how-to-get-ip-address-of-the-device-from-code – terencey Jun 05 '18 at 20:11
  • So they do it with my primary way of doing it, I probably copied their code long ago. But I still don't know if that is more reliable than the other way I have. – casolorz Jun 05 '18 at 20:14
0

Scanning the NetworkInterfaces can certainly return a variety of results. You can understand more from the intf.getName(), e.g. :

  • Wifi connection on wlan0
  • 3G/4G connection on such as rmnet1
  • The loopback (127.0.0.1) on lo - you're already eliminating this
  • Wired ethernet connection eth0 - possible on some Chromebooks

There are more possibilities too like a VPN connection.

If it's safe to say you'll only be wanting to connect to the web server on the Wifi connection, it would be possible to add a check that the interface name starts with wlan, but your alternate solution seems simpler for this case.

If the ethernet connection is also possible on the Chromebook, the web server may be offering connections on both wlan0 and eth0. Either pick a preferred connection from the network interfaces, or even be prepared to offer both a wireless and a wired IP.

df778899
  • 10,703
  • 1
  • 24
  • 36
  • Thanks for those network names. I'm already checking for `wlan0`. I will check `eth` as well. On the Chromebook I think the issue is that Android apps are kind of like emulated or something, that is why the wifi manager returns the right info but NetworkInterfaces doesn't. I'm not no so much trying to handle the Chromebook case since that is an easier one to figure out, but all the weird other devices out there. – casolorz Jun 09 '18 at 15:52
0

I am using below way to get local IP address from Android device and it looks good to me:

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;
} 

This is almost same as your normal way but a bit refined. Hope this will help!

Vikasdeep Singh
  • 20,983
  • 15
  • 78
  • 104
  • I didn't add all of my code, I do check for ipv4 and also I prefer things like `wlan0` but at least on the chromebook, none of the ips returned here are the right one. I'm guessing at this point that there isn't a right answer. – casolorz Jun 12 '18 at 05:01
0

I would suggest you to move the IP stuff to the server/backend part. Its more reliable and generally easier (you dont have to deal with android API's) to determine this kind of stuff on the server, since most of the connection properties are passed to you in form of the header fields.

You can look for client ip in following headers (This depends on your server setup, but in most cases this will suffice):

  • "X-Forwarded-For",
  • "Proxy-Client-IP" (if server is behind a proxy)
  • "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"

Since you said you are accessing your server only from local network in some of these headers you will get only your local IP

Ivan Milisavljevic
  • 2,048
  • 2
  • 13
  • 21
  • There is no external server, the app in android is the server, and the client is inside the same network as the phone, so the communication is all within the same network. – casolorz Jun 19 '18 at 14:19
  • Ok, when i said server/backend part i meant your backend application, this is going to work for both external or internal networks because protocol is the same – Ivan Milisavljevic Jun 19 '18 at 18:07
  • I guess I should have clarified. My app is the server on android. All it knows is the phone, doesn't have any components anywhere else. It gives the user the server address (the Android phone address plus port) for the user to put into the client that will access my server. I don't have any control over the client, the client isn't controlled or written by me. This is all done in the internal network, there is never need for external access, just LAN access. – casolorz Jun 19 '18 at 18:55
  • Aha so your exposing your android app as a backend part? – Ivan Milisavljevic Jun 19 '18 at 18:56
  • Yeah, the Android app is the only "server" in this whole thing. – casolorz Jun 19 '18 at 19:22
-1

Make a TCP connection to something on the public internet and then check the source IP of that socket.

/JB

Jonas Bjork
  • 158
  • 3