Android MAC地址 02:00:00:00:00:00

文章介绍了在Android 6.0及以上版本中,由于系统安全策略的变化,使用传统方法无法正确获取设备的WiFi MAC地址。文中提供了一种新的解决方案,通过检查返回的默认值并尝试从网络接口或文件系统读取真实MAC地址。

转载:http://blog.youkuaiyun.com/zhaohaiyan629/article/details/51122344

谷歌在6.0及以后版本对获取wifi及蓝牙MacAddress 做的改动。

Most notably, Local WiFi and Bluetooth MAC addresses are no longer available. The getMacAddress() method of a WifiInfo object and the BluetoothAdapter.getDefaultAdapter().getAddress() method will both return 02:00:00:00:00:00 from now on.


也就是早先的:

[java]  view plain  copy
  print ? 在CODE上查看代码片 派生到我的代码片
  1. WifiManager wifiManager=(WifiManager) getSystemService(Context.WIFI_SERVICE);  
  2. WifiInfo wifiInfo=wifiManager.getConnectionInfo();  
  3. String mac=wifiInfo.getMacAddress();  
方法在安卓6.0系统上获取到的Mac 都是 02:00:00:00:00:00。

在Android6.0的版本以后用原来的getMacAddress()方法获取手机的MAC地址都为:02:00:00:00:00:00这个固定的值,获取不到原来的值了,原来Android6.0对硬件信息的访问,其管控更加严格。SD 卡的读写,除了权限声明之外,还应该动态请求,否则就会被禁止。读取设备的 IMEI 也一样。

Stackoverflow上的答案,试过可行,前提是wifi开关必须打开(数据开关打开也没有用),否则取到的结果为空,这里还是用02:00:00:00:00:00代替:


