Bir Android cihazın MAC'ini programlı olarak alma


93

Java kullanarak android cihazımın MAC adresini almam gerekiyor. İnternette arama yaptım, ancak yararlı bir şey bulamadım.





Lütfen bu çözümü kontrol edin, benim için çalışıyor stackoverflow.com/questions/31329733/…
Gorio

Android M'den bu api kullanımdan kaldırılmıştır, şimdilik bunu kullanın: stackoverflow.com/questions/31329733/…
Ehud

Yanıtlar:


115

Yorumda daha önce belirtildiği gibi, MAC adresi WifiManager aracılığıyla alınabilir .

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

Ayrıca, uygun izinleri sitenize eklemeyi unutmayın. AndroidManifest.xml

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

Lütfen Android 6.0 Değişikliklerine bakın .

Bu sürümden başlayarak, kullanıcılara daha fazla veri koruması sağlamak için Android, Wi-Fi ve Bluetooth API'lerini kullanan uygulamalar için cihazın yerel donanım tanımlayıcısına programlı erişimi kaldırıyor. WifiInfo.getMacAddress () ve BluetoothAdapter.getAddress () yöntemleri artık 02: 00: 00: 00: 00: 00 sabit bir değer döndürür.

Bluetooth ve Wi-Fi taramaları aracılığıyla yakındaki harici cihazların donanım tanımlayıcılarına erişmek için, uygulamanızın artık ACCESS_FINE_LOCATION veya ACCESS_COARSE_LOCATION izinlerine sahip olması gerekir.


11
Ayrıca sadece bir not, bazen cihazda wifi kapalı olduğu için Mac adresi alınamaz
sbrichards

3
Bağlantılı blog ayrıca, bu MAC adresinin, ağ arayüzünün WiFi bağlantısını kullandığını varsaymadan daha genel bir şekilde nasıl bulunacağını açıklar.
Stephen C

GetSystemService'i çağırmak için bağlamı kullanmayı unutmayın.
Tito Leiva

Bu, Wifi kullanan Android telefonlar ve tabletler için harika, ancak Ethernet MAC adresini, Wifi veya Ethernet kullanabilen eski bir Gingerbread Android tablette almaya çalışıyorum. Ethernet MAC adresinin nasıl kontrol edileceğine dair herhangi bir fikriniz var mı? Teşekkürler.
Seth

@sbrichards WiFi kapalı olmaktan ne kastediyorsunuz?
peterchaula

34

MAC adresini WifiInfo.getMacAddress()almak Marshmallow ve üzeri sürümlerde çalışmaz, devre dışı bırakılmıştır ve sabit değerini02:00:00:00:00:00 döndürür .


3
Alternatif nedir?
Sam

2
@SameerThigale Neyi başarmaya çalıştığınıza bağlıdır. Bunun arkasındaki fikir, muhtemelen MAC adresini almaya çalışmamanız gerektiğidir.
minipif

Neden olduğundan emin değilim, ancak bağlantılı api belgesinde kullanımdan kaldırılmış bir not bulamıyorum. Belki bu konuda fikirlerini değiştirmişlerdir?
DBX12

1
@ DBX12 Yöntemin kendisi, belgelenmemiş olmasına rağmen, kullanımdan kaldırıldı olarak işaretlenmemiştir. İkinci bağlantı, bununla ilgili resmi bir nota işaret ediyor.
minipif

26
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
Android 7.1'de bana "02: 00: 00: 00: 00: 00" gösteriyor.
android geliştiricisi

Öykünücü veya sanal cihaz yerine Fiziksel cihazda test edilmelidir
pm dubey

1
Manifest dosyasında internet izni vermeyi unutmayın.
pm dubey

2
"02: 00: 00: 00: 00: 00" değerini döndüreceğinden artık android hatmi ve üzeri
sürümlerde çalışmıyor

1
İşe yarıyor. Bu kodu çok uzun zamandır kullanıyorum. Hala Android Q'da çalışıyor
Rupam Das

14

Bu çözümü http://robinhenniges.com/en/android6-get-mac-address-programmatically adresinden kurdum ve benim için çalışıyor! Umut yardımcı olur!

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

Sanırım son “:” karakterini kaldırmamız gerektiğinden. Bu kod 2 yaşında ve muhtemelen bunu yapmanın en iyi yolu değil, onu optimize etmelisiniz
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;
}

burada başkaları var


Will macAddressolabileceğimden null?
Maksimum Heiber

işlev çağrısı yapılırken hangi parametrenin bağlam olarak geçmesi gerekir?
Donal

@Donal demek istiyorsun Context context? evet ise, herhangi bir bağlam çalışmalıdır. developer.android.com/reference/android/content/…
ademar111190

8

Marshmallow ile Çalışması

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

Teşekkürler Qadir Hussain
Keshav Gera

4

Artık bir android cihazın donanım MAC adresini alamazsınız. WifiInfo.getMacAddress () ve BluetoothAdapter.getAddress () yöntemleri 02: 00: 00: 00: 00: 00 döndürür. Bu kısıtlama Android 6.0'da tanıtıldı.

Ancak Rob Anderson, <Marshmallow: https://stackoverflow.com/a/35830358 için çalışan bir çözüm buldu


3

Mac adresini alabilirsiniz:

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

Menifest.xml'de İzin Ayarla

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

Soru, wifi yönlendiriciden değil, android cihazdan Mac almakla ilgili.
hina abbasi

3

Bu basit yöntemi kullanarak

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

2

Buradaki Android kaynaklarından alınmıştır . Bu, sistemin ayarlar uygulamasında MAC ADRESİNİZİ gösteren gerçek koddur.

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

buna aktivite olmayan sınıfta veya parçada nasıl erişmeliyim?
Hunt

Bir WifiManager(ie WifiManager mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);) elde etmek için bir bağlama ihtiyacınız olacak .
fernandohur

5
Bu kodu denerse, 02:00:00:00:00:00mac adresini gerçek wifi mac kimliği değil alıyorum
Hunt

0

Bunun çok eski bir soru olduğunu biliyorum ama bunu yapmanın bir yolu daha var. Aşağıdaki kod derleniyor ama ben denemedim. MAC adresini almak için bir miktar C kodu yazabilir ve JNI (Java Native Interface) kullanabilirsiniz. İşte örnek ana aktivite kodu:

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

Ve düzen dosyası 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 dosyası, hangi izinleri ekleyeceğimi bilmediğimden bazılarını ekledim.

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

Get_mac_addr işlevinin C uygulaması.

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

Ve son olarak, CMakeLists.txt dosyası

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

Sanırım MAC adreslerini LOCATION izni olmadan okumanın bir yolunu buldum: ip linkÇıktısını çalıştırın ve ayrıştırın. (muhtemelen bu ikilinin kaynak koduna bakarak benzerini yapabilirsiniz)

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.