在做用户信息统计时,发现 安卓6.0系统用户返回的Mac地址都是 02:00:00:00:00:00,被误判为作弊用户,实际上是谷歌在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.

 

也就是早先的:

 

WifiManager wifiManager=(WifiManager) getSystemService(Context.WIFI_SERVICE);
WifiInfo wifiInfo=wifiManager.getConnectionInfo();
String mac=wifiInfo.getMacAddress();


方法在安卓6.0系统上获取到的Mac 都是 02:00:00:00:00:00。刚开始以为权限不够,但权限都给了之后还是获取到02:00信息,说明不是权限问题。查寻资料还可以通过获取设备网络设备信息的API—— NetworkInterface.getNetworkInterfaces() 去获取。

 

 

 

Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
while (interfaces.hasMoreElements()) {
    NetworkInterface iF = interfaces.nextElement();

    byte[] addr = iF.getHardwareAddress();
    if (addr == null || addr.length == 0) {
        continue;
    }

    StringBuilder buf = new StringBuilder();
    for (byte b : addr) {
        buf.append(String.format("%02X:", b));
    }
    if (buf.length() > 0) {
        buf.deleteCharAt(buf.length() - 1);
    }
    String mac = buf.toString();
    Log.d("---mac", "interfaceName="+iF.getName()+", mac="+mac);
}

 

 

 

用 Genymotion 虚拟机运行的6.0系统,打印如下:

---mac: interfaceName=eth0, mac=08:00:27:75:9A:98
---mac: interfaceName=eth1, mac=08:00:27:DF:43:CA
---mac: interfaceName=ifb0, mac=BE:98:32:22:9A:51
---mac: interfaceName=ifb1, mac=7A:E0:26:3E:8D:D3

 

获取一个属性的Mac 地址如下:

 

public static String getMacAddress(Context context) {



       
            WifiManager wifiMgr = (WifiManager) context
                    .getSystemService(Context.WIFI_SERVICE);
            WifiInfo wifiInfo = wifiMgr.getConnectionInfo();
       


        String macAddress = null;
        StringBuffer buf = new StringBuffer();
        NetworkInterface networkInterface = null;
        try {
            networkInterface = NetworkInterface.getByName("eth1");
            if (networkInterface == null) {
                networkInterface = NetworkInterface.getByName("wlan0");
            }
            if (networkInterface == null) {
                return "02:00:00:00:00:02";
            }
            byte[] addr = networkInterface.getHardwareAddress();




            for (byte b : addr) {
                buf.append(String.format("%02X:", b));
            }
            if (buf.length() > 0) {
                buf.deleteCharAt(buf.length() - 1);
            }
            macAddress = buf.toString();
        } catch (SocketException e) {
            e.printStackTrace();
            return "02:00:00:00:00:02";
        }
        Log.i("----getMacAddress--1--", "" + buf.toString());
        return macAddress;
    }

 

 

可以通过 运行各版本手机的方法 对比测试

networkInterface = NetworkInterface.getByName("wlan0");  
来确定getByName 为哪个name 。

 

蓝牙Mac地址获取:

/**
 * 获取Mac地址
 */
public class MacUtils {
	
	
	/**
	 * 获取手机的MAC地址
	 * 
	 * @return
	 */
	public static String getMac() {
		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) {
			ex.printStackTrace();
		}
		if (macSerial == null || "".equals(macSerial)) {
			try {
				return loadFileAsString("/sys/class/net/eth0/address")
						.toUpperCase().substring(0, 17);
			} catch (Exception e) {
				e.printStackTrace();

			}

		}
		return macSerial;
	}
	
	public static String loadFileAsString(String fileName) throws Exception {
		FileReader reader = new FileReader(fileName);
		String text = loadReaderAsString(reader);
		reader.close();
		return text;
	}

	public 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();
	}	

}


进行蓝牙相关操作要在AndroidManifest 进行蓝牙权限声明:

 


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

但通过4.4系统发现通过上面方法打印的结果 和 通过

 

 BluetoothManager bluetoothManager =
                (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
        BluetoothAdapter mBluetoothAdapter = bluetoothManager.getAdapter();
        String addressStr = mBluetoothAdapter.getAddress();

不太一样, 通过MacUtils 打印的 abcdef 都是小写字母, 通过getAddress 获得的是 大写字母,不过都是为了区分唯一性没有影响。
 

 

 

 

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