2017-07-09

【Android Studio】取得裝置的 MAC

參考資料 ----
IPv6 MAC 轉換成 Link-local IP
Access to Hardware Identifier
DevicePolicyManager
Android 手機如何獲取 MAC 地址
 


Android 7.0 Nougat(API 24) 前用這個語法還行, 自 Nougat(含) 起就不行了
 
public String getMacAddress()
{
    WifiManager wifiMan = (WifiManager) this.getSystemService(Context.WIFI_SERVICE);
    WifiInfo wifiInf = wifiMan.getConnectionInfo();
    return wifiInf.getMacAddress();
}


Nougat(含) 後的做法,雖然程式可執行, 但是結果是無效的,僅做為筆記記錄用途
 
// 因安全性因素, 不再能取得 IPv4 的 MAC
public String getMacAddress()
{
    WifiManager wifiMan = (WifiManager) this.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
    WifiInfo wifiInf = wifiMan.getConnectionInfo();
    return wifiInf.getMacAddress();    // 會回傳假的 MAC -- 02:00:00:00:00:00
}
 


變通方式,不知是否為正解,但可達到目的
== 106.08.27 更新:現在此法也不行了, 程式會跑 exception: java.lang.NullPointerException: Attempt to get length of null array ==
== 目前先在 exception 回傳假的 MAC -- 02:00:00:00:00:00 擋著用 ==
== 看來唯有走 DevicePolicyManager 一途才是正解 ==

 
// 獲取移動設備本地 IP
private static InetAddress getLocalInetAddress()
{
    InetAddress ip = null;
    try
    {
        // 列舉
        Enumeration<NetworkInterface> en_netInterface = NetworkInterface.getNetworkInterfaces();
        while (en_netInterface.hasMoreElements())
        {
            // 是否還有元素
            NetworkInterface ni = (NetworkInterface) en_netInterface.nextElement();
            // 得到下一個元素
            Enumeration<InetAddress> en_ip = ni.getInetAddresses();
            // 得到一個 IP 位址的列舉
            while (en_ip.hasMoreElements())
            {
                ip = en_ip.nextElement();
                if (!ip.isLoopbackAddress() && ip.getHostAddress().indexOf(":") == -1)
                    break;
                else
                    ip = null;
            }
            if (ip != null)
            {
                break;
            }
        }
    }
    catch (SocketException e)
    {
        e.printStackTrace();
    }
    return ip;
}

...
...

public String getMacAddress()
{
    String strMacAddr = null;
    try
    {
        // 獲得 IP 位址
        InetAddress ip = getLocalInetAddress();
        byte[] b = NetworkInterface.getByInetAddress(ip).getHardwareAddress();
        StringBuffer buffer = new StringBuffer();
        for(int i=0; i<b.length; i++)
        {
            if(i!=0)
            {
                buffer.append(':');
            }
            String str = Integer.toHexString(b[i] & 0xFF);
            buffer.append(str.length() == 1 ? 0 + str : str);
        }
        strMacAddr = buffer.toString().toUpperCase();
    }
    catch (Exception e)
    {
        Log.d(TAG, "取得 MAC 失敗 == "+e.toString());        
        strMacAddr ="02:00:00:00:00:00";
    }
    return strMacAddr;
 
}


在爬文的過程中,看到有另一種做法 -- 從 IPv6 換算回 MAC,原來 IPv6 是以 MAC 為基礎演算出來的,有空再研究。

相關筆記 ----
ANDROID_ID -- Android 裝置的身分證