Obtener programáticamente la MAC de un dispositivo Android

93

Necesito obtener la dirección MAC de mi dispositivo Android usando Java. He buscado en línea, pero no he encontrado nada útil.

TSW1985
fuente
Por favor, compruebe esta solución, me funciona stackoverflow.com/questions/31329733/…
Gorio
Desde Android M, esta api está en desuso, use esto por ahora: stackoverflow.com/questions/31329733/…
Ehud

Respuestas:

115

Como ya se señaló en el comentario, la dirección MAC se puede recibir a través de WifiManager .

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

Además, no olvide agregar los permisos adecuados en su AndroidManifest.xml

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

Consulte los cambios de Android 6.0 .

Para brindar a los usuarios una mayor protección de datos, a partir de esta versión, Android elimina el acceso programático al identificador de hardware local del dispositivo para las aplicaciones que utilizan las API de Wi-Fi y Bluetooth. Los métodos WifiInfo.getMacAddress () y BluetoothAdapter.getAddress () ahora devuelven un valor constante de 02: 00: 00: 00: 00: 00.

Para acceder a los identificadores de hardware de dispositivos externos cercanos a través de escaneos de Bluetooth y Wi-Fi, su aplicación ahora debe tener los permisos ACCESS_FINE_LOCATION o ACCESS_COARSE_LOCATION.

Konrad Reiche
fuente
11
También es solo una nota, a veces no se puede extraer la dirección mac porque el wifi está apagado en el dispositivo
sbrichards
3
El blog vinculado también explica cómo encontrar esta dirección MAC de una manera más general que no asume que la interfaz de red usa una conexión WiFi.
Stephen C
Recuerde usar el contexto para llamar a getSystemService.
Tito Leiva
Esto es excelente para teléfonos y tabletas Android que usan Wifi, pero estoy tratando de obtener la dirección MAC de Ethernet en una tableta Android Gingerbread antigua que puede usar Wifi o Ethernet. ¿Alguna idea sobre cómo verificar la dirección MAC de Ethernet? Gracias.
Seth
@sbrichards ¿a qué te refieres con WiFi apagado?
peterchaula
34

Obtener la dirección MAC WifiInfo.getMacAddress()no funcionará en Marshmallow y superior, se ha desactivado y devolverá el valor constante de02:00:00:00:00:00 .

minipif
fuente
3
Cual es la alternativa?
Sam
2
@SameerThigale Depende de lo que intentes lograr. La idea detrás de esto es que probablemente no deberías intentar obtener la dirección MAC.
minipif
No estoy seguro de por qué, pero no puedo encontrar una nota obsoleta en el documento de API vinculado. ¿Quizás cambiaron de opinión sobre esto?
DBX12
1
@ DBX12 El método en sí no está marcado como obsoleto, aunque no está documentado. El segundo enlace apunta a una nota oficial al respecto.
minipif
25
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";
}
pm dubey
fuente
2
Sigue mostrándome "02: 00: 00: 00: 00: 00" en Android 7.1.
desarrollador de Android
Debe probarse en un dispositivo físico en lugar de un emulador o dispositivo virtual
pm dubey
1
Todavía funciona No olvide otorgar permiso de Internet en el archivo de manifiesto.
pm dubey
2
Ya no funciona en Android marshmallow y superior, ya que devolverá el valor de "02: 00: 00: 00: 00: 00"
SweArmy
1
Funciona. He estado usando este código durante mucho tiempo. Todavía funciona en Android Q.
Rupam Das
14

¡Fundé esta solución en http://robinhenniges.com/en/android6-get-mac-address-programically y está funcionando para mí! ¡La esperanza ayuda!

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 "";
}
Tiziano Bruschetta
fuente
Supongo que es porque necesitamos eliminar el último carácter ":". Este código tiene 2 años y probablemente no sea la mejor manera de hacerlo, debería optimizarlo
Tiziano Bruschetta
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;
}

tener otros camino aquí

ademar111190
fuente
¿ macAddressAlguna vez lo será null?
Max Heiber
¿Qué parámetro debe pasar como contexto mientras se llama a la función?
Donal
@Donal, ¿te refieres al Context context? Si es así, cualquier contexto debería funcionar. developer.android.com/reference/android/content/…
ademar111190
8

Está trabajando con 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 "";
    }
}
Keshav Gera
fuente
Gracias Qadir Hussain
Keshav Gera
4

Ya no puede obtener la dirección MAC de hardware de un dispositivo Android. Los métodos WifiInfo.getMacAddress () y BluetoothAdapter.getAddress () devolverán 02: 00: 00: 00: 00: 00. Esta restricción se introdujo en Android 6.0.

Pero Rob Anderson encontró una solución que funciona para <Marshmallow: https://stackoverflow.com/a/35830358

Luvnish Monga
fuente
3

Puede obtener la dirección mac:

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

Establecer permisos en Menifest.xml

<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"></uses-permission>
Manoj Tarkar
fuente
La pregunta es sobre cómo obtener mac del dispositivo Android, no del enrutador wifi.
hina abbasi
3

Usando este método simple

WifiManager wm = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
            String WLANMAC = wm.getConnectionInfo().getMacAddress();
Abdulhakim Zeinu
fuente
2

Tomado de las fuentes de Android aquí . Este es el código real que muestra su DIRECCIÓN MAC en la aplicación de configuración del sistema.

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);
}
Fernandohur
fuente
¿Cómo debo acceder a esto en una clase sin actividad o en un fragmento?
Caza
Necesitará un contexto para obtener un WifiManager(ie WifiManager mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);).
fernandohur
5
si prueba este código, 02:00:00:00:00:00obtengo la dirección mac, no la identificación de mac wifi real
Hunt
0

Sé que esta es una pregunta muy antigua, pero hay un método más para hacerlo. A continuación, el código se compila pero no lo he probado. Puede escribir código C y usar JNI (Java Native Interface) para obtener la dirección MAC. Aquí está el ejemplo de código de actividad principal:

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);
}

Y el archivo de diseño, 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>

Archivo de manifiesto, no sabía qué permisos agregar, así que agregué algunos.

<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>

Implementación en C de la función get_mac_addr.

/* 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;
}

Y finalmente, archivo CMakeLists.txt

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)
Efe C.
fuente
-3

Creo que acabo de encontrar una manera de leer direcciones MAC sin permiso de UBICACIÓN: ejecutar ip linky analizar su salida. (probablemente podría hacer lo similar mirando el código fuente de este binario)

Dios mío
fuente