今天在撸代码时发现,之前能获取mac地址的方法在nexus 6上返回了“02:00:00:00:00:00”,进入设置查看mac地址,结果不相同,肯定有问题,于是就开始上网查资料一探究竟。
原先获取mac地址的代码段:
6.0之前获取mac地址方法对于在Android Mashmallow返回地址“02:00:00:00:00:00”,官方其实是有说明的:“保护用户隐私数据”。
android 官方说明然后就找到了这篇文章,里面详细的介绍了一种方法获取。用Java获取设备网络设备信息的API——NetworkInterface.getNetworkInterfaces()——仍然可以间接地获取到MAC地址。
NetworkInterface.getNetworkInterfaces注意:在使用上述代码时,记得添加以下权限:
使用NetworkInterface.getNetworkInterfaces在手机上的输出结果为:
猜想wlan0对应的mac地址应该就是我们要找的。既然NetworkInterface可以正常获取,那得好好看看它在 Android framework 中的实现源码:
原来MAC地址是直接从"/sys/class/net/" + name + "/address"文件中读取的!
这个name是什么呢?
继续翻源码:
可以看出/sys/class/net目录下的一个文件夹即对应一个NetworkInterface的name。
从路由器上在线设备的MAC地址列表,可以验证我这台设备Wifi的name是wlan0
那么读取文件/sys/class/net/wlan0/address就轻松得到了这台设备的MAC地址:
不出所料!
进而,问题又变成如何获取设备的Wifi的interface name?
回到开头,我们是通过context.getSystemService(Context.WIFI_SERVICE)获取的WifiManager。而WifiManager肯定是与远程系统服务的IBinder在交互,而系统服务都是在SystemServer.run()中被启动的。在SystemServer.java中搜索关键字”WIFI_SERVICE”,很容易便找到mSystemServiceManager.startService(WIFI_SERVICE_CLASS);顺藤摸瓜,又找到系统服务实现类com.android.server.wifi.WifiService,WifiService中的逻辑很简单,构造真正的实现类com.android.server.wifi.WifiServiceImpl对象并注册到系统服务中:
WifiService.java打开WifiServiceImpl.java,从构造方法处,一眼就看到了关键代码:mInterfaceName = SystemProperties.get("wifi.interface", "wlan0");
如此这般终于找到定义设备的Wifi的interface name的地方:SystemProperties
通过adb可以很容易得到这个属性值:adb shell getprop wifi.interface
那么在我们应用里可以通过Java的反射获取SystemProperties,进而调用静态方法get即可拿到Wifi的interface name。
如果是系统应用,可以直接添加下面的权限,之前的方法仍旧可以返回正确的mac地址:
网友评论
try {
Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
while (networkInterfaces.hasMoreElements()) {
NetworkInterface networkInterface = networkInterfaces.nextElement();
byte[] hardwareAddress = networkInterface.getHardwareAddress();
if (hardwareAddress == null || hardwareAddress.length == 0) {
continue;
}
StringBuilder stringBuffer = new StringBuilder();
for (byte hardwareAddres : hardwareAddress) {
stringBuffer.append(String.format("%02X:", hardwareAddres));
}
if (stringBuffer.length() > 0) {
stringBuffer.deleteCharAt(stringBuffer.length() - 1);
}
return stringBuffer.toString();
}
} catch (SocketException e) {
return "";
}
return "";
}
获取到的 mac 和 手机应用信息的 Mac 地址对应不上
你需要判断当前的interface的名字,加个过滤
if(networkInterface.getName().equals("wlan0")){
...
}否则获取的是其他地址