【问题标题】:Getting MAC address in Android 6.0在 Android 6.0 中获取 MAC 地址
【发布时间】:2016-01-14 13:00:50
【问题描述】:

我正在开发一个获取设备 MAC 地址的应用,但由于 Android 6.0 我的代码无法正常工作,给我一个不正确的值。

这是我的代码...

public String ObtenMAC()
{
    WifiManager manager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
    WifiInfo info = manager.getConnectionInfo();

    return(info.getMacAddress().toUpperCase());
}

它返回的不是真正的 MAC 地址,而是一个奇怪的代码:02:00:00:00:00:00

【问题讨论】:

  • 您确定在获取 MAC 地址之前检查了ACCESS_WIFI_STATE 吗?在 M 中,如果你只在 Manifest 中要求它,它就行不通,你必须像这样在 rumtime 中实现它:youtube.com/…
  • 感谢您的回答。我的清单中有该权限,但是当我按照视频中所示以编程方式检查它时,Android Studio 无法识别“checkSelfPermission”,我不知道是否可能是因为我的目标是 API 21 Lollipop 并且没有'未安装 API 23 Marshmallow。
  • 在调用 checkSelfPermission 之前,您应该检查 SDK 版本是否低于 API 23 Marshmallow,如下所示:stackoverflow.com/questions/3423754/…
  • 在目标级别拥有最新的 Android API 版本总是好的
  • 请检查这个解决方案,它对我有用stackoverflow.com/questions/31329733/…

标签: android wifi mac-address


【解决方案1】:

请参考Android 6.0 Changes

为了向用户提供更好的数据保护,从本版本开始,Android 移除了对使用 Wi-Fi 和蓝牙 API 的应用程序的设备本地硬件标识符的编程访问。 WifiInfo.getMacAddress() 和 BluetoothAdapter.getAddress() 方法现在返回一个常量值 02:00:00:00:00:00。

要通过蓝牙和 Wi-Fi 扫描访问附近外部设备的硬件标识符,您的应用现在必须具有 ACCESS_FINE_LOCATION 或 ACCESS_COARSE_LOCATION 权限。

【讨论】:

  • 我的应用拥有这些权限,但仍然无法使用。
  • @Hrodger,即使拥有这些权限,您也无法获得自己的 MAC。仔细阅读。据说您可以获得具有这些权限的其他设备MAC,但不能获得您的
  • 那么就没有办法了吗?
  • 显然你仍然可以通过 java.net.NetworkInterface 获取 mac 地址。是的,我对 Google 开发人员的能力有很高的评价;)。
【解决方案2】:

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

            if (res1.length() > 0) {
                res1.deleteCharAt(res1.length() - 1);
            }
            return res1.toString();
        }
    } catch (Exception ex) {
        //handle exception
    }
    return "";
}

【讨论】:

  • 这个答案有一个错误,十六进制形式的字节只有一个数字,不会出现在它前面的“0”。对 res1 的追加应改为 res1.append(String.format("%02X:",b));
  • 也适用于 Android 7。
  • WiFi MAC 地址并不总是与蓝牙接口相同。在我的手机上,只有前 3 个八度音阶匹配(顺便说一下供应商)。
【解决方案3】:

我没有得到上述答案,但偶然发现了另一个答案。

这里是获取IPv6地址然后从中获取mac地址的完整而简单的方法。

How to get Wi-Fi Mac address in Android Marshmallow

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(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";
}

已经测试过了,它可以工作。非常感谢 Rob Anderson!

【讨论】:

  • 谢谢,正如其他地方所述,这需要 才能工作。
【解决方案4】:

这是在 Marshmallow 上成功获取它的完整 2 种方法代码,只需复制过去即可!

//Android 6.0 : Access to mac address from WifiManager forbidden
    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);
        StringBuilder builder = new StringBuilder();
    int ch;
    while((ch = fin.read()) != -1){
        builder.append((char)ch);
    }

    ret = builder.toString();
    fin.close();

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

清单:

<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
  • 总结:此代码将首先尝试通过接口获取 MAC 地址,如果失败则通过文件系统获取。

  • 注意:文件系统方式,需要开启WIFI才能访问文件。

感谢 Sam 的回答 https://stackoverflow.com/a/39288868/3818437

