Android 10 下通过网络接口获取MAC地址结果异常的求助
Android 10及以上获取MAC地址异常的适配方案
异常根因
从Android 10(API 29)开始,系统对硬件敏感标识做了严格的访问限制:
- 普通应用通过
NetworkInterface.getNetworkInterfaces()遍历网卡、调用getHardwareAddress()读取wlan0/p2p0等网口硬件地址时,会被系统强制返回固定占位值02:00:00:00:00:00。这个拦截是系统层面的,和你匹配哪个网口名无关,所以把匹配规则从wlan0改成p2p0也解决不了问题 - Android 10以下版本没有该限制,原代码可以正常读到真实MAC,因此会出现低版本全正常、高版本取值错误的表现
- 你的测试场景(WiFi开启、未连接公网、基于Wi-Fi Direct做P2P通信)完全符合系统开放读取真实MAC的场景,不需要申请特殊的高阶权限。
可直接落地的适配实现
- 不要硬编码写死匹配单一网口名,不同厂商定制ROM的Wi-Fi、P2P网口命名存在差异(比如部分设备的P2P网口名是
p2p-wlan0-0,不是纯p2p0),硬卡单一网口很容易漏匹配 - 按系统版本分流实现,高版本直接走系统开放的WiFi接口读真实MAC,低版本沿用网卡遍历逻辑:
private static String getRealMacAddress(Context context) { // Android 10及以上直接调用系统WiFi接口读取工厂MAC if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { WifiManager wifiManager = (WifiManager) context.getApplicationContext() .getSystemService(Context.WIFI_SERVICE); return wifiManager.getFactoryMacAddress(); } // Android 10及以下沿用网卡遍历逻辑,优化网口过滤规则 try { Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces(); while (interfaces.hasMoreElements()) { NetworkInterface nic = interfaces.nextElement(); String nicName = nic.getName(); // 过滤回环、VPN、虚拟网卡等非Wi-Fi类网口 if (nicName.startsWith("wlan") || nicName.startsWith("p2p")) { byte[] macBytes = nic.getHardwareAddress(); if (macBytes == null || macBytes.length == 0) continue; StringBuilder macBuilder = new StringBuilder(); for (byte b : macBytes) { macBuilder.append(String.format("%02X:", b)); } macBuilder.deleteCharAt(macBuilder.length() - 1); return macBuilder.toString(); } } } catch (SocketException e) { Log.e("MacUtils", "read network interface error", e); } return ""; } - 实操避坑:
- 首先核对原代码的网口名拼写:系统标准Wi-Fi网口名是
wlan0而非代码里写的wlon0,拼写错误会导致网口匹配失败,低版本上能读到值大概率是测试时的巧合场景 - 不要尝试直接读
/sys/class/net/xxx/address系统文件,Android 10之后普通应用没有该路径的读取权限,只会拿到占位假值 - Wi-Fi Direct通信使用的MAC地址和设备Wi-Fi硬件的工厂MAC是同一个,不需要单独针对P2P网口做特殊适配
- 上述实现仅需要申请
ACCESS_WIFI_STATE普通权限,该权限是安装时自动授予的,不需要动态申请定位权限、也不需要系统签名。
- 首先核对原代码的网口名拼写:系统标准Wi-Fi网口名是
内容的提问来源于stack exchange,提问作者Naveen
相关产品推荐
相关产品推荐

