详解Android MacAddress 适配心得

android 6.0以下mac地址获取

我们获取mac地址一般都是这样写的:

/**

* 根据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以后 将不再能通过 wifimanager 获取mac,获取到的mac将是固定的:02:00:00:00:00:00 。

然而我开发的sdk就是通过wifimanager获取的mac。

android sdk后来做了6.0适配,通过cat /sys/class/net/wlan0/address,可以在6.0上获取mac地址。

/**

* 获取mac地址

* @param context

* @return

*/

public static String getMacAddress(Context context){

//如果是6.0以下,直接通过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 后,通过上述适配的方法,将获取不到mac地址。

经过调研和测试,7.0上仍有办法回去mac地址:

(1)通过ip地址来获取绑定的mac地址

/**

* 获取移动设备本地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();//得到下一个元素

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;

}

/**

* 获取本地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;

}

/**

* 根据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)扫描各个网络接口获取mac地址

/**

* 获取设备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转为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)通过busybox获取本地存储的mac地址

/**

* 根据busybox获取本地Mac

* @return

*/

public static String getLocalMacAddressFromBusybox(){

String result = "";

String Mac = "";

result = callCmd("busybox ifconfig","HWaddr");

//如果返回的result == null,则说明网络不可取

if(result==null){

return "网络异常";

}

//对该行数据进行解析

//例如: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;

}

 对比效果截图

上述三种方法,对比我开发的sdk现在使用的方法以及通过wifimanager获取mac地址的方法,效果如下(7.0设备有限,只覆盖部分机型):

结论

通过上述对比,通过ip获取mac地址和扫描网络接口获取mac结合使用,可以达到准确的效果。

通过ip获取的mac地址优先级高,只有在它获取不到的情况下,再使用扫描网络接口获取的mac地址。

以上是 详解Android MacAddress 适配心得 的全部内容, 来源链接: utcz.com/z/355465.html

回到顶部