詳解Android MacAddress 適配心得
android 6.0以下mac地址獲取
我們獲取mac地址一般都是這樣寫的:
/** * 根據(jù)wifi信息獲取本地mac * @param context * @return */ public static String getLocalMacAddressFromWifiInfo(Context context){ WifiManager wifi = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); WifiInfo winfo = wifi.getConnectionInfo(); String mac = winfo.getMacAddress(); return mac; }
android 6.0及以上、7.0以下
Android 6.0以后 將不再能通過(guò) wifimanager 獲取mac,獲取到的mac將是固定的:02:00:00:00:00:00 。
然而我開發(fā)的sdk就是通過(guò)wifimanager獲取的mac。
android sdk后來(lái)做了6.0適配,通過(guò)cat /sys/class/net/wlan0/address,可以在6.0上獲取mac地址。
/** * 獲取mac地址 * @param context * @return */ public static String getMacAddress(Context context){ //如果是6.0以下,直接通過(guò)wifimanager獲取 if(Build.VERSION.SDK_INT<Build.VERSION_CODES.M){ String macAddress0 = getMacAddress0(context); if(!TextUtils.isEmpty(macAddress0)){ return macAddress0; } } String str=""; String macSerial=""; try { Process pp = Runtime.getRuntime().exec( "cat /sys/class/net/wlan0/address"); InputStreamReader ir = new InputStreamReader(pp.getInputStream()); LineNumberReader input = new LineNumberReader(ir); for (; null != str;) { str = input.readLine(); if (str != null) { macSerial = str.trim();// 去空格 break; } } } catch (Exception ex) { Log.e("----->" + "NetInfoManager", "getMacAddress:" + ex.toString()); } if (macSerial == null || "".equals(macSerial)) { try { return loadFileAsString("/sys/class/net/eth0/address") .toUpperCase().substring(0, 17); } catch (Exception e) { e.printStackTrace(); Log.e("----->" + "NetInfoManager", "getMacAddress:" + e.toString()); } } return macSerial; } private static String getMacAddress0(Context context) { if (isAccessWifiStateAuthorized(context)) { WifiManager wifiMgr = (WifiManager) context .getSystemService(Context.WIFI_SERVICE); WifiInfo wifiInfo = null; try { wifiInfo = wifiMgr.getConnectionInfo(); return wifiInfo.getMacAddress(); } catch (Exception e) { Log.e("----->" + "NetInfoManager", "getMacAddress0:" + e.toString()); } } return ""; } /** * Check whether accessing wifi state is permitted * * @param context * @return */ private static boolean isAccessWifiStateAuthorized(Context context) { if (PackageManager.PERMISSION_GRANTED == context .checkCallingOrSelfPermission("android.permission.ACCESS_WIFI_STATE")) { Log.e("----->" + "NetInfoManager", "isAccessWifiStateAuthorized:" + "access wifi state is enabled"); return true; } else return false; } private static String loadFileAsString(String fileName) throws Exception { FileReader reader = new FileReader(fileName); String text = loadReaderAsString(reader); reader.close(); return text; } private static String loadReaderAsString(Reader reader) throws Exception { StringBuilder builder = new StringBuilder(); char[] buffer = new char[4096]; int readLength = reader.read(buffer); while (readLength >= 0) { builder.append(buffer, 0, readLength); readLength = reader.read(buffer); } return builder.toString(); }
android 7.0及以上
android 7.0 后,通過(guò)上述適配的方法,將獲取不到mac地址。
經(jīng)過(guò)調(diào)研和測(cè)試,7.0上仍有辦法回去mac地址:
(1)通過(guò)ip地址來(lái)獲取綁定的mac地址
/** * 獲取移動(dòng)設(shè)備本地IP * @return */ private static InetAddress getLocalInetAddress() { InetAddress ip = null; try { //列舉 Enumeration<NetworkInterface> en_netInterface = NetworkInterface.getNetworkInterfaces(); while (en_netInterface.hasMoreElements()) {//是否還有元素 NetworkInterface ni = (NetworkInterface) en_netInterface.nextElement();//得到下一個(gè)元素 Enumeration<InetAddress> en_ip = ni.getInetAddresses();//得到一個(gè)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; } /** * 獲取本地IP * @return */ private static String getLocalIpAddress() { try { for (Enumeration<NetworkInterface> en = NetworkInterface .getNetworkInterfaces(); en.hasMoreElements();) { NetworkInterface intf = en.nextElement(); for (Enumeration<InetAddress> enumIpAddr = intf .getInetAddresses(); enumIpAddr.hasMoreElements();) { InetAddress inetAddress = enumIpAddr.nextElement(); if (!inetAddress.isLoopbackAddress()) { return inetAddress.getHostAddress().toString(); } } } } catch (SocketException ex) { ex.printStackTrace(); } return null; } /** * 根據(jù)IP地址獲取MAC地址 * @return */ public static String getMacAddress(){ String strMacAddr = null; try { //獲得IpD地址 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) { } return strMacAddr; }
(2)掃描各個(gè)網(wǎng)絡(luò)接口獲取mac地址
/** * 獲取設(shè)備HardwareAddress地址 * @return */ public static String getMachineHardwareAddress(){ Enumeration<NetworkInterface> interfaces = null; try { interfaces = NetworkInterface.getNetworkInterfaces(); } catch (SocketException e) { e.printStackTrace(); } String hardWareAddress = null; NetworkInterface iF = null; while (interfaces.hasMoreElements()) { iF = interfaces.nextElement(); try { hardWareAddress = bytesToString(iF.getHardwareAddress()); if(hardWareAddress != null) break; } catch (SocketException e) { e.printStackTrace(); } } return hardWareAddress ; } /*** * byte轉(zhuǎn)為String * @param bytes * @return */ private static String bytesToString(byte[] bytes){ if (bytes == null || bytes.length == 0) { return null ; } StringBuilder buf = new StringBuilder(); for (byte b : bytes) { buf.append(String.format("%02X:", b)); } if (buf.length() > 0) { buf.deleteCharAt(buf.length() - 1); } return buf.toString(); }
(3)通過(guò)busybox獲取本地存儲(chǔ)的mac地址
/** * 根據(jù)busybox獲取本地Mac * @return */ public static String getLocalMacAddressFromBusybox(){ String result = ""; String Mac = ""; result = callCmd("busybox ifconfig","HWaddr"); //如果返回的result == null,則說(shuō)明網(wǎng)絡(luò)不可取 if(result==null){ return "網(wǎng)絡(luò)異常"; } //對(duì)該行數(shù)據(jù)進(jìn)行解析 //例如:eth0 Link encap:Ethernet HWaddr 00:16:E8:3E:DF:67 if(result.length()>0 && result.contains("HWaddr")==true){ Mac = result.substring(result.indexOf("HWaddr")+6, result.length()-1); result = Mac; } return result; } private static String callCmd(String cmd,String filter) { String result = ""; String line = ""; try { Process proc = Runtime.getRuntime().exec(cmd); InputStreamReader is = new InputStreamReader(proc.getInputStream()); BufferedReader br = new BufferedReader (is); while ((line = br.readLine ()) != null && line.contains(filter)== false) { result += line; } result = line; } catch(Exception e) { e.printStackTrace(); } return result; }
對(duì)比效果截圖
上述三種方法,對(duì)比我開發(fā)的sdk現(xiàn)在使用的方法以及通過(guò)wifimanager獲取mac地址的方法,效果如下(7.0設(shè)備有限,只覆蓋部分機(jī)型):
結(jié)論
通過(guò)上述對(duì)比,通過(guò)ip獲取mac地址和掃描網(wǎng)絡(luò)接口獲取mac結(jié)合使用,可以達(dá)到準(zhǔn)確的效果。
通過(guò)ip獲取的mac地址優(yōu)先級(jí)高,只有在它獲取不到的情況下,再使用掃描網(wǎng)絡(luò)接口獲取的mac地址。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Android手機(jī)獲取Mac地址的方法
- Mac OS X 下有關(guān)Android adb用法詳解
- Android編程獲取設(shè)備MAC地址的實(shí)現(xiàn)方法
- Android 手機(jī)無(wú)法連接mac解決辦法
- Mac Android Studio快捷鍵整理
- android 獲取本機(jī)的IP地址和mac物理地址的實(shí)現(xiàn)方法
- Mac OS下為Android Studio編譯FFmpeg解碼庫(kù)的詳細(xì)教程
- Mac中Eclipse連不上Android手機(jī)的解決方法
- mac開發(fā)android環(huán)境搭建步驟圖解
相關(guān)文章
Android編程實(shí)現(xiàn)的首頁(yè)左右滑動(dòng)切換功能示例
這篇文章主要介紹了Android編程實(shí)現(xiàn)的首頁(yè)左右滑動(dòng)切換功能,涉及Android事件監(jiān)聽(tīng)及響應(yīng)相關(guān)操作技巧,需要的朋友可以參考下2017-07-07Android App中使用LinearLayout進(jìn)行居中布局的實(shí)例講解
這篇文章主要介紹了Android App中使用LinearLayout進(jìn)行居中布局的實(shí)例講解,文中分別介紹了水平居中和垂直居中的相關(guān)線性布局,需要的朋友可以參考下2016-04-04Android利用Flutter?path繪制粽子的示例代碼
端午將至,作為中華民族的非常重要的傳統(tǒng)節(jié)日,粽子那是必不可少的。今天跟隨本篇文章用Flutter?path畫一個(gè)會(huì)科普節(jié)日的的粽子吧2022-05-05Android富文本實(shí)現(xiàn)的幾種方式匯總
由于項(xiàng)目中需要使用到富文本顯示和編輯,索性整理下,這篇文章主要給大家介紹了關(guān)于Android富文本實(shí)現(xiàn)的幾種方式,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-05-05淺析Android App的相對(duì)布局RelativeLayout
這篇文章主要介紹了Android App的相對(duì)布局RelativeLayout,文中舉了一個(gè)登錄界面的XML布局例子,非常直觀,需要的朋友可以參考下2016-04-04分享Android開發(fā)自學(xué)筆記之AndroidStudio常用功能
這篇文章主要給大家分享Android開發(fā)自學(xué)筆記之AndroidStudio常用功能的相關(guān)資料,需要的朋友可以參考下2015-12-12Android開發(fā)-之監(jiān)聽(tīng)button點(diǎn)擊事件的多種方法
本篇文章主要是介紹了Android開發(fā)之監(jiān)聽(tīng)button點(diǎn)擊事件的方法,Android開發(fā)-之監(jiān)聽(tīng)button點(diǎn)擊事件的方法總結(jié),有興趣的可以了解一下。2016-11-11Android 自定義控件實(shí)現(xiàn)顯示文字的功能
這篇文章主要介紹了Android 自定義控件實(shí)現(xiàn)顯示文字的功能的相關(guān)資料,需要的朋友可以參考下2016-11-11