Obtenir le MAC d'un appareil Android par programme

91

J'ai besoin d'obtenir l'adresse MAC de mon appareil Android en utilisant Java. J'ai cherché en ligne, mais je n'ai rien trouvé d'utile.

TSW1985
la source
Veuillez vérifier cette solution, cela fonctionne pour moi stackoverflow.com/questions/31329733/…
Gorio
Depuis Android M, cette API est obsolète, utilisez-la pour le moment: stackoverflow.com/questions/31329733/...
Ehud

Réponses:

114

Comme cela a déjà été souligné dans le commentaire, l'adresse MAC peut être reçue via le WifiManager .

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

N'oubliez pas non plus d'ajouter les autorisations appropriées dans votre AndroidManifest.xml

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

Veuillez vous référer aux changements d' Android 6.0 .

Pour offrir aux utilisateurs une meilleure protection des données, à partir de cette version, Android supprime l'accès par programmation à l'identifiant matériel local de l'appareil pour les applications utilisant les API Wi-Fi et Bluetooth. Les méthodes WifiInfo.getMacAddress () et BluetoothAdapter.getAddress () renvoient désormais une valeur constante de 02: 00: 00: 00: 00: 00.

Pour accéder aux identifiants matériels des appareils externes à proximité via des analyses Bluetooth et Wi-Fi, votre application doit désormais disposer des autorisations ACCESS_FINE_LOCATION ou ACCESS_COARSE_LOCATION.

Konrad Reiche
la source
11
Aussi juste une note, parfois l'adresse mac ne peut pas être extraite parce que le wifi est désactivé sur l'appareil
sbrichards
3
Le blog lié explique également comment trouver cette adresse MAC d'une manière plus générale qui ne suppose pas que l'interface réseau utilise une connexion WiFi.
Stephen C
N'oubliez pas d'utiliser le contexte pour appeler le getSystemService.
Tito Leiva
C'est génial pour les téléphones et tablettes Android utilisant le Wifi, mais j'essaie d'obtenir l'adresse MAC Ethernet sur une ancienne tablette Android Gingerbread qui peut utiliser Wifi ou Ethernet. des réflexions sur la façon de vérifier l'adresse MAC Ethernet? Merci.
Seth
@sbrichards qu'entendez-vous par WiFi éteint?
peterchaula
34

Obtenir l'adresse MAC WifiInfo.getMacAddress()ne fonctionnera pas sur Marshmallow et les versions ultérieures, elle a été désactivée et renverra la valeur constante de02:00:00:00:00:00 .

minipif
la source
3
Quelle est l'alternative?
Sam
2
@SameerThigale Dépend de ce que vous essayez d'accomplir. L'idée derrière cela est que vous ne devriez probablement pas essayer d'obtenir l'adresse MAC.
minipif du
Je ne sais pas pourquoi, mais je ne trouve pas de note obsolète dans la doc api liée. Peut-être ont-ils changé d'avis à ce sujet?
DBX12
1
@ DBX12 La méthode elle-même n'est pas marquée comme obsolète, bien qu'elle ne soit pas documentée. Le deuxième lien pointe vers une note officielle à ce sujet.
minipif du
24
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
la source
2
Il continue de me montrer "02: 00: 00: 00: 00: 00" sur Android 7.1.
développeur android
Il doit être testé sur un périphérique physique plutôt qu'un émulateur ou un périphérique virtuel
pm dubey
Cette approche de contournement fonctionne-t-elle toujours? ou a-t-il été corrigé / corrigé du côté du système d'exploitation?
CasualT
1
Cela fonctionne toujours.N'oubliez pas de donner l'autorisation Internet dans le fichier Manifest.
pm dubey
1
Il ne fonctionne plus sur Android guimauve et au-dessus car il renverra la valeur de "02: 00: 00: 00: 00: 00"
SweArmy
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;
}

en avoir d'autres ici

ademar111190
la source
Sera macAddressjamais null?
Max Heiber
quel paramètre doit passer comme contexte lors de l'appel de fonction?
Donal
@Donal voulez-vous dire le Context context? si oui, n'importe quel contexte devrait fonctionner. developer.android.com/reference/android/content/…
ademar111190
11

J'ai fondé cette solution sur http://robinhenniges.com/en/android6-get-mac-address-programmatically et ça marche pour moi! L'espoir aide!

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
la source
Je suppose que c'est parce que nous devons supprimer le dernier caractère «:». Ce code a 2 ans et ce n'est probablement pas la meilleure façon de le faire, vous devriez l'optimiser
Tiziano Bruschetta
7

Son travail avec la guimauve

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
la source
Merci Qadir Hussain
Keshav Gera
4

Vous ne pouvez plus obtenir l'adresse MAC matérielle d'un appareil Android. Les méthodes WifiInfo.getMacAddress () et BluetoothAdapter.getAddress () renverront 02: 00: 00: 00: 00: 00. Cette restriction a été introduite dans Android 6.0.

Mais Rob Anderson a trouvé une solution qui fonctionne pour <Marshmallow: https://stackoverflow.com/a/35830358

Luvnish Monga
la source
3

Vous pouvez obtenir l'adresse Mac:

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

Définir l'autorisation dans Menifest.xml

<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"></uses-permission>
Manoj Tarkar
la source
La question est d'obtenir le mac de l'appareil Android, pas du routeur wifi.
hina abbasi le
2

Tiré des sources Android ici . Il s'agit du code réel qui affiche votre ADRESSE MAC dans l'application des paramètres du système.

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
la source
comment dois-je y accéder dans une classe ou un fragment sans activité?
Chasse
Vous aurez besoin d'un contexte pour obtenir un WifiManager(ie WifiManager mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);).
fernandohur
5
s'il essaie ce code, 02:00:00:00:00:00j'obtiens l'adresse mac et non l'identifiant mac wifi réel
Hunt
2

En utilisant cette méthode simple

WifiManager wm = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
            String WLANMAC = wm.getConnectionInfo().getMacAddress();
Abdulhakim Zeinu
la source
0

Je sais que c'est une question très ancienne, mais il existe une autre méthode pour y parvenir. Ci-dessous le code compile mais je ne l'ai pas essayé. Vous pouvez écrire du code C et utiliser JNI (Java Native Interface) pour obtenir l'adresse MAC. Voici l'exemple de code d'activité principale:

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

Et le fichier de mise en page, 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>

Fichier manifeste, je ne savais pas quelles autorisations ajouter, alors j'en ai ajouté.

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

Implémentation en C de la fonction 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;
}

Et enfin, fichier 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.
la source
-3

Je pense que je viens de trouver un moyen de lire les adresses MAC sans l'autorisation LOCATION: exécutez ip linket analysez sa sortie. (vous pourriez probablement faire la même chose en regardant le code source de ce binaire)

Mon Dieu
la source