Accurate Posture Acquisition of Android IP and MAC

Keywords: Android Mac network Programming

Each product counts user terminal information. A little neglect will lead to data errors, analysis and even strategic errors. (Pretending to be a procedural ape creates the world)

Equipment: Oppo R9s, vivo X9
System: Android 6.0.2
Network: 4G
Error IP and MAC are respectively

fe80::188c:24ff:fe49:8e54%dummy0
02:00:00:00:00:00

Error code:

  public static String getLocalIpAddress() {
    try {
      for (
          Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
          networkInterfaces.hasMoreElements(); ) {
        NetworkInterface networkInterface = networkInterfaces.nextElement();
        for (Enumeration<InetAddress> inetAddresses = networkInterface.getInetAddresses();
            inetAddresses.hasMoreElements(); ) {
          InetAddress inetAddress = inetAddresses.nextElement();
          if (!inetAddress.isLoopbackAddress()) {
            String ipAddress = inetAddress.getHostAddress().toUpperCase();
            return ipAddress;
          }
        }
      }
    } catch (SocketException e) {
    }
    return null;
  }

Then according to the search results, the result of removing "% dummy 0% 2" directly is the ipv6 address. Believe it or not, I believed it at that time, and then there was a voice in my mind telling me from time to time that it was wrong, the world was not like this. (sequelae of programmed apes)

Link-local address, Loopback address

In the code above, we blocked Loopback address. And the obtained fe80::188c:24ff:fe49:8e54 is indeed IPv6, but the prefix is fe80::/64 is the link local address, not the ip we really want. IPv6 address types, concepts, see in detail IPv6

Unlocking Gets IP Correct Posture

Knowing that Link-local address and Loopback address are not the IP we want through the popular posture of Duniang above, we killed them and changed them to the following code.

  public static String getLocalIpAddress() {
    try {
      for (
          Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
          networkInterfaces.hasMoreElements(); ) {
        NetworkInterface networkInterface = networkInterfaces.nextElement();
        for (Enumeration<InetAddress> inetAddresses = networkInterface.getInetAddresses();
            inetAddresses.hasMoreElements(); ) {
          InetAddress inetAddress = inetAddresses.nextElement();
          //Filter Loopback address, Link-local address
          if (!inetAddress.isLoopbackAddress() && !inetAddress.isLinkLocalAddress()) {
            return inetAddress.getHostAddress();
          }
        }
      }
    } catch (SocketException e) {
    }
    return null;
  }

OPPO R9s Android 6.0.1 Running results:

type IP
wifi 172.27.35.3
flow 100.58.248.64

Acquisition of correct MAC posture after extension-unlock 6.0

Dummy 0, lo, p2p0, rev_rmnet0, rev_rmnet1, rev_rmnet2, rev_rmnet3, rmnet0, rmnet1, rmnet2, rmnet3, rmnet_smux0, sit0, wlan0 and so on. We find many such names. My understanding is that besides wlan0, which is a real wireless network card like a computer, all other virtual network cards are used for internal communication.
After 6.0, Android removed programming access to the device's local hardware identifier. Using WifiInfo.getMacAddress(), BluetoothAdapter.getAddress(), the return value is constant 02:00:00:00:00. With the above experience of getting IP addresses through Java api, can you also get mac addresses here? Upper Code

  public static String getMac() {
    try {
      for (
          Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
          networkInterfaces.hasMoreElements(); ) {
        NetworkInterface networkInterface = networkInterfaces.nextElement();
        if ("wlan0".equals(networkInterface.getName())) {
          byte[] hardwareAddress = networkInterface.getHardwareAddress();
          if (hardwareAddress == null || hardwareAddress.length == 0) {
            continue;
          }
          StringBuilder buf = new StringBuilder();
          for (byte b : hardwareAddress) {
            buf.append(String.format("%02X:", b));
          }
          if (buf.length() > 0) {
            buf.deleteCharAt(buf.length() - 1);
          }
          String mac = buf.toString();
          return mac;
        }
      }
    } catch (SocketException e) {
      e.printStackTrace();
    }
    return null;
  }

OPPO R9s Android 6.0.1 Running results:

Code type MAC Jurisdiction
WifiInfo 02:00:00:00:00:00 android.permission.ACCESS_WIFI_STATE
NetworkInterface B8:37:65:2D:23:ED android.permission.INTERNET

It involves a lot of network knowledge, but now it's still rather obscure.
What happened to dummy 0, lo, p2p0, rev_rmnet0, rev_rmnet1, rev_rmnet2, rev_rmnet3, rmnet0, rmnet1, rmnet2, rmnet3, rmnet_smux0, site 0?

Special Thanks

Daniel Laozhang, former company boss, whole stack. A sexy product has been launched recently. Graph intersection
Hardware Player, Network Man Mango

Reference resources:

IPv6
InetAddress API
Hardware identifier access rights

Posted by xcasio on Sun, 07 Jul 2019 18:10:16 -0700