如何在Android设备上编程查找MAC地址

64

如何编程获取安卓设备的Mac地址。我已经用 IMIE 码完成了操作,也知道如何手动检查设备上的Mac地址,但不知道如何编程找出它。


我在这里发布了可行的解决方案 https://stackoverflow.com/a/47789324/5330408 - Android Developer
1
这个回答解决了你的问题吗?编程获取Android设备的MAC地址 - Mark Rotteveel
8个回答

132
WifiManager wifiManager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
WifiInfo wInfo = wifiManager.getConnectionInfo();
String macAddress = wInfo.getMacAddress(); 

另外,在您的清单文件中添加以下权限

<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
请参考Android 6.0更改内容。为了提供更好的数据保护,从这个版本开始,当应用使用Wi-Fi和蓝牙API时,Android会移除对设备本地硬件标识符的编程访问。WifiInfo.getMacAddress()和BluetoothAdapter.getAddress()方法现在返回常量值02:00:00:00:00:00。要通过蓝牙和Wi-Fi扫描访问附近外部设备的硬件标识符,您的应用程序现在必须具有ACCESS_FINE_LOCATION或ACCESS_COARSE_LOCATION权限。

19
除非您授予该活动ACCESS_WIFI_STATE权限,否则它将无法正常工作。 - Harry
12
请注意:如果在设置中禁用了WiFi,则此方法将无法使用。 - Ranhiru Jude Cooray
4
这以前很好用,在我的Nexus 9上运行Marshmallow时,现在返回02:00:00:00:00:00。 - AndyB
3
@AndyB在http://developer.android.com/about/versions/marshmallow/android-6.0-changes.html#behavior-hardware-id中提到,方法`WifiInfo.getMacAddress()`将会返回一个恒定的值。为了在Android M中获取MAC地址,您可以使用这个答案:https://dev59.com/1l0Z5IYBdhLWcg3wiw0v#32948723。请注意WiFi必须开启。 - Ahmed Mostafa
如果您直接使用此代码,可能会出现以下错误:WIFI_SERVICE 必须在应用程序上下文中查找,否则在 Android N 以下的设备上会发生内存泄漏。请尝试将 .getApplicationContext() 更改为 .getApplicationContext() [WifiManagerLeak]。以下代码应该可以正常工作:WifiManager wifiManager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE); - David Airapetyan
如果我正在使用蜂窝数据呢? - George Sp

21

看看这篇帖子,我在那里提交了Utils.java示例,提供了纯Java实现,而且不需要WifiManager。一些Android设备可能没有可用的WiFi或正在使用以太网布线。

Utils.getMACAddress("wlan0");
Utils.getMACAddress("eth0");
Utils.getIPAddress(true); // IPv4
Utils.getIPAddress(false); // IPv6 

一些设备可能有一个或多个以太网端口(有线或无线)。这只是Linux术语,用于命名通信端口。通常,Android设备只有一个可用的无线wlan0端口。 - Whome
如何查看设备端口名称 - Zala Janaksinh
请查看我发布的getMACAddress源代码,它循环所有网络接口(设备端口),您可以打印名称或执行其他操作。https://dev59.com/l2025IYBdhLWcg3wVkif#13007325 - Whome
这需要一些外部库吗? - hackjutsu
@Hackjustu:这不需要任何外部库,尽管我的原始答案使用了 InetAddressUtils.isIPv4Address(sAddr) 函数,但它已从 Android SDK 中删除。相反,应该使用 isIPv4=sAddr.indexOf(':')<0 技巧。 - Whome
显示剩余3条评论

11

使用此代码,您也将能够在Android 6.0中获取Mac地址

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) + ":");
                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";
}

编辑 1. 这个答案有一个bug,当一个字节的十六进制形式只有一位数时,它将不会在前面加上“0”。对于这个问题,已经更改了对res1的附加操作来解决它。


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) + ":");
                        res1.append(String.format("%02X:",b)); 
                    }
    
                    if (res1.length() > 0) {
                        res1.deleteCharAt(res1.length() - 1);
                    }
                    return res1.toString();
                }
            } catch (Exception ex) {
                //handle exception
            }
            return "";
        }
    }

更新1

本回答中存在一个错误,在十六进制形式下只有一位数字的字节将不会在前面添加“0”。现已更改对res1的追加以解决此问题。

 StringBuilder res1 = new StringBuilder();
                for (byte b : macBytes) {
                    // res1.append(Integer.toHexString(b & 0xFF) + ":");
                    res1.append(String.format("%02X:",b)); 
                }

7

最新的开发者.Android.com更新:

不要使用MAC地址。MAC地址是全球唯一的,用户不可重置,也可以经受工厂恢复。因此,通常不建议使用MAC地址进行任何形式的用户识别。在运行Android 10(API级别29)及更高版本的设备中,对于所有不是设备管理员应用程序的应用程序,都会向其报告随机化的MAC地址。

在Android 6.0(API级别23)和Android 9(API级别28)之间,本地设备MAC地址 (例如Wi-Fi和蓝牙) 不可通过第三方API获得。 WifiInfo.getMacAddress()方法和BluetoothAdapter.getDefaultAdapter().getAddress()方法都返回02:00:00:00:00:00。

此外,在Android 6.0和Android 9之间,必须拥有以下权限才能访问通过蓝牙和Wi-Fi扫描获得的附近外部设备的MAC地址:

方法/属性 所需权限

ACCESS_FINE_LOCATION或 ACCESS_COARSE_LOCATION

来源:https://developer.android.com/training/articles/user-data-ids.html#version_specific_details_identifiers_in_m


4

以下是Arth Tilvas的答案的Kotlin版本:

fun getMacAddr(): String {
    try {
        val all = Collections.list(NetworkInterface.getNetworkInterfaces())
        for (nif in all) {
            if (!nif.getName().equals("wlan0", ignoreCase=true)) continue

            val macBytes = nif.getHardwareAddress() ?: return ""

            val res1 = StringBuilder()
            for (b in macBytes) {
                //res1.append(Integer.toHexString(b & 0xFF) + ":");
                res1.append(String.format("%02X:", b))
            }

            if (res1.length > 0) {
                res1.deleteCharAt(res1.length - 1)
            }
            return res1.toString()
        }
    } catch (ex: Exception) {
    }

    return "02:00:00:00:00:00"
}

3
private fun getMac(): String? =
        try {
            NetworkInterface.getNetworkInterfaces()
                    .toList()
                    .find { networkInterface -> networkInterface.name.equals("wlan0", ignoreCase = true) }
                    ?.hardwareAddress
                    ?.joinToString(separator = ":") { byte -> "%02X".format(byte) }
        } catch (ex: Exception) {
            ex.printStackTrace()
            null
        }

-1

有一个简单的方法:

Android:

   String macAddress = 
android.provider.Settings.Secure.getString(this.getApplicationContext().getContentResolver(), "android_id");

Xamarin:

    Settings.Secure.GetString(this.ContentResolver, "android_id");

嘿,我尝试了这个,但是当从不同的笔记本电脑构建apk时,它会给出不同的mac地址。 - GiridharaSPK

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接