如何从代码中获取设备的IP地址?

Nil*_*upe 353 android ip-address

是否可以使用某些代码获取设备的IP地址?

Who*_*ome 415

这是我帮助读取IP和MAC地址的工具.实现是纯java,但我有一个注释块getMACAddress(),可以读取特殊Linux(Android)文件中的值.我只在少数设备和模拟器上运行此代码,但如果您发现奇怪的结果,请告诉我.

// AndroidManifest.xml permissions
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

// test functions
Utils.getMACAddress("wlan0");
Utils.getMACAddress("eth0");
Utils.getIPAddress(true); // IPv4
Utils.getIPAddress(false); // IPv6 
Run Code Online (Sandbox Code Playgroud)

Utils.java

import java.io.*;
import java.net.*;
import java.util.*;   
//import org.apache.http.conn.util.InetAddressUtils;

public class Utils {

    /**
     * Convert byte array to hex string
     * @param bytes toConvert
     * @return hexValue
     */
    public static String bytesToHex(byte[] bytes) {
        StringBuilder sbuf = new StringBuilder();
        for(int idx=0; idx < bytes.length; idx++) {
            int intVal = bytes[idx] & 0xff;
            if (intVal < 0x10) sbuf.append("0");
            sbuf.append(Integer.toHexString(intVal).toUpperCase());
        }
        return sbuf.toString();
    }

    /**
     * Get utf8 byte array.
     * @param str which to be converted
     * @return  array of NULL if error was found
     */
    public static byte[] getUTF8Bytes(String str) {
        try { return str.getBytes("UTF-8"); } catch (Exception ex) { return null; }
    }

    /**
     * Load UTF8withBOM or any ansi text file.
     * @param filename which to be converted to string
     * @return String value of File
     * @throws java.io.IOException if error occurs
     */
    public static String loadFileAsString(String filename) throws java.io.IOException {
        final int BUFLEN=1024;
        BufferedInputStream is = new BufferedInputStream(new FileInputStream(filename), BUFLEN);
        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream(BUFLEN);
            byte[] bytes = new byte[BUFLEN];
            boolean isUTF8=false;
            int read,count=0;           
            while((read=is.read(bytes)) != -1) {
                if (count==0 && bytes[0]==(byte)0xEF && bytes[1]==(byte)0xBB && bytes[2]==(byte)0xBF ) {
                    isUTF8=true;
                    baos.write(bytes, 3, read-3); // drop UTF8 bom marker
                } else {
                    baos.write(bytes, 0, read);
                }
                count+=read;
            }
            return isUTF8 ? new String(baos.toByteArray(), "UTF-8") : new String(baos.toByteArray());
        } finally {
            try{ is.close(); } catch(Exception ignored){} 
        }
    }

    /**
     * Returns MAC address of the given interface name.
     * @param interfaceName eth0, wlan0 or NULL=use first interface 
     * @return  mac address or empty string
     */
    public static String getMACAddress(String interfaceName) {
        try {
            List<NetworkInterface> interfaces = Collections.list(NetworkInterface.getNetworkInterfaces());
            for (NetworkInterface intf : interfaces) {
                if (interfaceName != null) {
                    if (!intf.getName().equalsIgnoreCase(interfaceName)) continue;
                }
                byte[] mac = intf.getHardwareAddress();
                if (mac==null) return "";
                StringBuilder buf = new StringBuilder();
                for (byte aMac : mac) buf.append(String.format("%02X:",aMac));  
                if (buf.length()>0) buf.deleteCharAt(buf.length()-1);
                return buf.toString();
            }
        } catch (Exception ignored) { } // for now eat exceptions
        return "";
        /*try {
            // this is so Linux hack
            return loadFileAsString("/sys/class/net/" +interfaceName + "/address").toUpperCase().trim();
        } catch (IOException ex) {
            return null;
        }*/
    }

    /**
     * Get IP address from first non-localhost interface
     * @param useIPv4   true=return ipv4, false=return ipv6
     * @return  address or empty string
     */
    public static String getIPAddress(boolean useIPv4) {
        try {
            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();
                        //boolean isIPv4 = InetAddressUtils.isIPv4Address(sAddr);
                        boolean isIPv4 = sAddr.indexOf(':')<0;

                        if (useIPv4) {
                            if (isIPv4) 
                                return sAddr;
                        } else {
                            if (!isIPv4) {
                                int delim = sAddr.indexOf('%'); // drop ip6 zone suffix
                                return delim<0 ? sAddr.toUpperCase() : sAddr.substring(0, delim).toUpperCase();
                            }
                        }
                    }
                }
            }
        } catch (Exception ignored) { } // for now eat exceptions
        return "";
    }

}
Run Code Online (Sandbox Code Playgroud)