【讨论】:

    【解决方案5】:

    您可以从 IPv6 本地地址获取 MAC 地址。例如,IPv6 地址“fe80::1034:56ff:fe78:9abc”对应于 MAC 地址“12-34-56-78-9a-bc”。请参阅下面的代码。获取 WiFi IPv6 地址只需要 android.permission.INTERNET。

    参见维基百科页面IPv6 address,特别是关于“本地地址”fe80::/64 的注释和关于“修改的EUI-64”的部分。

    /**
     * Gets an EUI-48 MAC address from an IPv6 link-local address.
     * E.g., the IPv6 address "fe80::1034:56ff:fe78:9abc"
     * corresponds to the MAC address "12-34-56-78-9a-bc".
     * <p/>
     * See the note about "local addresses" fe80::/64 and the section about "Modified EUI-64" in
     * the Wikipedia article "IPv6 address" at https://en.wikipedia.org/wiki/IPv6_address
     *
     * @param ipv6 An Inet6Address object.
     * @return The EUI-48 MAC address as a byte array, null on error.
     */
    private static byte[] getMacAddressFromIpv6(final Inet6Address ipv6)
    {
        byte[] eui48mac = null;
    
        if (ipv6 != null) {
            /*
             * Make sure that this is an fe80::/64 link-local address.
             */
            final byte[] ipv6Bytes = ipv6.getAddress();
            if ((ipv6Bytes != null) &&
                    (ipv6Bytes.length == 16) &&
                    (ipv6Bytes[0] == (byte) 0xfe) &&
                    (ipv6Bytes[1] == (byte) 0x80) &&
                    (ipv6Bytes[11] == (byte) 0xff) &&
                    (ipv6Bytes[12] == (byte) 0xfe)) {
                /*
                 * Allocate a byte array for storing the EUI-48 MAC address, then fill it
                 * from the appropriate bytes of the IPv6 address. Invert the 7th bit
                 * of the first byte and discard the "ff:fe" portion of the modified
                 * EUI-64 MAC address.
                 */
                eui48mac = new byte[6];
                eui48mac[0] = (byte) (ipv6Bytes[8] ^ 0x2);
                eui48mac[1] = ipv6Bytes[9];
                eui48mac[2] = ipv6Bytes[10];
                eui48mac[3] = ipv6Bytes[13];
                eui48mac[4] = ipv6Bytes[14];
                eui48mac[5] = ipv6Bytes[15];
            }
        }
    
        return eui48mac;
    }
    

    【讨论】:

    • Mac地址似乎是随机的,即使你能抓住它! developer.android.com/about/versions/marshmallow/…
    • Android 6.0 中的 WifiManager API 已更改为返回虚假 MAC 地址。但是您仍然可以获取 Wi-Fi 网络的 IPv6 链接本地地址,然后如上提取 MAC 地址。这适用于我尝试过的每台设备。
    • 嗨@Yojimbo,这个代码会返回路由器的MAC地址,还是设备的MAC地址?
    • 这是设备的 WiFi MAC 地址。您可以使用 WiFiManager.getScanResults() 获取 WiFi 接入点的 MAC。对于 WAP,BSSID 等于 MAC 地址。
    • 您可以使用NetworkInterface 枚举网络接口。有关示例,请参阅此 SO question。使用 Java instanceof 运算符确定哪些 IP 地址是Inet6Address
    【解决方案6】:

    我尝试通过 2 种方法获取 mac 地址,首先通过接口,如果失败,我通过文件系统获取它,但您需要启用 wifi 才能访问该文件。

    //Android 6.0 : Access to mac address from WifiManager forbidden
        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 = convertStreamToString(fin);
            fin.close();
    
            boolean enabled = WifiManager.WIFI_STATE_ENABLED == wifiState;
            wifiMan.setWifiEnabled(enabled);
            return ret;
        }
    

    将此行添加到您的清单中。

    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
        <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
    

    我建议您将您的 mac 地址保留在您的首选项中,就像这里

    mac = activity.getSharedPreferences("MAC_ADDRESS", Context.MODE_PRIVATE).getString("MAC_ADDRESS", "");
                    if(mac == null || mac.equals("")){
                        WifiManager wifiMan = (WifiManager) activity.getSystemService(Context.WIFI_SERVICE);
                        mac = MobileAccess.recupAdresseMAC(wifiMan);
                        if(mac != null && !mac.equals("")){
                            SharedPreferences.Editor editor = activity.getSharedPreferences("MAC_ADDRESS", Context.MODE_PRIVATE).edit();
                            editor.putString("MAC_ADDRESS", mac).commit();
                        }
                    }
    

    【讨论】:

      【解决方案7】:

      非常好

      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) + ":");
                      }
      
                      if (res1.length() > 0) {
                          res1.deleteCharAt(res1.length() - 1);
                      }
                      return res1.toString();
                  }
              } catch (Exception ex) {
                  //handle exception
              }
              return "";
          }
      }
      

      【讨论】:

      【解决方案8】:

      首先你需要添加互联网用户权限。

      <uses-permission android:name="android.permission.INTERNET" />
      

      然后你可以通过 NetworkInterfaces API 找到 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(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";
      }
      

      【讨论】:

      【解决方案9】:

      答案大多是正确的,但请注意,android 7 中存在变化。您将需要使用

      DevicePolicyManager 和方法 getWifiMacAddress。官方文档有一个错字,这意味着你不应该从那里复制/粘贴它。

      DevicePolicyManager.getWifiMacAddress()
      

      参考: https://developer.android.com/about/versions/nougat/android-7.0-changes.html

      Get Device mac adress in Android Nougat and O programmatically

      【讨论】:

        【解决方案10】:

        使用 wifiInfo.getBSSID() 代替 getMacAddress 方法获取 AccessPoint 的 Mac 地址。

        【讨论】:

        • 只提供你连接的设备的mac地址,比如wifi路由器。不是设备本身
        【解决方案11】:

        这是获取 Mac 地址的更 kotlin 方式

        fun getMacAddress(): String =
                NetworkInterface.getNetworkInterfaces().toList()
                        .firstOrNull { it.name.equals("wlan0", ignoreCase = true) }?.let {
                            it.hardwareAddress?.let { macBytes ->
                                StringBuilder().apply {
                                    for (b in macBytes) {
                                        append(String.format("%02X:", b))
                                    }
                                    if (isNotEmpty()) {
                                        deleteCharAt(lastIndex)
                                    }
                                }
                            }.toString()
                        } ?: "02:00:00:00:00:00"
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2016-05-08
          • 2014-07-24
          • 1970-01-01
          • 2016-01-11
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多