프로그래밍 방식으로 Android 기기의 MAC 가져 오기


93

Java를 사용하여 Android 장치의 MAC 주소를 얻어야합니다. 온라인으로 검색했지만 유용한 정보를 찾지 못했습니다.





이 솔루션을 확인하십시오. 그것은 나를 위해 작동합니다. stackoverflow.com/questions/31329733/…
Gorio

Android M에서이 API는 더 이상 사용되지 않습니다. 지금은 다음을 사용하세요. stackoverflow.com/questions/31329733/…
Ehud

답변:


115

주석에서 이미 지적했듯이 MAC 주소는 WifiManager 를 통해 수신 할 수 있습니다 .

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

또한 적절한 권한을 추가하는 것을 잊지 마십시오. AndroidManifest.xml

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

Android 6.0 변경 사항을 참조하십시오 .

사용자에게 더 나은 데이터 보호를 제공하기 위해 이번 릴리스부터 Android는 Wi-Fi 및 Bluetooth API를 사용하는 앱의 기기 로컬 하드웨어 식별자에 대한 프로그래밍 방식 액세스를 제거합니다. WifiInfo.getMacAddress () 및 BluetoothAdapter.getAddress () 메서드는 이제 상수 값 02 : 00 : 00 : 00 : 00 : 00을 반환합니다.

블루투스 및 Wi-Fi 검색을 통해 주변 외부 기기의 하드웨어 식별자에 액세스하려면 이제 앱에 ACCESS_FINE_LOCATION 또는 ACCESS_COARSE_LOCATION 권한이 있어야합니다.


11
또한 단지 메모, 때로는 MAC 주소는 무선 랜 장치에서 떨어져 있기 때문에 당겨질 수 없습니다
sbrichards

3
링크 된 블로그에서는 네트워크 인터페이스가 WiFi 연결을 사용한다고 가정하지 않는보다 일반적인 방법으로이 MAC 주소를 찾는 방법도 설명합니다.
Stephen C

컨텍스트를 사용하여 getSystemService를 호출하십시오.
Tito Leiva

이것은 Wi-Fi를 사용하는 Android 휴대폰 및 태블릿에 적합하지만 Wi-Fi 또는 이더넷을 사용할 수있는 구형 Gingerbread Android 태블릿에서 이더넷 MAC 주소를 얻으려고합니다. 이더넷 MAC 주소를 확인하는 방법에 대한 생각이 있으십니까? 감사.
Seth

@sbrichards WiFi가 꺼져 있다는 것은 무엇을 의미합니까?
peterchaula

34

MAC 주소를 가져 오는 것은 WifiInfo.getMacAddress()Marshmallow 이상에서 작동하지 않으며 비활성화되었으며 상수 값을02:00:00:00:00:00 반환 합니다 .


3
대안은 무엇입니까?
Sam

2
@SameerThigale 달성하려는 목표에 따라 다릅니다. 이것의이면에있는 아이디어는 아마도 MAC 주소를 얻으려고하지 말아야한다는 것입니다.
minipif

이유는 잘 모르겠지만 연결된 api 문서에서 더 이상 사용되지 않는 메모를 찾을 수 없습니다. 어쩌면 그들은 이것에 대해 마음을 바꿨 을까요?
DBX12

1
@ DBX12 메서드 자체는 문서화되어 있지 않지만 더 이상 사용되지 않는 것으로 표시되지 않습니다. 두 번째 링크는 이에 대한 공식 메모를 가리 킵니다.
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";
}

2
Android 7.1에서 계속 "02 : 00 : 00 : 00 : 00 : 00"이 표시됩니다.
안드로이드 개발자

에뮬레이터 나 가상 장치가 아닌 물리적 장치에서 테스트해야합니다
pm dubey

1
여전히 작동합니다. Manifest 파일에서 인터넷 권한을 부여하는 것을 잊지 마십시오.
pm dubey

1
"02 : 00 : 00 : 00 : 00 : 00"값을 반환하므로 Android 마시멜로 이상에서 더 이상 작동하지 않습니다.
SweArmy

1
효과가있다. 저는이 코드를 아주 오랫동안 사용해 왔습니다. 여전히 Android Q에서 작동합니다.
Rupam Das

14

http://robinhenniges.com/en/android6-get-mac-address-programmatically 에서이 솔루션을 설립 했으며 저에게 효과적입니다! 희망이 도움이됩니다!

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

마지막 ":"문자를 제거해야하기 때문이라고 생각합니다. 이 코드는 2 세이며, 아마도 그 일을 위해 최선의 방법을 itsn't, 당신은 그것을 최적화해야
티지 아노 브루 쉐 타에게

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

여기에 다른 방법이 있습니다


macAddress이제까지 null?
Max Heiber

함수 호출 중에 컨텍스트로 전달해야하는 매개 변수는 무엇입니까?
Donal

@ Donal 당신은 의미 Context context합니까? 그렇다면 어떤 컨텍스트가 작동해야합니다. developer.android.com/reference/android/content/…
ademar111190

8

마시멜로 작업

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

감사합니다 Qadir Hussain
Keshav Gera

4

더 이상 Android 기기의 하드웨어 MAC 주소를 가져올 수 없습니다. WifiInfo.getMacAddress () 및 BluetoothAdapter.getAddress () 메서드는 02 : 00 : 00 : 00 : 00 : 00을 반환합니다. 이 제한은 Android 6.0에서 도입되었습니다.

그러나 Rob Anderson은 <Marshmallow : https://stackoverflow.com/a/35830358에서 작동하는 솔루션을 찾았습니다.


3

Mac 주소를 얻을 수 있습니다.

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

Menifest.xml에서 권한 설정

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

질문은 와이파이 라우터가 아닌 안드로이드 장치의 맥을 얻는 것에 관한 것입니다.
hina abbasi

3

이 간단한 방법 사용

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

2

여기 Android 소스 에서 가져 왔습니다 . 이것은 시스템의 설정 앱에서 MAC 주소를 보여주는 실제 코드입니다.

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

비 활동 클래스 또는 조각에서 어떻게 액세스해야합니까?
사냥

WifiManager(예 :)를 얻으려면 컨텍스트가 필요합니다 WifiManager mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);.
fernandohur

5
02:00:00:00:00:00그것이이 코드를 시도하면 나는 실제 와이파이 맥 ID가 아닌 맥 주소를 얻고있다
헌트

0

나는 이것이 매우 오래된 질문이라는 것을 알고 있지만 이것을 수행하는 방법이 하나 더 있습니다. 아래 코드는 컴파일되지만 시도하지 않았습니다. C 코드를 작성하고 JNI (Java Native Interface)를 사용하여 MAC 주소를 가져올 수 있습니다. 다음은 주요 활동 코드의 예입니다.

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

그리고 레이아웃 파일 인 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 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 함수의 C 구현.

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

마지막으로 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

LOCATION 권한없이 MAC 주소를 읽는 방법을 찾은 것 같습니다 ip link. 출력을 실행 하고 구문 분석합니다. (이 바이너리의 소스 코드를 보면 비슷한 작업을 수행 할 수 있습니다.)

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.