免责声明:此Utils类的想法和示例代码来自几个SO帖子和Google.我已经清理并合并了所有的例子.

  • 由于getHardwareAddress(),这需要API级别9及更高级别. (17认同)
  • 如果您在本地网络(例如Wifi或模拟器)上,您将获得一个私有IP地址.您可以通过请求到特定网站获取代理IP地址,该网站为您提供代理地址,例如http://whatismyip.akamai.com/ (4认同)
  • 在尝试获取IP地址时,我在Nexus 6上的结果很糟糕.我有一个名为"name:dummy0(dummy0)"的NetworkInterface,它给出一个格式为"/ XX :: XXXX:XXXX:XXXX:XXXX%dummy0"的地址,还有一个与wlan0对应的真实网络接口,但是因为"假"首先发生我总是得到那个虚拟地址 (3认同)
  • 问题-`toUpperCase()`上的皮棉警告。捕捉`Exception`总是很狡猾(并且无论如何,辅助方法都应该抛出,并让调用者处理Exception-尽管未对此进行修改)。格式:不得超过80行。有条件执行`getHardwareAddress()`-补丁程序:https://github.com/Utumno/AndroidHelpers/commit/b285df75ab6dd1e724e1985d480d18be3a8692a7。你说的话 ? (2认同)

Nil*_*upe 193

这对我有用:

WifiManager wm = (WifiManager) getSystemService(WIFI_SERVICE);
String ip = Formatter.formatIpAddress(wm.getConnectionInfo().getIpAddress());
Run Code Online (Sandbox Code Playgroud)

  • 即使用户使用数据而不是wifi,这仍然可以工作吗? (34认同)
  • 由于某种原因,不推荐使用formatIpAddress.应该用什么呢? (13认同)
  • 这个对我有用.但是,它需要"ACCESS_WIFI_STATE"权限,并且正如"Umair"所写,不需要列表使用. (9认同)
  • 从文档:使用`getHostAddress()`,它支持IPv4和IPv6地址.此方法不支持IPv6地址. (8认同)
  • 如何使用getHostAddress()获取服务器和客户端IP地址@RyanR? (7认同)
  • 不,这不是直接回答OP.因为并非所有Android设备都使用WiFi连接到互联网.它可能在以太网上具有NATed LAN,或者BT而不是NATed WAN连接等. (4认同)
  • 即使我连接到局域网而不是无线网络,这也可以吗? (2认同)
  • Android Studio 现在显示警告,执行`getApplicationContext().getSystemService(WIFI_SERVICE)` (2认同)
  • 不推荐使用Formatter.formatIpAddress()。 (2认同)

ana*_*und 62

我使用了以下代码:我使用hashCode的原因是因为我在使用时将一些垃圾值附加到ip地址getHostAddress.但hashCode对我来说效果非常好,因为我可以使用Formatter来获取正确格式化的IP地址.

以下是示例输出:

使用getHostAddress:***** IP=fe80::65ca:a13d:ea5a:233d%rmnet_sdio0

2.使用hashCodeFormatter: ***** IP=238.194.77.212

正如您所看到的,第二种方法正好能满足我的需求.

public 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()) {
                    String ip = Formatter.formatIpAddress(inetAddress.hashCode());
                    Log.i(TAG, "***** IP="+ ip);
                    return ip;
                }
            }
        }
    } catch (SocketException ex) {
        Log.e(TAG, ex.toString());
    }
    return null;
}
Run Code Online (Sandbox Code Playgroud)

  • 使用hashCode是完全错误的,并返回废话.请改用InetAddress.getHostAddress(). (10认同)

小智 53

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;
}
Run Code Online (Sandbox Code Playgroud)

我添加了inetAddressinstanceof Inet4Address以检查它是否是ipv4地址.


CYB*_*CYB 49

虽然有正确的答案,但我在这里分享我的答案,并希望这种方式更方便.

WifiManager wifiMan = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
WifiInfo wifiInf = wifiMan.getConnectionInfo();
int ipAddress = wifiInf.getIpAddress();
String ip = String.format("%d.%d.%d.%d", (ipAddress & 0xff),(ipAddress >> 8 & 0xff),(ipAddress >> 16 & 0xff),(ipAddress >> 24 & 0xff));
Run Code Online (Sandbox Code Playgroud)

  • 谢谢!不推荐使用Formatter,我真的不喜欢编写简单的位逻辑. (4认同)
  • 效果很好,但需要WIFI_STATE权限:`<uses-permission android:name ="android.permission.ACCESS_WIFI_STATE"/>` (4认同)

