42

I'm developing an app that gets the MAC address of the device, but since Android 6.0 my code doesn't work, giving me an incorrect value.

Here's my code...

public String ObtenMAC()
{
    WifiManager manager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
    WifiInfo info = manager.getConnectionInfo();

    return(info.getMacAddress().toUpperCase());
}

Instead of the real MAC address, it returns an strange code: 02:00:00:00:00:00.

Dale K
  • 25,246
  • 15
  • 42
  • 71
Mazinger
  • 633
  • 1
  • 6
  • 12
  • Did you made sure that you checked for the `ACCESS_WIFI_STATE` before getting the MAC-Address? In M it won't work if you only ask for it in the Manifest you have to implemet it in rumtime like that: https://www.youtube.com/watch?v=C8lUdPVSzDk&index=3&list=PLWz5rJ2EKKc-lJo_RGGXL2Psr8vVCTWjM – Ichor de Dionysos Oct 15 '15 at 22:08
  • Thanks for the answer. I have that permission in my Manifest, but when I go to check it programatically as shown in the video, Android Studio doesn't recognize "checkSelfPermission", I don't know if could be because I`m targeting API 21 Lollipop and hasn't installed API 23 Marshmallow. – Mazinger Oct 16 '15 at 00:22
  • Before you call checkSelfPermission you should check if the SDK Version is lass than API 23 Marshmallow like here: http://stackoverflow.com/questions/3423754/retrieving-android-api-version-programmatically – Ichor de Dionysos Oct 17 '15 at 19:40
  • It is always good to have the newest Android API version at the target level – Ichor de Dionysos Oct 17 '15 at 19:41
  • 2
    Please check this solution, it works for me http://stackoverflow.com/questions/31329733/how-to-get-the-missing-wifi-mac-address-on-android-m-preview – Gorio Jan 28 '16 at 12:06

11 Answers11

35

Please refer to Android 6.0 Changes.

To provide users with greater data protection, starting in this release, Android removes programmatic access to the device’s local hardware identifier for apps using the Wi-Fi and Bluetooth APIs. The WifiInfo.getMacAddress() and the BluetoothAdapter.getAddress() methods now return a constant value of 02:00:00:00:00:00.

To access the hardware identifiers of nearby external devices via Bluetooth and Wi-Fi scans, your app must now have the ACCESS_FINE_LOCATION or ACCESS_COARSE_LOCATION permissions.

Community
  • 1
  • 1
Siu
  • 1,422
  • 1
  • 12
  • 17
27

Use below code to get Mac address in Android 6.0

public static String getMacAddr() {
    try {
        List<NetworkInterface> all = Collections.list(NetworkInterface.getNetworkInterfaces());
        for (NetworkInterface nif : all) {
            if (!nif.getName().equalsIgnoreCase("wlan0")) continue;

            byte[] macBytes = nif.getHardwareAddress();
            if (macBytes == null) {
                return "";
            }

            StringBuilder res1 = new StringBuilder();
            for (byte b : macBytes) {
                res1.append(Integer.toHexString(b & 0xFF) + ":");
            }

            if (res1.length() > 0) {
                res1.deleteCharAt(res1.length() - 1);
            }
            return res1.toString();
        }
    } catch (Exception ex) {
        //handle exception
    }
    return "";
}
Chintan Rathod
  • 25,864
  • 13
  • 83
  • 93
15

I didn't get the above answer to work, but stumbled upon another answer.

Here is a complete and simple method on getting the IPv6 address and then getting the mac address from it.

How to get Wi-Fi Mac address in Android Marshmallow

public static String getMacAddr() {
    try {
        List<NetworkInterface> all = Collections.list(NetworkInterface.getNetworkInterfaces());
        for (NetworkInterface nif : all) {
            if (!nif.getName().equalsIgnoreCase("wlan0")) continue;

            byte[] macBytes = nif.getHardwareAddress();
            if (macBytes == null) {
                return "";
            }

            StringBuilder res1 = new StringBuilder();
            for (byte b : macBytes) {
                res1.append(String.format("%02X:",b));
            }

            if (res1.length() > 0) {
                res1.deleteCharAt(res1.length() - 1);
            }
            return res1.toString();
        }
    } catch (Exception ex) {
    }
    return "02:00:00:00:00:00";
}

Tested it already and it works. Many thanks to Rob Anderson!

Community
  • 1
  • 1
ADDER
  • 404
  • 3
  • 5
11

this is the complete 2 ways code of getting it successfully on Marshmallow , just copy past this and it will work !

//Android 6.0 : Access to mac address from WifiManager forbidden
    private static final String marshmallowMacAddress = "02:00:00:00:00:00";
    private static final String fileAddressMac = "/sys/class/net/wlan0/address";    

public static String recupAdresseMAC(WifiManager wifiMan) {
        WifiInfo wifiInf = wifiMan.getConnectionInfo();

        if(wifiInf.getMacAddress().equals(marshmallowMacAddress)){
            String ret = null;
            try {
                ret= getAdressMacByInterface();
                if (ret != null){
                    return ret;
                } else {
                    ret = getAddressMacByFile(wifiMan);
                    return ret;
                }
            } catch (IOException e) {
                Log.e("MobileAccess", "Erreur lecture propriete Adresse MAC");
            } catch (Exception e) {
                Log.e("MobileAcces", "Erreur lecture propriete Adresse MAC ");
            }
        } else{
            return wifiInf.getMacAddress();
        }
        return marshmallowMacAddress;
    }

private static String getAdressMacByInterface(){
        try {
            List<NetworkInterface> all = Collections.list(NetworkInterface.getNetworkInterfaces());
            for (NetworkInterface nif : all) {
                if (nif.getName().equalsIgnoreCase("wlan0")) {
                    byte[] macBytes = nif.getHardwareAddress();
                    if (macBytes == null) {
                        return "";
                    }

                    StringBuilder res1 = new StringBuilder();
                    for (byte b : macBytes) {
                        res1.append(String.format("%02X:",b));
                    }

                    if (res1.length() > 0) {
                        res1.deleteCharAt(res1.length() - 1);
                    }
                    return res1.toString();
                }
            }

        } catch (Exception e) {
            Log.e("MobileAcces", "Erreur lecture propriete Adresse MAC ");
        }
        return null;
    }

private static String getAddressMacByFile(WifiManager wifiMan) throws Exception {
        String ret;
        int wifiState = wifiMan.getWifiState();

        wifiMan.setWifiEnabled(true);
        File fl = new File(fileAddressMac);
        FileInputStream fin = new FileInputStream(fl);
        StringBuilder builder = new StringBuilder();
    int ch;
    while((ch = fin.read()) != -1){
        builder.append((char)ch);
    }

    ret = builder.toString();
    fin.close();

        boolean enabled = WifiManager.WIFI_STATE_ENABLED == wifiState;
        wifiMan.setWifiEnabled(enabled);
        return ret;
    }

manifest :

<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
  • Summary : this code will try to get the MAC address first by Interface and if its failed it get it by file system.

  • Note:for file System way, you need to enable WIFI to access the file.

thnx to Sam's answer here https://stackoverflow.com/a/39288868/3818437

Community
  • 1
  • 1
mhdjazmati
  • 4,152
  • 1
  • 26
  • 37
6

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
  • 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:53
  • The WifiManager API was changed in Android 6.0 to return a fake MAC address. But you can still get the IPv6 link local address for the Wi-Fi network and then extract the MAC address as above. This works on every device I have tried. – Yojimbo Jul 11 '16 at 13:08
  • Hi @Yojimbo, will this code return the MAC address of the router, or that of the device? – Daniel Jomphe Aug 23 '16 at 19:54
  • 1
    This is the WiFi MAC address of the device. You may be able to get the MAC of the WiFi access point using WiFiManager.getScanResults(). For a WAP, the BSSID equals the MAC address. – Yojimbo Aug 23 '16 at 20:14
  • You can enumerate the network interfaces using [NetworkInterface](https://developer.android.com/reference/java/net/NetworkInterface.html). See this [SO question](http://stackoverflow.com/questions/7010903/network-interface-names-for-android-devices) for an example. Use the Java instanceof operator to determine which IP addresses are [Inet6Address](https://developer.android.com/reference/java/net/Inet6Address.html) – Yojimbo Aug 24 '16 at 13:50
5

I try to get mac address with 2 methods, first by Interface and if its failed, i get it by file system, but you need to enable wifi to access the file.

//Android 6.0 : Access to mac address from WifiManager forbidden
    private static final String marshmallowMacAddress = "02:00:00:00:00:00";
    private static final String fileAddressMac = "/sys/class/net/wlan0/address";    

public static String recupAdresseMAC(WifiManager wifiMan) {
        WifiInfo wifiInf = wifiMan.getConnectionInfo();

        if(wifiInf.getMacAddress().equals(marshmallowMacAddress)){
            String ret = null;
            try {
                ret= getAdressMacByInterface();
                if (ret != null){
                    return ret;
                } else {
                    ret = getAddressMacByFile(wifiMan);
                    return ret;
                }
            } catch (IOException e) {
                Log.e("MobileAccess", "Erreur lecture propriete Adresse MAC");
            } catch (Exception e) {
                Log.e("MobileAcces", "Erreur lecture propriete Adresse MAC ");
            }
        } else{
            return wifiInf.getMacAddress();
        }
        return marshmallowMacAddress;
    }

private static String getAdressMacByInterface(){
        try {
            List<NetworkInterface> all = Collections.list(NetworkInterface.getNetworkInterfaces());
            for (NetworkInterface nif : all) {
                if (nif.getName().equalsIgnoreCase("wlan0")) {
                    byte[] macBytes = nif.getHardwareAddress();
                    if (macBytes == null) {
                        return "";
                    }

                    StringBuilder res1 = new StringBuilder();
                    for (byte b : macBytes) {
                        res1.append(String.format("%02X:",b));
                    }

                    if (res1.length() > 0) {
                        res1.deleteCharAt(res1.length() - 1);
                    }
                    return res1.toString();
                }
            }

        } catch (Exception e) {
            Log.e("MobileAcces", "Erreur lecture propriete Adresse MAC ");
        }
        return null;
    }

private static String getAddressMacByFile(WifiManager wifiMan) throws Exception {
        String ret;
        int wifiState = wifiMan.getWifiState();

        wifiMan.setWifiEnabled(true);
        File fl = new File(fileAddressMac);
        FileInputStream fin = new FileInputStream(fl);
        ret = convertStreamToString(fin);
        fin.close();

        boolean enabled = WifiManager.WIFI_STATE_ENABLED == wifiState;
        wifiMan.setWifiEnabled(enabled);
        return ret;
    }

Add this line to your manifest.

<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />

I recommend you to persist your mac address in your preferences like here

mac = activity.getSharedPreferences("MAC_ADDRESS", Context.MODE_PRIVATE).getString("MAC_ADDRESS", "");
                if(mac == null || mac.equals("")){
                    WifiManager wifiMan = (WifiManager) activity.getSystemService(Context.WIFI_SERVICE);
                    mac = MobileAccess.recupAdresseMAC(wifiMan);
                    if(mac != null && !mac.equals("")){
                        SharedPreferences.Editor editor = activity.getSharedPreferences("MAC_ADDRESS", Context.MODE_PRIVATE).edit();
                        editor.putString("MAC_ADDRESS", mac).commit();
                    }
                }
Sam
  • 51
  • 1
  • 1
5

Its Perfectly Fine

package com.keshav.fetchmacaddress;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;

import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Collections;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Log.e("keshav","getMacAddr -> " +getMacAddr());
    }

    public static String getMacAddr() {
        try {
            List<NetworkInterface> all = Collections.list(NetworkInterface.getNetworkInterfaces());
            for (NetworkInterface nif : all) {
                if (!nif.getName().equalsIgnoreCase("wlan0")) continue;

                byte[] macBytes = nif.getHardwareAddress();
                if (macBytes == null) {
                    return "";
                }

                StringBuilder res1 = new StringBuilder();
                for (byte b : macBytes) {
                    res1.append(Integer.toHexString(b & 0xFF) + ":");
                }

                if (res1.length() > 0) {
                    res1.deleteCharAt(res1.length() - 1);
                }
                return res1.toString();
            }
        } catch (Exception ex) {
            //handle exception
        }
        return "";
    }
}
Keshav Gera
  • 10,807
  • 1
  • 75
  • 53
1

First you need to add Internet user permission.

<uses-permission android:name="android.permission.INTERNET" />

Then you can find the mac over the NetworkInterfaces API.

public static String getMacAddr() {
    try {
        List<NetworkInterface> all = Collections.list(NetworkInterface.getNetworkInterfaces());
        for (NetworkInterface nif : all) {
            if (!nif.getName().equalsIgnoreCase("wlan0")) continue;

            byte[] macBytes = nif.getHardwareAddress();
            if (macBytes == null) {
                return "";
            }

            StringBuilder res1 = new StringBuilder();
            for (byte b : macBytes) {
                res1.append(String.format("%02X:",b));
            }

            if (res1.length() > 0) {
                res1.deleteCharAt(res1.length() - 1);
            }
            return res1.toString();
        }
    } catch (Exception ex) {
    }
    return "02:00:00:00:00:00";
}
Laurel
  • 5,965
  • 14
  • 31
  • 57
  • 1
    The above answer was taken from this blog post: http://robinhenniges.com/en/android6-get-mac-address-programmatically – zerobandwidth Sep 30 '16 at 18:19
1

The answers are mostly correct, but keep care, that there is a change in android 7. You will need to use the

DevicePolicyManager and the Method getWifiMacAddress. The official docs has a typo, which means that you shouldnt copy/paste it from there.

DevicePolicyManager.getWifiMacAddress()

Refs: https://developer.android.com/about/versions/nougat/android-7.0-changes.html

Get Device mac adress in Android Nougat and O programmatically

Community
  • 1
  • 1
Emanuel
  • 8,027
  • 2
  • 37
  • 56
1

Use wifiInfo.getBSSID() to get Mac Address of AccessPoint instead of getMacAddress method.

Aziz Ejaz
  • 57
  • 2
  • Only provides the mac address of the device your connected to like a wifi router. Not the device itself – ldrrp Mar 24 '20 at 17:59
0

This is a more kotlin way to get Mac Address

fun getMacAddress(): String =
        NetworkInterface.getNetworkInterfaces().toList()
                .firstOrNull { it.name.equals("wlan0", ignoreCase = true) }?.let {
                    it.hardwareAddress?.let { macBytes ->
                        StringBuilder().apply {
                            for (b in macBytes) {
                                append(String.format("%02X:", b))
                            }
                            if (isNotEmpty()) {
                                deleteCharAt(lastIndex)
                            }
                        }
                    }.toString()
                } ?: "02:00:00:00:00:00"