32

Pre Marshmallow my app would obtain it's device MAC address via BluetoothAdapter.getDefaultAdapter().getAddress().

Now with Marshmallow Android is returning 02:00:00:00:00:00.

I saw some link(sorry not sure where now) that said you need to add the additional permission

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

to be able to get it. However it isn't working for me.

Is there some additional permission needed to get the mac address?

I am not sure it is pertinent here but the manifest also includes

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

So is there a way to get the local bluetooth mac address?

Abhinav Singh Maurya
  • 3,313
  • 8
  • 33
  • 51
Eric
  • 781
  • 1
  • 10
  • 18

9 Answers9

42

zmarties is right but you can still get the mac address via reflection or Settings.Secure:

  String macAddress = android.provider.Settings.Secure.getString(context.getContentResolver(), "bluetooth_address");
blobbie
  • 1,279
  • 1
  • 10
  • 8
  • 1
    what about wifi address ? , can you handle for mac address ? – Adnan Abdollah Zaki Dec 27 '15 at 09:11
  • 1
    This is giving different bdaddr(but a valid mac). Reflection method is giving correct bdaddr. – Rilwan Feb 03 '17 at 10:01
  • 2
    @Rilwan using reflection for hidden/blacklisted API will crash your app with next OS update and it is never correct solution, just temporal workaround. – Ewoks Aug 01 '18 at 09:11
  • 5
    android.provider.Settings.Secure.getString(context.getContentResolver(), "bluetooth_address") return null in Android 10 – Bolt UIX Aug 12 '20 at 11:06
14

Access to the mac address has been deliberately removed:

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.

(from Android 6.0 Changes)

Thomasleveil
  • 95,867
  • 15
  • 119
  • 113
zmarties
  • 4,809
  • 22
  • 39
  • 2
    Yes. I had read that. But the API 23 BluetoothAdapter has the following: /** * Default MAC address reported to a client that does not have the * android.permission.LOCAL_MAC_ADDRESS permission. * * @hide */ public static final String DEFAULT_MAC_ADDRESS = "02:00:00:00:00:00"; So that implies there is meant to be some way to get it. (Perhaps not implemented yet? I cling to hope.) – Eric Oct 28 '15 at 13:03
  • 3
    The LOCAL_MAC_ADDRESS permission can only be used by system apps and it's unlikely that Google is going to change that. – David Brown Jan 31 '16 at 16:43
6

You can access Mac address from the file "/sys/class/net/" + networkInterfaceName+ "/address" ,where networkInterfaceName can be wlan0 or eth1.But Its permission may be read-protected,so it may not work in some devices. I am also attaching the code part which i got from SO.

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 exp) {

            exp.printStackTrace();
        } 
        return "";
    }
Jinosh P
  • 341
  • 2
  • 8
6

First the following permissions have to be added to Manifest;

<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.LOCAL_MAC_ADDRESS" />

Then,

public static final String SECURE_SETTINGS_BLUETOOTH_ADDRESS = "bluetooth_address";

String macAddress = Settings.Secure.getString(getContentResolver(), SECURE_SETTINGS_BLUETOOTH_ADDRESS);

After that the application has to be signed with OEM / System key. Tested and verified on Android 8.1.0.

Samantha
  • 921
  • 9
  • 12
4

Please use the below code to get the bluetooth mac address. let me know if any issues.

private String getBluetoothMacAddress() {
    BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
    String bluetoothMacAddress = "";
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M){
        try {
            Field mServiceField = bluetoothAdapter.getClass().getDeclaredField("mService");
            mServiceField.setAccessible(true);

            Object btManagerService = mServiceField.get(bluetoothAdapter);

            if (btManagerService != null) {
                bluetoothMacAddress = (String) btManagerService.getClass().getMethod("getAddress").invoke(btManagerService);
            }
        } catch (NoSuchFieldException e) {

        } catch (NoSuchMethodException e) {

        } catch (IllegalAccessException e) {

        } catch (InvocationTargetException e) {

        }
    } else {
        bluetoothMacAddress = bluetoothAdapter.getAddress();
    }
    return bluetoothMacAddress;
}
RaghavPai
  • 652
  • 9
  • 14
  • 4
    tip: reflection for using blacklisted API is never good solution and it might hit you in the face with next Android update – Ewoks Aug 01 '18 at 09:07