Sat*_*yam 31

下面的代码可能会帮助你..不要忘记添加权限..

public 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()) {
                return inetAddress.getHostAddress();
                }
           }
       }
       } catch (Exception ex) {
          Log.e("IP Address", ex.toString());
      }
      return null;
}
Run Code Online (Sandbox Code Playgroud)

在清单文件中添加以下权限.

 <uses-permission android:name="android.permission.INTERNET" />
 <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
Run Code Online (Sandbox Code Playgroud)

快乐的编码!!

  • 嘿这会返回一个不正确的值,如:"fe80 :: f225:b7ff:fe8c:d357%wlan0" (5认同)
  • 更改条件是否像这样以获得正确的ip:if(!inetAddress.isLoopbackAddress()&amp;&amp; inetAddress instance of Inet4Address) (3认同)

Daa*_*aan 15

您不需要像目前为止提供的解决方案那样添加权限.以字符串形式下载此网站:

http://www.ip-api.com/json

要么

http://www.telize.com/geoip

可以使用java代码将网站作为字符串下载:

http://www.itcuties.com/java/read-url-to-string/

像这样解析JSON对象:

/sf/answers/1329874241/

json属性"query"或"ip"包含IP地址.

  • 为什么这是一个大问题?当然,您需要互联网连接,因为IP地址在技术上与此类连接相关.如果您离开家并前往餐厅,您将使用另一个互联网连接,从而使用另一个IP地址.您不需要添加更多内容,如ACCESS_NETWORK_STATE或ACCESS_WIFI_STATE.互联网连接是您提供解决方案所需的唯一权限. (4认同)
  • 大卫的原始观点仍然存在.如果您所在的内部网络无法访问互联网,该怎么办? (3认同)
  • 这需要Internet连接。大问题 (2认同)
  • 哪个域名?如果ip-api.com不起作用,您可以使用telize.com作为后备.否则,您可以使用https://api.ipify.org/.它也可以在这里(不是json):http://ip.jsontest.com/?callback = showIP.许多应用都使用可以保证在线的域名; 这是正常的.但是,如果您使用后备,则不太可能出现问题. (2认同)
  • 我从来没有想过这个,因为我不知道应用程序的任何实际目的肯定需要一个网络,但应该没有互联网工作(也许有,但我没有看到它的移动设备). (2认同)

Rap*_*l C 15

kotlin 极简版

fun getIpv4HostAddress(): String {
    NetworkInterface.getNetworkInterfaces()?.toList()?.map { networkInterface ->
        networkInterface.inetAddresses?.toList()?.find {
            !it.isLoopbackAddress && it is Inet4Address
        }?.let { return it.hostAddress }
    }
    return ""
}
Run Code Online (Sandbox Code Playgroud)


sal*_*lid 9

private InetAddress getLocalAddress()throws IOException {

            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()) {
                            //return inetAddress.getHostAddress().toString();
                            return inetAddress;
                        }
                    }
                }
            } catch (SocketException ex) {
                Log.e("SALMAN", ex.toString());
            }
            return null;
        }
Run Code Online (Sandbox Code Playgroud)


小智 8

方法getDeviceIpAddress返回设备的IP地址,如果连接,则优先选择wifi接口地址.

  @NonNull
    private String getDeviceIpAddress() {
        String actualConnectedToNetwork = null;
        ConnectivityManager connManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
        if (connManager != null) {
            NetworkInfo mWifi = connManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
            if (mWifi.isConnected()) {
                actualConnectedToNetwork = getWifiIp();
            }
        }
        if (TextUtils.isEmpty(actualConnectedToNetwork)) {
            actualConnectedToNetwork = getNetworkInterfaceIpAddress();
        }
        if (TextUtils.isEmpty(actualConnectedToNetwork)) {
            actualConnectedToNetwork = "127.0.0.1";
        }
        return actualConnectedToNetwork;
    }

    @Nullable
    private String getWifiIp() {
        final WifiManager mWifiManager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
        if (mWifiManager != null && mWifiManager.isWifiEnabled()) {
            int ip = mWifiManager.getConnectionInfo().getIpAddress();
            return (ip & 0xFF) + "." + ((ip >> 8) & 0xFF) + "." + ((ip >> 16) & 0xFF) + "."
                    + ((ip >> 24) & 0xFF);
        }
        return null;
    }


    @Nullable
    public String getNetworkInterfaceIpAddress() {
        try {
            for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements(); ) {
                NetworkInterface networkInterface = en.nextElement();
                for (Enumeration<InetAddress> enumIpAddr = networkInterface.getInetAddresses(); enumIpAddr.hasMoreElements(); ) {
                    InetAddress inetAddress = enumIpAddr.nextElement();
                    if (!inetAddress.isLoopbackAddress() && inetAddress instanceof Inet4Address) {
                        String host = inetAddress.getHostAddress();
                        if (!TextUtils.isEmpty(host)) {
                            return host;
                        }
                    }
                }

            }
        } catch (Exception ex) {
            Log.e("IP Address", "getLocalIpAddress", ex);
        }
        return null;
    }
