Programmatically getting the MAC of an Android device
Asked Answered
C

14

108

I need to obtain the MAC address of my android device using Java. I've searched online, but I haven't found anything useful.

Chilt answered 29/7, 2012 at 1:17 Comment(6)
programminglinuxblog.blogspot.pt/2011/06/…Piggott
possible duplicate of How to obtain MAC address of WiFi network interface?Sodium
possible duplicate of How to find MAC address of an Android device programaticallySelfdeprecating
Please check this solution, it works for me #31330233Urinary
From android M this api is deprecated, use this for now: #31330233Is
This ` ip link | grep -A1 wlan0 ` works on Android 9 from #58464158Iives
L
125

As was already pointed out in the comment, the MAC address can be received via the WifiManager.

WifiManager manager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
WifiInfo info = manager.getConnectionInfo();
String address = info.getMacAddress();

Also do not forget to add the appropriate permissions into your AndroidManifest.xml

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

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.

Loveinidleness answered 29/7, 2012 at 1:32 Comment(6)
Also just a note, sometimes mac address can't be pulled because wifi is off on the deviceAtiptoe
The linked blog also explains how to find this MAC address in a more general way that doesn't assume the network interface uses WiFi connection.Unyielding
Remember use the context to call the getSystemService.Ferrell
This is great for Android phones and tablets using Wifi, but I am trying to get the Ethernet MAC address on an old Gingerbread Android tablet that can use either Wifi or Ethernet. any thoughts on how to check the Ethernet MAC address? Thanks.Coycoyle
@Atiptoe what do you mean by WiFi being off?Calida
It's not useable anymore!Rubious
V
44

Getting the MAC address through WifiInfo.getMacAddress() won't work on Marshmallow and above, it has been disabled and will return the constant value of 02:00:00:00:00:00.

Valediction answered 25/2, 2016 at 23:3 Comment(4)
Whats the alternative?Arrangement
@SameerThigale Depends what you're trying to achieve. The idea behind this is you probably shouldn't be trying to get the MAC address.Valediction
I'm not sure why, but I can not find a deprecated note in linked api doc. Maybe they changed their mind about this?Royalty
@Royalty The method itself isn't marked as deprecated, although it's not documented. The second link points to an official note about it.Valediction
P
30
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";
}
Pruter answered 30/9, 2016 at 12:53 Comment(7)
It keeps showing me "02:00:00:00:00:00" on Android 7.1.Alamein
It must be tested on Physical device rather than emulator or virtual devicePruter
Does this work around approach still work? or did it get patched out/fixed on the OS side?Irremovable
It still works.Do not forget to give internet permission in Manifest file.Pruter
It no longer works on android marshmallow and above as it will return the value of "02:00:00:00:00:00"Caster
It works. I have been using this code for a very long time. It still works on Android Q.Modie
Tested on physical devices with Android 6, 7 and 8Hooten
A
17

I founded this solution from http://robinhenniges.com/en/android6-get-mac-address-programmatically and it's working for me! Hope helps!

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) {
                String hex = Integer.toHexString(b & 0xFF);
                if (hex.length() == 1)
                    hex = "0".concat(hex);
                res1.append(hex.concat(":"));
            }

            if (res1.length() > 0) {
                res1.deleteCharAt(res1.length() - 1);
            }
            return res1.toString();
        }
    } catch (Exception ex) {
    }
    return "";
}
Annmaria answered 6/6, 2017 at 10:35 Comment(1)
Im supposing it’s because we need to remove the last “:” character. This code is 2 years old and probably itsn’t the best way for doing that, you should optimize itAnnmaria
V
11
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />

public String getMacAddress(Context context) {
    WifiManager wimanager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
    String macAddress = wimanager.getConnectionInfo().getMacAddress();
    if (macAddress == null) {
        macAddress = "Device don't have mac address or wi-fi is disabled";
    }
    return macAddress;
}

have others way here

Varicose answered 4/3, 2013 at 14:35 Comment(3)
Will macAddress ever be null?Septicidal
which param need to pass as context while function call?Gutter
@Gutter do you mean the Context context ? if yes any context should work. developer.android.com/reference/android/content/…Varicose
M
9

Its Working with Marshmallow

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 "";
    }
}
Megalopolis answered 15/6, 2017 at 12:9 Comment(0)
D
5

You can no longer get the hardware MAC address of a android device. WifiInfo.getMacAddress() and BluetoothAdapter.getAddress() methods will return 02:00:00:00:00:00. This restriction was introduced in Android 6.0.

But Rob Anderson found a solution which is working for < Marshmallow : https://stackoverflow.com/a/35830358

Dahomey answered 2/9, 2016 at 11:25 Comment(0)
R
3

You can get mac address:

WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
WifiInfo wInfo = wifiManager.getConnectionInfo();
String mac = wInfo.getMacAddress();

Set Permission in Menifest.xml

<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"></uses-permission>
Relieve answered 16/7, 2014 at 11:10 Comment(1)
Question is about getting mac of android device, not of wifi router.Riffraff
M
3

Using this simple method

WifiManager wm = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
            String WLANMAC = wm.getConnectionInfo().getMacAddress();
Mesics answered 4/4, 2019 at 7:25 Comment(0)
C
2

Taken from the Android sources here. This is the actual code that shows your MAC ADDRESS in the system's settings app.

private void refreshWifiInfo() {
    WifiInfo wifiInfo = mWifiManager.getConnectionInfo();

    Preference wifiMacAddressPref = findPreference(KEY_MAC_ADDRESS);
    String macAddress = wifiInfo == null ? null : wifiInfo.getMacAddress();
    wifiMacAddressPref.setSummary(!TextUtils.isEmpty(macAddress) ? macAddress
            : getActivity().getString(R.string.status_unavailable));

    Preference wifiIpAddressPref = findPreference(KEY_CURRENT_IP_ADDRESS);
    String ipAddress = Utils.getWifiIpAddresses(getActivity());
    wifiIpAddressPref.setSummary(ipAddress == null ?
            getActivity().getString(R.string.status_unavailable) : ipAddress);
}
Corelli answered 11/12, 2013 at 15:41 Comment(3)
how should i access this in non activity class or fragment ?Downey
You will need a context to obtain a WifiManager (i.e. WifiManager mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);).Corelli
if it try this code i am getting 02:00:00:00:00:00 mac address not the actual wifi mac idDowney
I
2

I know this is a very old question but there is one more method to do this. Code below compiles without errors but I haven't tried it. You can write some C code and use JNI (Java Native Interface) to get MAC address. Here is the example main activity code:

package com.example.getmymac;

import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;

public class GetMyMacActivity extends AppCompatActivity {
    static { // here we are importing native library.
        // name of the library is libnet-utils.so, in cmake and java code
        // we just use name "net-utils".
        System.loadLibrary("net-utils");
    }

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main_screen);

        // some debug text and a TextView.
        Log.d(NetUtilsActivity.class.getSimpleName(), "Starting app...");
        TextView text = findViewById(R.id.sample_text);

        // the get_mac_addr native function, implemented in C code.
        byte[] macArr = get_mac_addr(null);
        // since it is a byte array, we format it and convert to string.
        String val = String.format("%02x:%02x:%02x:%02x:%02x:%02x",
                macArr[0], macArr[1], macArr[2],
                macArr[3], macArr[4], macArr[5]);
        // print it to log and TextView.
        Log.d(NetUtilsActivity.class.getSimpleName(), val);
        text.setText(val);
    }

    // here is the prototype of the native function.
    // use native keyword to indicate it is a native function,
    // implemented in C code.
    private native byte[] get_mac_addr(String interface_name);
}

And the layout file, main_screen.xml:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/sample_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/app_name"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>

</androidx.constraintlayout.widget.ConstraintLayout>

Manifest file, I didn't know what permissions to add so I added some.

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.getmymac">

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

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

        <activity android:name=".GetMyMacActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
    </application>
</manifest>

C implementation of get_mac_addr function.

/* length of array that MAC address is stored. */
#define MAC_ARR_LEN 6

#define BUF_SIZE 256

#include <jni.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <unistd.h>

#define ERROR_IOCTL 1
#define ERROR_SOCKT 2

static jboolean
cstr_eq_jstr(JNIEnv *env, const char *cstr, jstring jstr) {
    /* see [this](https://stackoverflow.com/a/38204842) */

    jstring cstr_as_jstr = (*env)->NewStringUTF(env, cstr);
    jclass cls = (*env)->GetObjectClass(env, jstr);
    jmethodID method_id = (*env)->GetMethodID(env, cls, "equals", "(Ljava/lang/Object;)Z");
    jboolean equal = (*env)->CallBooleanMethod(env, jstr, method_id, cstr_as_jstr);
    return equal;
}

