Android 6.0 和 7.0后获取Mac地址

随着Android的版本迭代,获取设备的Mac地址也发生了改变。这里找到了最新的适配方案(适配当前的最新版本Android 9.0),并且记录了整个适配的修复过程,以供参考。

Android 6.0 之前,获得Mac地址的通用方式

必须的权限 < uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />

 /** * Android  6.0 之前(不包括6.0) * 必须的权限   * @param context * @return */private static String getMacDefault(Context context) {    String mac = "02:00:00:00:00:00";    if (context == null) {        return mac;    }    WifiManager wifi = (WifiManager) context.getApplicationContext()            .getSystemService(Context.WIFI_SERVICE);    if (wifi == null) {        return mac;    }    WifiInfo info = null;    try {        info = wifi.getConnectionInfo();    } catch (Exception e) {    }    if (info == null) {        return null;    }    mac = info.getMacAddress();    if (!TextUtils.isEmpty(mac)) {        mac = mac.toUpperCase(Locale.ENGLISH);    }    return mac;}

Android 6.0 — Android 7.0之前

Android 6.0 变更
硬件标识符访问权
为给用户提供更严格的数据保护,从此版本开始,对于使用 WLAN API 和 Bluetooth API 的应用,Android 移除了对设备本地硬件标识符的编程访问权。WifiInfo.getMacAddress() 方法和 BluetoothAdapter.getAddress() 方法现在会返回常量值 02:00:00:00:00:00。

上面是官网说明,很显然如果采用原有的方式获得是默认的值 02:00:00:00:00:00
这里采用的是读取系统的这个文件

/** * Android 6.0(包括) - Android 7.0(不包括) * @return */private static String getMacAddress() {    String WifiAddress = "02:00:00:00:00:00";    try {        WifiAddress = new BufferedReader(new FileReader(new File("/sys/class/net/wlan0/address"))).readLine();    } catch (IOException e) {        e.printStackTrace();    }    return WifiAddress;}

Android 7.0 之后

然而有一天发现在Android 7.0手机上,上面的那种方式出现异常了,并且提醒
/sys/class/net/wlan0/address permission denied
很显然,从7.0后,权限被拒绝,凉凉
从网上找到了另一种方案,通过扫描各个网络接口来获取Mac地址,并且这种方式在Android 6.0上同样有效
必须的权限 < uses-permission android:name="android.permission.INTERNET" />

 /** * 遍历循环所有的网络接口,找到接口是 wlan0 * 必须的权限  * @return */private static String getMacFromHardware() {    try {        List 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 e) {        e.printStackTrace();    }    return "02:00:00:00:00:00";}

适配方案

  • 在Android 4.4.4上,以上三种方式全部有效
    Android 4.4.4
  • 在Android 6.0 上,除了第一种Android 6.0之前的这个方案无效,剩下两个都是有效的
    Android 6.0
  • 在Android 9.0上,只有第三种方案是有效的
    Android 9.0

虽然第三种方案都是有效的,但这里我采用的是按照版本使用,如下

/** * 获取MAC地址 * * @param context * @return */public static String getMacAddress(Context context) {    String mac = "02:00:00:00:00:00";    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {        mac = getMacDefault(context);    } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {        mac = getMacFromFile();    } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {        mac = getMacFromHardware();    }    return mac;}

AndroidManifest.xml

参考资料:
Getting MAC address in Android 6.0 --- stackoverflow

更多相关文章

  1. android进行异步更新UI的四种方式
  2. android 绑定arp
  3. Android(安卓)apk的安装、卸载
  4. MediaRecorder视频的录制和播放
  5. 收集的android开源项目,android学习必备
  6. Android(安卓)安全机制概述
  7. Android动态换肤(二、apk免安装插件方式)
  8. Service和Activity通讯的3种常用方式示例
  9. Android声明和使用权限

随机推荐

  1. Android平台定义的主题样式
  2. Android(安卓)ProgressBar 设置滚动的图
  3. Android判断是否是平板
  4. android中布局使用大全
  5. android 用代码画虚线边框背景
  6. Android(安卓)相对布局
  7. Android(安卓)API Level对应Android版本
  8. android 实现透明按钮
  9. Android隐藏状态栏和标题栏,相当于全屏效
  10. Android剖析和运行机制