以编程方式获取 Android 设备的 MAC
Posted
技术标签:
【中文标题】以编程方式获取 Android 设备的 MAC【英文标题】:Programmatically getting the MAC of an Android device 【发布时间】:2012-07-27 04:48:48 【问题描述】:我需要使用 Java 获取我的 android 设备的 MAC 地址。我在网上搜索过,但没有找到任何有用的东西。
【问题讨论】:
programminglinuxblog.blogspot.pt/2011/06/… How to obtain MAC address of WiFi network interface?的可能重复 How to find MAC address of an Android device programatically的可能重复 请检查这个解决方案,它对我有用***.com/questions/31329733/… 从 android M 这个 api 被弃用,现在使用这个:***.com/questions/31329733/… 【参考方案1】:我知道这是一个非常古老的问题,但还有另一种方法可以做到这一点。下面的代码可以编译,但我还没有尝试过。 您可以编写一些 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_
android:layout_>
<TextView
android:id="@+id/sample_text"
android:layout_
android:layout_
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://***.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://***.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)
【讨论】:
我在 Android 30 上试过这个,它返回全零。【参考方案2】:此ip link | grep -A1 wlan0
命令适用于来自How to determine wifi hardware address in Termux 的Android 9
【讨论】:
【参考方案3】:我想我刚刚找到了一种无需 LOCATION 权限即可读取 MAC 地址的方法:运行 ip link
并解析其输出。 (你可以通过查看这个二进制文件的源代码来做类似的事情)
【讨论】:
【参考方案4】:使用这个简单的方法
WifiManager wm = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
String WLANMAC = wm.getConnectionInfo().getMacAddress();
【讨论】:
【参考方案5】:我从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 年历史了,可能不是最好的方法,你应该优化它【参考方案6】:它与棉花糖一起工作
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 "";
【讨论】:
感谢卡迪尔侯赛因【参考方案7】:正如评论中已经指出的那样,可以通过WifiManager 接收 MAC 地址。
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 Changes。
为了向用户提供更好的数据保护,从本版本开始,Android 移除了对使用 Wi-Fi 和蓝牙 API 的应用程序的设备本地硬件标识符的编程访问。 WifiInfo.getMacAddress() 和 BluetoothAdapter.getAddress() 方法现在返回一个常量值 02:00:00:00:00:00。
要通过蓝牙和 Wi-Fi 扫描访问附近外部设备的硬件标识符,您的应用现在必须具有 ACCESS_FINE_LOCATION 或 ACCESS_COARSE_LOCATION 权限。
【讨论】:
也只是一个说明,有时因为设备上的wifi关闭而无法提取mac地址 链接的博客还解释了如何在不假设网络接口使用 WiFi 连接的情况下以更通用的方式查找此 MAC 地址。 记得使用上下文调用getSystemService。 这非常适合使用 Wifi 的 Android 手机和平板电脑,但我正在尝试在可以使用 Wifi 或以太网的旧 Gingerbread Android 平板电脑上获取以太网 MAC 地址。关于如何检查以太网 MAC 地址的任何想法?谢谢。 @sbrichards 关闭 WiFi 是什么意思?【参考方案8】: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";
【讨论】:
在 Android 7.1 上一直显示“02:00:00:00:00:00”。 必须在物理设备上测试,而不是在模拟器或虚拟设备上测试 它仍然有效。不要忘记在 Manifest 文件中授予 Internet 权限。 它不再适用于 android marshmallow 及更高版本,因为它将返回“02:00:00:00:00:00”的值 它有效。我已经使用此代码很长时间了。它仍然适用于 Android Q。【参考方案9】:您无法再获取安卓设备的硬件 MAC 地址。 WifiInfo.getMacAddress() 和 BluetoothAdapter.getAddress() 方法将返回 02:00:00:00:00:00。此限制是在 Android 6.0 中引入的。
但是 Rob Anderson 找到了一个适用于 https://***.com/a/35830358
的解决方案【讨论】:
【参考方案10】:通过WifiInfo.getMacAddress()
获取 MAC 地址在 Marshmallow 及更高版本上不起作用,它已被禁用并将返回the constant value of 02:00:00:00:00:00
。
【讨论】:
有什么选择? @SameerThigale 取决于您要实现的目标。这背后的想法是您可能不应该尝试获取 MAC 地址。 我不知道为什么,但我在链接的 api 文档中找不到弃用的注释。也许他们改变了主意? @DBX12 该方法本身没有被标记为已弃用,尽管它没有记录在案。第二个链接指向有关它的官方说明。【参考方案11】:取自 Android 资源 here。这是在系统设置应用程序中显示您的 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);
)。
如果它尝试这个代码我得到02:00:00:00:00:00
mac 地址而不是实际的 wifi mac id【参考方案12】:
可以获取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>
【讨论】:
问题是关于获取android设备的mac,而不是wifi路由器。【参考方案13】:<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;
有其他方式here
【讨论】:
macAddress
会不会是null
?
函数调用时需要将哪个参数作为上下文传递?
@Donal 你的意思是Context context
吗?如果是的话,任何上下文都应该起作用。 developer.android.com/reference/android/content/…以上是关于以编程方式获取 Android 设备的 MAC的主要内容,如果未能解决你的问题,请参考以下文章
如何以编程方式在 Android 设备中获取设备 (AOSP) 内部版本号?
如何以编程方式获取 android 设备屏幕截图? [复制]