3

Getting the MAC address via reflection can look like this:

private static String getBtAddressViaReflection() {
    BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
    Object bluetoothManagerService = new Mirror().on(bluetoothAdapter).get().field("mService");
    if (bluetoothManagerService == null) {
        Log.w(TAG, "couldn't find bluetoothManagerService");
        return null;
    }
    Object address = new Mirror().on(bluetoothManagerService).invoke().method("getAddress").withoutArgs();
    if (address != null && address instanceof String) {
        Log.w(TAG, "using reflection to get the BT MAC address: " + address);
        return (String) address;
    } else {
        return null;
    }
}

using a reflection library (net.vidageek:mirror) but you'll get the idea.

p2pkit
  • 1,159
  • 8
  • 11
  • Code does not work. With the lib it always return null on serveral devices with different API levels – glethien Feb 23 '17 at 13:28
  • 1
    I just tried the code on a few devices and always got a mac address back (tested with targetSDK 22 on devices with 4.4, 5.0, 5.1 and 6.0) – p2pkit Mar 07 '17 at 10:56
  • 6
    On the Pixel 2 version of Android 8.0 Oreo this method won't work any more. I'm getting java.lang.reflect.InvocationTargetException Caused by: java.lang.SecurityException: Need LOCAL_MAC_ADDRESS permission: Neither user 10141 nor current process has android.permission.LOCAL_MAC_ADDRESS. – Andreas Oct 19 '17 at 23:36
  • 1
    Google seems to have rolled out the 'fix' to any device that's getting Android 8.1. A Nexus 5X updated to the preview of 8.1 also gets the exception. As a small consolation, Google has started to show the own Bluetooth MAC in the Bluetooth Settings UI, so at least users could manually copy it into an app that needs it. – Andreas Nov 02 '17 at 15:50
  • I can confirm that manually entering and then using the MAC address works for my application to establish a pair-free connection. – Albert Armea Mar 18 '18 at 23:25
  • LOCAL_MAC_ADDRESS shows system permission is required & always return null in android 10 – Bolt UIX Aug 12 '20 at 12:08
1

Since below method return null for android O.

String macAddress = android.provider.Settings.Secure.getString(context.getContentResolver(), "bluetooth_address");

I found new way to get Bluetooth Mac address, you can try by using below command line.

su strings /data/misc/bluedroid/bt_config.conf | grep Address

NOTE: In my case, i was working with root device so my app has super user permission.

amit semwal
  • 345
  • 3
  • 16
0

As it turns out, I ended up not getting the MAC address from Android. The bluetooth device ended up providing the Android device MAC address, which was stored and then used when needed. Yeah it seems a little funky but on the project I was on, the bluetooth device software was also being developed and this turned out to be the best way to deal with the situation.

Eric
  • 781
  • 1
  • 10
  • 18
-1

Worked great

 private String getBluetoothMacAddress() {
        BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        String bluetoothMacAddress = "";
        try {
            Field mServiceField = bluetoothAdapter.getClass().getDeclaredField("mService");
            mServiceField.setAccessible(true);

            Object btManagerService = mServiceField.get(bluetoothAdapter);

            if (btManagerService != null) {
                bluetoothMacAddress = (String) btManagerService.getClass().getMethod("getAddress").invoke(btManagerService);
            }
        } catch (NoSuchFieldException | NoSuchMethodException | IllegalAccessException | InvocationTargetException ignore) {

        }
        return bluetoothMacAddress;
    }
Vinayak
  • 6,056
  • 1
  • 32
  • 30