Secara terprogram mendapatkan MAC dari perangkat Android

93

Saya perlu mendapatkan alamat MAC perangkat android saya menggunakan Java. Saya telah mencari secara online, tetapi saya belum menemukan sesuatu yang berguna.

TSW1985
sumber
Silakan periksa solusi ini, ini berfungsi untuk saya stackoverflow.com/questions/31329733/…
Gorio
Dari android M api ini tidak digunakan lagi, gunakan ini untuk saat ini: stackoverflow.com/questions/31329733/…
Ehud

Jawaban:

115

Seperti yang sudah dijelaskan di komentar, alamat MAC dapat diterima melalui WifiManager .

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

Juga jangan lupa untuk menambahkan hak akses yang sesuai ke file AndroidManifest.xml

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

Silakan merujuk ke Perubahan Android 6.0 .

Untuk memberi pengguna perlindungan data yang lebih besar, mulai rilis ini, Android menghapus akses terprogram ke pengenal hardware lokal perangkat untuk aplikasi yang menggunakan Wi-Fi dan Bluetooth API. Metode WifiInfo.getMacAddress () dan BluetoothAdapter.getAddress () sekarang mengembalikan nilai konstan 02: 00: 00: 00: 00: 00.

Untuk mengakses pengenal hardware perangkat eksternal terdekat melalui pemindaian Bluetooth dan Wi-Fi, aplikasi Anda sekarang harus memiliki izin ACCESS_FINE_LOCATION atau ACCESS_COARSE_LOCATION.

Konrad Reiche
sumber
11
Juga hanya sebuah catatan, terkadang alamat mac tidak dapat ditarik karena wifi di perangkat
mati
3
Blog yang ditautkan juga menjelaskan cara menemukan alamat MAC ini dengan cara yang lebih umum yang tidak menganggap antarmuka jaringan menggunakan koneksi WiFi.
Stephen C
Ingatlah gunakan konteks untuk memanggil getSystemService.
Tito Leiva
Ini bagus untuk ponsel dan tablet Android yang menggunakan Wifi, tetapi saya mencoba mendapatkan alamat MAC Ethernet di tablet Android Gingerbread lama yang dapat menggunakan Wifi atau Ethernet. ada pemikiran tentang cara memeriksa alamat MAC Ethernet? Terima kasih.
Seth
@sbrichards apa yang Anda maksud dengan WiFi mati?
peterchaula
34

Mendapatkan alamat MAC WifiInfo.getMacAddress()tidak akan berfungsi di Marshmallow dan yang lebih baru, itu telah dinonaktifkan dan akan mengembalikan nilai konstan02:00:00:00:00:00 .

minipif
sumber
3
Apa alternatifnya?
Sam
2
@SameerThigale Tergantung apa yang ingin Anda capai. Ide di balik ini adalah Anda mungkin tidak boleh mencoba mendapatkan alamat MAC.
minipif
Saya tidak yakin mengapa, tetapi saya tidak dapat menemukan catatan usang di dokumen api tertaut. Mungkin mereka berubah pikiran tentang ini?
DBX12
1
@ DBX12 Metode itu sendiri tidak ditandai sebagai usang, meskipun tidak didokumentasikan. Tautan kedua menunjuk ke catatan resmi tentang itu.
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
sumber
2
Itu terus menampilkan saya "02: 00: 00: 00: 00: 00" di Android 7.1.
pengembang android
Ini harus diuji pada perangkat Fisik daripada emulator atau perangkat virtual
pm dubey
1
Masih berfungsi Jangan lupa berikan izin internet di file Manifest.
pm dubey
2
Ini tidak lagi berfungsi pada android marshmallow dan di atasnya karena akan mengembalikan nilai "02: 00: 00: 00: 00: 00"
SweArmy
1
Berhasil. Saya telah menggunakan kode ini untuk waktu yang sangat lama. Ini masih berfungsi di Android Q.
Rupam Das
14

Saya menemukan solusi ini dari http://robinhenniges.com/en/android6-get-mac-address-programmatically dan berhasil untuk saya! Semoga membantu!

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
sumber
Saya kira itu karena kita perlu menghapus karakter ":" terakhir. Kode ini berumur 2 tahun dan mungkin ini bukan cara terbaik untuk melakukan itu, Anda harus mengoptimalkannya
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;
}

ada cara lain di sini

ademar111190
sumber
Akankah macAddresspernah null?
Max Heiber
param mana yang perlu diteruskan sebagai konteks saat pemanggilan fungsi?
Donal
@Donal maksudmu Context context? jika ya, konteks apa pun harus bekerja. developer.android.com/reference/android/content/…
ademar111190
8

Bekerja dengan 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
sumber
Terima kasih Qadir Hussain
Keshav Gera
4

Anda tidak bisa lagi mendapatkan alamat MAC perangkat keras dari perangkat android. Metode WifiInfo.getMacAddress () dan BluetoothAdapter.getAddress () akan mengembalikan 02: 00: 00: 00: 00: 00. Batasan ini diperkenalkan di Android 6.0.

Tetapi Rob Anderson menemukan solusi yang berfungsi untuk <Marshmallow: https://stackoverflow.com/a/35830358

Luvnish Monga
sumber
3

Anda bisa mendapatkan alamat mac:

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

Setel Izin di Menifest.xml

<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"></uses-permission>
Manoj Tarkar
sumber
Pertanyaannya adalah tentang mendapatkan mac dari perangkat android, bukan dari router wifi.
hina abbasi
3

Menggunakan metode sederhana ini

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

Diambil dari sumber Android di sini . Ini adalah kode sebenarnya yang menunjukkan MAC ADDRESS Anda di aplikasi pengaturan sistem.

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
sumber
bagaimana cara mengakses ini di kelas atau fragmen non aktivitas?
Berburu
Anda akan membutuhkan konteks untuk mendapatkan WifiManager(yaitu WifiManager mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);).
fernandohur
5
jika mencoba kode ini saya mendapatkan 02:00:00:00:00:00alamat mac bukan id mac wifi yang sebenarnya
Berburu
0

Saya tahu ini adalah pertanyaan yang sangat lama tetapi ada satu metode lagi untuk melakukan ini. Di bawah kompilasi kode tetapi saya belum mencobanya. Anda dapat menulis beberapa kode C dan menggunakan JNI (Java Native Interface) untuk mendapatkan alamat MAC. Berikut adalah contoh kode aktivitas utama:

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

Dan file tata letak, 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 manifes, saya tidak tahu izin apa yang harus ditambahkan jadi saya menambahkan beberapa.

<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 implementasi fungsi 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;
}

Dan terakhir, 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)
Efe C.
sumber
-3

Saya rasa saya baru saja menemukan cara untuk membaca alamat MAC tanpa izin LOKASI: Jalankan ip linkdan parsing outputnya. (Anda mungkin bisa melakukan hal serupa dengan melihat kode sumber biner ini)

Tuhanku
sumber