static void
get_mac_by_ifname(jchar *ifname, JNIEnv *env, jbyteArray arr, int *error) {
    /* see [this](https://stackoverflow.com/a/1779758) */

    struct ifreq ir;
    struct ifconf ic;
    char buf[BUF_SIZE];
    int ret = 0, sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);

    if (sock == -1) {
        *error = ERROR_SOCKT;
        return;
    }

    ic.ifc_len = BUF_SIZE;
    ic.ifc_buf = buf;

    ret = ioctl(sock, SIOCGIFCONF, &ic);
    if (ret) {
        *error = ERROR_IOCTL;
        goto err_cleanup;
    }

    struct ifreq *it = ic.ifc_req; /* iterator */
    struct ifreq *end = it + (ic.ifc_len / sizeof(struct ifreq));

    int found = 0; /* found interface named `ifname' */

    /* while we find an interface named `ifname' or arrive end */
    while (it < end && found == 0) {
        strcpy(ir.ifr_name, it->ifr_name);
        ret = ioctl(sock, SIOCGIFFLAGS, &ir);
        if (ret == 0) {
            if (!(ir.ifr_flags & IFF_LOOPBACK)) {
                ret = ioctl(sock, SIOCGIFHWADDR, &ir);
                if (ret) {
                    *error = ERROR_IOCTL;
                    goto err_cleanup;
                }

                if (ifname != NULL) {
                    if (cstr_eq_jstr(env, ir.ifr_name, ifname)) {
                        found = 1;
                    }
                }
            }
        } else {
            *error = ERROR_IOCTL;
            goto err_cleanup;
        }
        ++it;
    }

    /* copy the MAC address to byte array */
    (*env)->SetByteArrayRegion(env, arr, 0, 6, ir.ifr_hwaddr.sa_data);
    /* cleanup, close the socket connection */
    err_cleanup: close(sock);
}

JNIEXPORT jbyteArray JNICALL
Java_com_example_getmymac_GetMyMacActivity_get_1mac_1addr(JNIEnv *env, jobject thiz,
                                                          jstring interface_name) {
    /* first, allocate space for the MAC address. */
    jbyteArray mac_addr = (*env)->NewByteArray(env, MAC_ARR_LEN);
    int error = 0;

    /* then just call `get_mac_by_ifname' function */
    get_mac_by_ifname(interface_name, env, mac_addr, &error);

    return mac_addr;
}

And finally, CMakeLists.txt file

cmake_minimum_required(VERSION 3.4.1)
add_library(net-utils SHARED src/main/cpp/net-utils.c)
target_link_libraries(net-utils android log)
Ichthyoid answered 13/9, 2020 at 17:20 Comment(1)
I tried this on Android 30, and its returning all zeros.Ambitendency
P
0
Please add in AndroidManifest
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission 
    android:name="android.permission.ACCESS_COARSE_LOCATION"/>

// Get MAC Address, in an activity... String strMACAddress = getMacAddress_For_New_Tab(this);

public static String getMacAddress_For_New_Tab(Context context)
{
    String macAddress=null;
    WifiManager objwifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
    boolean wifiEnabled = objwifiManager.isWifiEnabled();
    int LoopCounter=0;
    while (macAddress==null) // Required if HD Security is Enabled.
    {
        if (wifiEnabled)
        {
            objwifiManager.setWifiEnabled(false);
            objwifiManager.reconnect();
            objwifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
        }

        if (android.os.Build.VERSION.SDK_INT > Build.VERSION_CODES.M) //M Means Marshmellow.
        {
            // Do something for lollipop and above versions
            macAddress = getMacAddr();
        } else
        {
            // do something for phones running an SDK before lollipop
            macAddress = objwifiManager.getConnectionInfo().getMacAddress();
        }

        // Required if HD Security is Enabled.
        LoopCounter++;
        if (LoopCounter>2) break;
    }
    if (wifiEnabled)
    {
        objwifiManager.setWifiEnabled(wifiEnabled); // Retain Old.
        objwifiManager.reconnect();
        /*try
        {
            Thread.sleep(100);
        } catch (InterruptedException e)
        {
            e.printStackTrace();
        }*/
    }
    return macAddress; //Device don't have mac address or wi-fi is disabled if it is null.
}

public static String getMacAddr()
{
    try {
        List<NetworkInterface> all = Collections.list(NetworkInterface.getNetworkInterfaces());
        for (NetworkInterface nif : all)
        {
            if (CurrentStatus.ModelName.toUpperCase().equals("LENOVO TB-8705X"))
            {
                Thread.sleep(50);
            }
            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) + ":");
                res1.append(String.format("%02X:",b));
            }

            if (res1.length() > 0) {
                res1.deleteCharAt(res1.length() - 1);
            }
            return res1.toString();
        }
    } catch (Exception ex) {
    }
    return "";
}
Pleurisy answered 6/10, 2022 at 7:12 Comment(2)
This worked for me, I am using Android Version 10 and model is "LENOVO TB-8705X".Pleurisy
It just disable the wifi, and get the MAC AddressPleurisy
I
-2

This ip link | grep -A1 wlan0 command works on Android 9 from How to determine wifi hardware address in Termux

Iives answered 19/12, 2019 at 9:18 Comment(0)
G
-3

I think I just found a way to read MAC addresses without LOCATION permission: Run ip link and parse its output. (you could probably do the similar by looking at this binary's source code)

Glutamate answered 19/1, 2018 at 8:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.