15

Android developers looking to get the Wifi MAC Address on Android M may have experienced an issue where the standard Android OS API to get the MAC Address returns a fake MAC Address (02:00:00:00:00:00) instead of the real value.

The normal way to get the Wifi MAC address is below:

final WifiManager wifiManager = (WifiManager) getApplication().getApplicationContext().getSystemService(Context.WIFI_SERVICE);

final String wifiMACaddress = wifiManager.getConnectionInfo().getMacAddress();
Yojimbo
  • 23,288
  • 5
  • 44
  • 48
DanielG
  • 370
  • 1
  • 3
  • 15
  • 3
    Stack Overflow is for programming questions. What is your question? If you are trying to provide some sort of FAQ entry, please [follow the site instructions](https://stackoverflow.com/help/self-answer), and ask a question, then provide your own answer to that question. – CommonsWare Jul 09 '15 at 23:00
  • It seems that Mac Address is randomized even you can catch it! https://developer.android.com/about/versions/marshmallow/android-6.0-changes.html#behavior-hardware-id – Behrouz.M Jul 10 '16 at 08:50
  • Possible duplicate of [Getting MAC address in Android 6.0](http://stackoverflow.com/questions/33159224/getting-mac-address-in-android-6-0) – mhdjazmati Dec 14 '16 at 13:37
  • I posted here working solution https://stackoverflow.com/a/47789324/5330408 – Android Developer Dec 13 '17 at 11:35

3 Answers3

32

In Android M the MACAddress will be "unreadable" for WiFi and Bluetooth. You can get the WiFi MACAddress with (Android M Preview 2):

public static String getWifiMacAddress() {
    try {
        String interfaceName = "wlan0";
        List<NetworkInterface> interfaces = Collections.list(NetworkInterface.getNetworkInterfaces());
        for (NetworkInterface intf : interfaces) {
            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 ex) { } // for now eat exceptions
    return "";
}

(got this code from this Post)

Somehow I heared that reading the File from "/sys/class/net/" + networkInterfaceName + "/address"; will not work since Android N will be released and also there can be differences between the different manufacturers like Samsung etc.

Hopefully this code will still work in later Android versions.

EDIT: Also in Android 6 release this works

Community
  • 1
  • 1
Informatic0re
  • 6,300
  • 5
  • 41
  • 56
  • what permission do you think we need for retrieving the `networkInterface`? and how does this approach diff from the official solution of Android http://developer.android.com/about/versions/marshmallow/android-6.0-changes.html#behavior-hardware-id? – bj4947 Oct 08 '15 at 20:40
  • 2
    there isn't a solution. To access the hardware identifiers of -->nearby external devices<-- your app must now have the ACCESS_FINE_LOCATION or ACCESS_COARSE_LOCATION permissions. I am not sure what permission is needed for retrieving networkInterfaces. But to access the smartphones WiFi-MAC-Address, this is the only way right now and it will be gone with one of the next versions of android – Informatic0re Oct 09 '15 at 06:02
  • 1
    It seems that Mac Address is randomized even you can catch it! https://developer.android.com/about/versions/marshmallow/android-6.0-changes.html#behavior-hardware-id – Behrouz.M Jul 10 '16 at 09:28
  • It works flawlessly +1 for that, Is it appropriate to use this method.. will it work in any sdk from 1 to upcoming sdk – Saiteja Prasadam Aug 08 '16 at 18:08
  • I would recommend to just use it from api-23 (Android M), for older versions I would use the normal way and from N you should check if it is still working. – Informatic0re Aug 09 '16 at 14:54
8

Resolved!

The MAC Address can still be grabbed from the path:

"/sys/class/net/" + networkInterfaceName + "/address";

Simply doing a file read, or a cat of that file will show the Wifi MAC Address.

Network interface names are usually along the lines of "wlan0" or "eth1"

DanielG
  • 370
  • 1
  • 3
  • 15
2

You can get the MAC address from the IPv6 local address. E.g., the IPv6 address "fe80::1034:56ff:fe78:9abc" corresponds to the MAC address "12-34-56-78-9a-bc". See the code below. Getting the WiFi IPv6 address only requires android.permission.INTERNET.

See the Wikipedia page IPv6 Address, particularly the note about "local addresses" fe80::/64 and the section about "Modified EUI-64".

/**
 * Gets an EUI-48 MAC address from an IPv6 link-local address.
 * E.g., the IPv6 address "fe80::1034:56ff:fe78:9abc"
 * corresponds to the MAC address "12-34-56-78-9a-bc".
 * <p/>
 * See the note about "local addresses" fe80::/64 and the section about "Modified EUI-64" in
 * the Wikipedia article "IPv6 address" at https://en.wikipedia.org/wiki/IPv6_address
 *
 * @param ipv6 An Inet6Address object.
 * @return The EUI-48 MAC address as a byte array, null on error.
 */
private static byte[] getMacAddressFromIpv6(final Inet6Address ipv6)
{
    byte[] eui48mac = null;

    if (ipv6 != null) {
        /*
         * Make sure that this is an fe80::/64 link-local address.
         */
        final byte[] ipv6Bytes = ipv6.getAddress();
        if ((ipv6Bytes != null) &&
                (ipv6Bytes.length == 16) &&
                (ipv6Bytes[0] == (byte) 0xfe) &&
                (ipv6Bytes[1] == (byte) 0x80) &&
                (ipv6Bytes[11] == (byte) 0xff) &&
                (ipv6Bytes[12] == (byte) 0xfe)) {
            /*
             * Allocate a byte array for storing the EUI-48 MAC address, then fill it
             * from the appropriate bytes of the IPv6 address. Invert the 7th bit
             * of the first byte and discard the "ff:fe" portion of the modified
             * EUI-64 MAC address.
             */
            eui48mac = new byte[6];
            eui48mac[0] = (byte) (ipv6Bytes[8] ^ 0x2);
            eui48mac[1] = ipv6Bytes[9];
            eui48mac[2] = ipv6Bytes[10];
            eui48mac[3] = ipv6Bytes[13];
            eui48mac[4] = ipv6Bytes[14];
            eui48mac[5] = ipv6Bytes[15];
        }
    }

    return eui48mac;
}
Yojimbo
  • 23,288
  • 5
  • 44
  • 48