Recupero programmatico del MAC di un dispositivo Android


91

Devo ottenere l'indirizzo MAC del mio dispositivo Android utilizzando Java. Ho cercato online, ma non ho trovato nulla di utile.





Per favore controlla questa soluzione, funziona per me stackoverflow.com/questions/31329733/…
Gorio,

Da Android M questa API è deprecata, per ora usala
Ehud

Risposte:


114

Come già sottolineato nel commento, l'indirizzo MAC può essere ricevuto tramite WifiManager .

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

Inoltre, non dimenticare di aggiungere le autorizzazioni appropriate nel tuo file AndroidManifest.xml

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

Fare riferimento alle modifiche ad Android 6.0 .

Per fornire agli utenti una maggiore protezione dei dati, a partire da questa versione, Android rimuove l'accesso programmatico all'identificatore hardware locale del dispositivo per le app che utilizzano le API Wi-Fi e Bluetooth. I metodi WifiInfo.getMacAddress () e BluetoothAdapter.getAddress () ora restituiscono un valore costante di 02: 00: 00: 00: 00: 00.

Per accedere agli identificatori hardware dei dispositivi esterni nelle vicinanze tramite Bluetooth e scansioni Wi-Fi, la tua app deve ora disporre delle autorizzazioni ACCESS_FINE_LOCATION o ACCESS_COARSE_LOCATION.


11
Anche solo una nota, a volte l'indirizzo mac non può essere estratto perché il wifi è spento sul dispositivo
sbrichards,

3
Il blog collegato spiega anche come trovare questo indirizzo MAC in un modo più generale che non presume che l'interfaccia di rete utilizzi la connessione WiFi.
Stephen C

Ricorda di utilizzare il contesto per chiamare getSystemService.
Tito Leiva

Questo è ottimo per telefoni e tablet Android che utilizzano Wi-Fi, ma sto cercando di ottenere l'indirizzo MAC Ethernet su un vecchio tablet Android Gingerbread che può utilizzare Wifi o Ethernet. qualche idea su come controllare l'indirizzo MAC Ethernet? Grazie.
Seth

@sbrichards cosa intendi per WiFi spento?
peterchaula

33

Ottenere l'indirizzo MAC WifiInfo.getMacAddress()non funzionerà su Marshmallow e versioni successive, è stato disabilitato e restituirà il valore costante di02:00:00:00:00:00 .


3
Qual è l'alternativa?
Sam

2
@SameerThigale Dipende da cosa stai cercando di ottenere. L'idea alla base di questo è che probabilmente non dovresti cercare di ottenere l'indirizzo MAC.
minipif

Non sono sicuro del perché, ma non riesco a trovare una nota deprecata nel documento api collegato. Forse hanno cambiato idea su questo?
DBX12

1
@ DBX12 Il metodo stesso non è contrassegnato come deprecato, sebbene non sia documentato. Il secondo collegamento indica una nota ufficiale a riguardo.
minipif

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

2
Continua a mostrarmi "02: 00: 00: 00: 00: 00" su Android 7.1.
sviluppatore Android

Deve essere testato su un dispositivo fisico piuttosto che su un emulatore o un dispositivo virtuale
pm dubey

Questo approccio funziona ancora? o è stato risolto / risolto sul lato del sistema operativo?
CasualT

1
Funziona ancora Non dimenticare di dare il permesso a Internet nel file Manifest.
pm dubey

1
Non funziona più su Android Marshmallow e versioni successive poiché restituirà il valore "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;
}

avere altri modi qui


Lo sarà macAddressmai null?
Max Heiber

quale parametro deve passare come contesto durante la chiamata di funzione?
Donal

@Donal intendi il Context context? se sì, qualsiasi contesto dovrebbe funzionare. developer.android.com/reference/android/content/…
ademar111190

11

Ho trovato questa soluzione da http://robinhenniges.com/en/android6-get-mac-address-programmaticamente e per me funziona! La speranza aiuta!

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

Immagino sia perché dobbiamo rimuovere l'ultimo carattere ":". Questo codice ha 2 anni e probabilmente non è il modo migliore per farlo, dovresti ottimizzarlo
Tiziano Bruschetta

7

Funziona 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 "";
    }
}

Grazie Qadir Hussain
Keshav Gera

3

Puoi ottenere l'indirizzo mac:

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

Imposta l'autorizzazione in Menifest.xml

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

La domanda riguarda l'acquisto del Mac del dispositivo Android, non del router Wi-Fi.
hina abbasi

3

Non è più possibile ottenere l'indirizzo MAC hardware di un dispositivo Android. I metodi WifiInfo.getMacAddress () e BluetoothAdapter.getAddress () restituiranno 02: 00: 00: 00: 00: 00. Questa restrizione è stata introdotta in Android 6.0.

Ma Rob Anderson ha trovato una soluzione che funziona per <Marshmallow: https://stackoverflow.com/a/35830358


2

Tratto dalle fonti Android qui . Questo è il codice effettivo che mostra il tuo INDIRIZZO MAC nell'app delle impostazioni 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);
}

come dovrei accedervi nella classe di non attività o nel frammento?
Caccia il

Avrai bisogno di un contesto per ottenere un WifiManager(ie WifiManager mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);).
fernandohur

5
se prova questo codice ottengo l' 02:00:00:00:00:00indirizzo mac non l'ID mac wifi effettivo
Hunt

2

Utilizzando questo semplice metodo

WifiManager wm = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
            String WLANMAC = wm.getConnectionInfo().getMacAddress();

0

So che questa è una domanda molto vecchia, ma c'è un altro metodo per farlo. Di seguito viene compilato il codice ma non l'ho provato. È possibile scrivere del codice C e utilizzare JNI (Java Native Interface) per ottenere l'indirizzo MAC. Ecco il codice dell'attività principale di esempio:

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

E il file di layout, 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>

File manifest, non sapevo quali autorizzazioni aggiungere, quindi ne ho aggiunte alcune.

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

Implementazione in C della funzione 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;
}

E infine, il file 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)


-3

Penso di aver appena trovato un modo per leggere gli indirizzi MAC senza il permesso di LOCATION: eseguire ip linke analizzare il suo output. (potresti probabilmente fare lo stesso guardando il codice sorgente di questo binario)

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.