Run Code Online (Sandbox Code Playgroud)


mat*_*dev 6

在您的活动中,以下函数getIpAddress(context)返回电话的 IP 地址:

public static String getIpAddress(Context context) {
    WifiManager wifiManager = (WifiManager) context.getApplicationContext()
                .getSystemService(WIFI_SERVICE);

    String ipAddress = intToInetAddress(wifiManager.getDhcpInfo().ipAddress).toString();

    ipAddress = ipAddress.substring(1);

    return ipAddress;
}

public static InetAddress intToInetAddress(int hostAddress) {
    byte[] addressBytes = { (byte)(0xff & hostAddress),
                (byte)(0xff & (hostAddress >> 8)),
                (byte)(0xff & (hostAddress >> 16)),
                (byte)(0xff & (hostAddress >> 24)) };

    try {
        return InetAddress.getByAddress(addressBytes);
    } catch (UnknownHostException e) {
        throw new AssertionError();
    }
}
Run Code Online (Sandbox Code Playgroud)


Ata*_*rim 6

您可以使用LinkProperties。推荐用于新的 Android 版本。

此函数检索 WiFi 和移动数据的本地 IP 地址。它需要Manifest.permission.ACCESS_NETWORK_STATE许可。

@Nullable
public static String getDeviceIpAddress(@NonNull ConnectivityManager connectivityManager) {
    LinkProperties linkProperties = connectivityManager.getLinkProperties(connectivityManager.getActiveNetwork());
    InetAddress inetAddress;
    for(LinkAddress linkAddress : linkProperties.getLinkAddresses()) {
        inetAddress = linkAddress.getAddress();
        if (inetAddress instanceof Inet4Address
                && !inetAddress.isLoopbackAddress()
                && inetAddress.isSiteLocalAddress()) {
            return inetAddress.getHostAddress();
        }
    }
    return null;
}
Run Code Online (Sandbox Code Playgroud)


Jon*_*ung 5

这是这个答案的重做,它去除了不相关的信息,添加了有用的评论,更清楚地命名变量,并改进了逻辑。

不要忘记包含以下权限:

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
Run Code Online (Sandbox Code Playgroud)

InternetHelper.java:

public class InternetHelper {

    /**
     * Get IP address from first non-localhost interface
     *
     * @param useIPv4 true=return ipv4, false=return ipv6
     * @return address or empty string
     */
    public static String getIPAddress(boolean useIPv4) {
        try {
            List<NetworkInterface> interfaces =
                    Collections.list(NetworkInterface.getNetworkInterfaces());

            for (NetworkInterface interface_ : interfaces) {

                for (InetAddress inetAddress :
                        Collections.list(interface_.getInetAddresses())) {

                    /* a loopback address would be something like 127.0.0.1 (the device
                       itself). we want to return the first non-loopback address. */
                    if (!inetAddress.isLoopbackAddress()) {
                        String ipAddr = inetAddress.getHostAddress();
                        boolean isIPv4 = ipAddr.indexOf(':') < 0;

                        if (isIPv4 && !useIPv4) {
                            continue;
                        }
                        if (useIPv4 && !isIPv4) {
                            int delim = ipAddr.indexOf('%'); // drop ip6 zone suffix
                            ipAddr = delim < 0 ? ipAddr.toUpperCase() :
                                    ipAddr.substring(0, delim).toUpperCase();
                        }
                        return ipAddr;
                    }
                }

            }
        } catch (Exception ignored) { } // if we can't connect, just return empty string
        return "";
    }

    /**
     * Get IPv4 address from first non-localhost interface
     *
     * @return address or empty string
     */
    public static String getIPAddress() {
        return getIPAddress(true);
    }

}
Run Code Online (Sandbox Code Playgroud)