private static final String marshmallowMacAddress = "02:00:00:00:00:00";
    private static final String fileAddressMac = "/sys/class/net/wlan0/address";

    public static String recupAdresseMAC(WifiManager wifiMan) {
        WifiInfo wifiInf = wifiMan.getConnectionInfo();

        if(wifiInf.getMacAddress().equals(marshmallowMacAddress)){
            String ret = null;
            try {
                ret= getAdressMacByInterface();
                if (ret != null){
                    return ret;
                } else {
                    ret = getAddressMacByFile(wifiMan);
                    return ret;
                }
            } catch (IOException e) {
                Log.e("MobileAccess", "Erreur lecture propriete Adresse MAC");
            } catch (Exception e) {
                Log.e("MobileAcces", "Erreur lecture propriete Adresse MAC ");
            }
        } else{
            return wifiInf.getMacAddress();
        }
        return marshmallowMacAddress;
    }

    private static String getAdressMacByInterface(){
        try {
            List<NetworkInterface> all = Collections.list(NetworkInterface.getNetworkInterfaces());
            for (NetworkInterface nif : all) {
                if (nif.getName().equalsIgnoreCase("wlan0")) {
                    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) {
            Log.e("MobileAcces", "Erreur lecture propriete Adresse MAC ");
        }
        return null;
    }

    private static String getAddressMacByFile(WifiManager wifiMan) throws Exception {
        String ret;
        int wifiState = wifiMan.getWifiState();

        wifiMan.setWifiEnabled(true);
        File fl = new File(fileAddressMac);
        FileInputStream fin = new FileInputStream(fl);
        ret = crunchifyGetStringFromStream(fin);
        fin.close();

        boolean enabled = WifiManager.WIFI_STATE_ENABLED == wifiState;
        wifiMan.setWifiEnabled(enabled);
        return ret;
    }

    // ConvertStreamToString() Utility - we name it as crunchifyGetStringFromStream()
    private static String crunchifyGetStringFromStream(InputStream crunchifyStream) throws IOException {
        if (crunchifyStream != null) {
            Writer crunchifyWriter = new StringWriter();

            char[] crunchifyBuffer = new char[2048];
            try {
                Reader crunchifyReader = new BufferedReader(new InputStreamReader(crunchifyStream, "UTF-8"));
                int counter;
                while ((counter = crunchifyReader.read(crunchifyBuffer)) != -1) {
                    crunchifyWriter.write(crunchifyBuffer, 0, counter);
                }
            } finally {
                crunchifyStream.close();
            }
            return crunchifyWriter.toString();
        } else {
            return "No Contents";
        }
    }


### 问题解析 在 Android 6.0 及以上版本中,`getMacAddress()` API 被限制使用,因此可能导致返回固定的 MAC 地址 `02:00:00:00:00:00`。这是由于 Google 对隐私保护政策的加强所致[^1]。 为了应对这一问题,可以采用其他替代方法来获取设备的实际 IP 或 MAC 地址。以下是详细的解决方案: --- ### 替代方案一:通过 `NetworkInterface` 获取实际 MAC 地址 可以通过调用 Java 提供的标准库类 `java.net.NetworkInterface` 来枚举所有的网络接口并提取其对应的硬件地址(即 MAC 地址)。这种方法不依赖于 Android 的私有 API,因而更加可靠。 #### 实现代码 ```kotlin import java.net.* import java.util.* fun getMacAddress(): String? { try { val networkInterfaces = NetworkInterface.getNetworkInterfaces() while (networkInterfaces.hasMoreElements()) { val ni = networkInterfaces.nextElement() if (!ni.name.equals("wlan0", true)) continue // 确保只处理 Wi-Fi 接口 val macBytes = ni.hardwareAddress ?: return null val sb = StringBuilder() for (b in macBytes) { sb.append(String.format("%02X:", b)) } if (sb.isNotEmpty()) { sb.deleteCharAt(sb.length - 1) } return sb.toString() } } catch (e: Exception) { e.printStackTrace() } return null } ``` 上述代码片段展示了如何通过遍历网络接口找到名为 `wlan0` 的 Wi-Fi 设备,并从中读取MAC 地址[^5]。 --- ### 替代方案二:Wi-Fi 下获取局域网 IP 地址 如果目标是获取设备的局域网 IP 地址而非 MAC 地址,则可以直接利用 `WifiManager` 类的相关功能实现此目的。需要注意的是,在 Android 6.0 和更高版本中,访问此类信息可能需要额外声明权限。 #### 实现代码 ```kotlin @Throws(Exception::class) fun getLocalIpAddress(context: Context): String? { val wifiMgr = context.applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager? val info = wifiMgr?.connectionInfo val ipAddress = info?.ipAddress return if (ipAddress != null && ipAddress != 0) { (ipAddress and 0xFF).toString() + "." + ((ipAddress shr 8) and 0xFF) + "." + ((ipAddress shr 16) and 0xFF) + "." + (ipAddress shr 24 and 0xFF) } else { null } } ``` 该函数能够成功检索到当前连接至 Wi-Fi 网络时分配给设备的 IPv4 地址[^3]。 --- ### 替代方案三:获取公网 IP 地址 对于某些应用场景而言,仅知道局域网内的 IP 并不足以满足需求;此时则需借助外部服务查询公网出口 IP。通常做法是从特定 HTTP/HTTPS URL 请求响应数据包中的客户端真实地址字段完成定位操作。 #### 实现代码 ```kotlin suspend fun fetchPublicIPAddress(): String? { var publicIp: String? = null withContext(Dispatchers.IO) { try { val url = URL("http://checkip.amazonaws.com/") val connection = url.openConnection() as HttpURLConnection BufferedReader(InputStreamReader(connection.inputStream)).use { br -> publicIp = br.readLine()?.trim() } } catch (ex: IOException) { ex.printStackTrace() } } return publicIp } ``` 这段异步执行逻辑允许开发者轻松抓取远程服务器反馈回来的结果作为最终答案[^4]。 --- ### 总结 综上所述,当面对 Android 6.0+ 版本系统无法正常调用旧版 `getMacAddress()` 函数的情况时,推荐改用基于标准 JDK 库封装的新技术路线解决问题。无论是针对本地物理层特征还是虚拟化后的互联网映射关系均提供了相应的适配策略可供选择。 --- 问题
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值