Android6.0 Android7.0系统获getMacAddress()取Wifi和蓝牙Mac地址返回02:00:00:00:00:00解决办法

时间:2021-02-04 12:48:17

   有一些比较老的app。在使用的过程中会出现 getmac 返回:  02:00:00:00 这样的一个值。导致这些app无法使用。在这些app没有更新的情况下。可以通过修改framework满足一些客户的定制app的使用

  造成这个问题的根本原因在于  6.0  以后的android 系统  getMacAddress();  这个api已经失效。如果是自己写应用。只需要更新api。换成6.0 以后支持的方法去获取就可以获取到mac地址。当然。我们这里讨论的是另外一种方式。客户提供较老的app给你,而这个app并没有源码的情况下。可以通过修改系统的framework来解决这个问题。

先看看wifiinfo这个类: 不想看直接跳到源码最后一行。

public class WifiInfo implements Parcelable {
private static final String TAG = "WifiInfo";
/**
* This is the map described in the Javadoc comment above. The positions
* of the elements of the array must correspond to the ordinal values
* of <code>DetailedState</code>.
*/
private static final EnumMap<SupplicantState, DetailedState> stateMap =
new EnumMap<SupplicantState, DetailedState>(SupplicantState.class);

/**
* Default MAC address reported to a client that does not have the
* android.permission.LOCAL_MAC_ADDRESS permission.
*
* @hide
*/
public static final String DEFAULT_MAC_ADDRESS = "02:00:00:00:00:00";

static {
stateMap.put(SupplicantState.DISCONNECTED, DetailedState.DISCONNECTED);
stateMap.put(SupplicantState.INTERFACE_DISABLED, DetailedState.DISCONNECTED);
stateMap.put(SupplicantState.INACTIVE, DetailedState.IDLE);
stateMap.put(SupplicantState.SCANNING, DetailedState.SCANNING);
stateMap.put(SupplicantState.AUTHENTICATING, DetailedState.CONNECTING);
stateMap.put(SupplicantState.ASSOCIATING, DetailedState.CONNECTING);
stateMap.put(SupplicantState.ASSOCIATED, DetailedState.CONNECTING);
stateMap.put(SupplicantState.FOUR_WAY_HANDSHAKE, DetailedState.AUTHENTICATING);
stateMap.put(SupplicantState.GROUP_HANDSHAKE, DetailedState.AUTHENTICATING);
stateMap.put(SupplicantState.COMPLETED, DetailedState.OBTAINING_IPADDR);
stateMap.put(SupplicantState.DORMANT, DetailedState.DISCONNECTED);
stateMap.put(SupplicantState.UNINITIALIZED, DetailedState.IDLE);
stateMap.put(SupplicantState.INVALID, DetailedState.FAILED);
}

private SupplicantState mSupplicantState;
private String mBSSID;
private WifiSsid mWifiSsid;
private int mNetworkId;

/** @hide **/
public static final int INVALID_RSSI = -127;

/** @hide **/
public static final int MIN_RSSI = -126;

/** @hide **/
public static final int MAX_RSSI = 200;


/**
* Received Signal Strength Indicator
*/
private int mRssi;

/**
* Link speed in Mbps
*/
public static final String LINK_SPEED_UNITS = "Mbps";
private int mLinkSpeed;

/**
* Frequency in MHz
*/
public static final String FREQUENCY_UNITS = "MHz";
private int mFrequency;

private InetAddress mIpAddress;
private String mMacAddress = DEFAULT_MAC_ADDRESS;

private boolean mEphemeral;

/**
* @hide
*/
public long txBad;
/**
* @hide
*/
public long txRetries;
/**
* @hide
*/
public long txSuccess;
/**
* @hide
*/
public long rxSuccess;
/**
* @hide
*/
public double txBadRate;
/**
* @hide
*/
public double txRetriesRate;
/**
* @hide
*/
public double txSuccessRate;
/**
* @hide
*/
public double rxSuccessRate;

/**
* @hide
*/
public int badRssiCount;

/**
* @hide
*/
public int linkStuckCount;

/**
* @hide
*/
public int lowRssiCount;

/**
* @hide
*/
public int score;

/**
* TODO: get actual timestamp and calculate true rates
* @hide
*/
public void updatePacketRates(WifiLinkLayerStats stats) {
if (stats != null) {
long txgood = stats.txmpdu_be + stats.txmpdu_bk + stats.txmpdu_vi + stats.txmpdu_vo;
long txretries = stats.retries_be + stats.retries_bk
+ stats.retries_vi + stats.retries_vo;
long rxgood = stats.rxmpdu_be + stats.rxmpdu_bk + stats.rxmpdu_vi + stats.rxmpdu_vo;
long txbad = stats.lostmpdu_be + stats.lostmpdu_bk
+ stats.lostmpdu_vi + stats.lostmpdu_vo;

if (txBad <= txbad
&& txSuccess <= txgood
&& rxSuccess <= rxgood
&& txRetries <= txretries) {
txBadRate = (txBadRate * 0.5)
+ ((double) (txbad - txBad) * 0.5);
txSuccessRate = (txSuccessRate * 0.5)
+ ((double) (txgood - txSuccess) * 0.5);
rxSuccessRate = (rxSuccessRate * 0.5)
+ ((double) (rxgood - rxSuccess) * 0.5);
txRetriesRate = (txRetriesRate * 0.5)
+ ((double) (txretries - txRetries) * 0.5);
} else {
txBadRate = 0;
txSuccessRate = 0;
rxSuccessRate = 0;
txRetriesRate = 0;
}
txBad = txbad;
txSuccess = txgood;
rxSuccess = rxgood;
txRetries = txretries;
} else {
txBad = 0;
txSuccess = 0;
rxSuccess = 0;
txRetries = 0;
txBadRate = 0;
txSuccessRate = 0;
rxSuccessRate = 0;
txRetriesRate = 0;
}
}


/**
* This function is less powerful and used if the WifiLinkLayerStats API is not implemented
* at the Wifi HAL
* @hide
*/
public void updatePacketRates(long txPackets, long rxPackets) {
//paranoia
txBad = 0;
txRetries = 0;
txBadRate = 0;
txRetriesRate = 0;
if (txSuccess <= txPackets && rxSuccess <= rxPackets) {
txSuccessRate = (txSuccessRate * 0.5)
+ ((double) (txPackets - txSuccess) * 0.5);
rxSuccessRate = (rxSuccessRate * 0.5)
+ ((double) (rxPackets - rxSuccess) * 0.5);
} else {
txBadRate = 0;
txRetriesRate = 0;
}
txSuccess = txPackets;
rxSuccess = rxPackets;
}

/**
* Flag indicating that AP has hinted that upstream connection is metered,
* and sensitive to heavy data transfers.
*/
private boolean mMeteredHint;

/** @hide */
public WifiInfo() {
mWifiSsid = null;
mBSSID = null;
mNetworkId = -1;
mSupplicantState = SupplicantState.UNINITIALIZED;
mRssi = INVALID_RSSI;
mLinkSpeed = -1;
mFrequency = -1;
}

/** @hide */
public void reset() {
setInetAddress(null);
setBSSID(null);
setSSID(null);
setNetworkId(-1);
setRssi(INVALID_RSSI);
setLinkSpeed(-1);
setFrequency(-1);
setMeteredHint(false);
setEphemeral(false);
txBad = 0;
txSuccess = 0;
rxSuccess = 0;
txRetries = 0;
txBadRate = 0;
txSuccessRate = 0;
rxSuccessRate = 0;
txRetriesRate = 0;
lowRssiCount = 0;
badRssiCount = 0;
linkStuckCount = 0;
score = 0;
}

/**
* Copy constructor
* @hide
*/
public WifiInfo(WifiInfo source) {
if (source != null) {
mSupplicantState = source.mSupplicantState;
mBSSID = source.mBSSID;
mWifiSsid = source.mWifiSsid;
mNetworkId = source.mNetworkId;
mRssi = source.mRssi;
mLinkSpeed = source.mLinkSpeed;
mFrequency = source.mFrequency;
mIpAddress = source.mIpAddress;
mMacAddress = source.mMacAddress;
mMeteredHint = source.mMeteredHint;
mEphemeral = source.mEphemeral;
txBad = source.txBad;
txRetries = source.txRetries;
txSuccess = source.txSuccess;
rxSuccess = source.rxSuccess;
txBadRate = source.txBadRate;
txRetriesRate = source.txRetriesRate;
txSuccessRate = source.txSuccessRate;
rxSuccessRate = source.rxSuccessRate;
score = source.score;
badRssiCount = source.badRssiCount;
lowRssiCount = source.lowRssiCount;
linkStuckCount = source.linkStuckCount;
}
}

/** @hide */
public void setSSID(WifiSsid wifiSsid) {
mWifiSsid = wifiSsid;
}

/**
* Returns the service set identifier (SSID) of the current 802.11 network.
* If the SSID can be decoded as UTF-8, it will be returned surrounded by double
* quotation marks. Otherwise, it is returned as a string of hex digits. The
* SSID may be <unknown ssid> if there is no network currently connected.
* @return the SSID
*/
public String getSSID() {
if (mWifiSsid != null) {
String unicode = mWifiSsid.toString();
if (!TextUtils.isEmpty(unicode)) {
return "\"" + unicode + "\"";
} else {
return mWifiSsid.getHexString();
}
}
return WifiSsid.NONE;
}

/** @hide */
public WifiSsid getWifiSsid() {
return mWifiSsid;
}

/** @hide */
public void setBSSID(String BSSID) {
mBSSID = BSSID;
}

/**
* Return the basic service set identifier (BSSID) of the current access point.
* The BSSID may be {@code null} if there is no network currently connected.
* @return the BSSID, in the form of a six-byte MAC address: {@code XX:XX:XX:XX:XX:XX}
*/
public String getBSSID() {
return mBSSID;
}

/**
* Returns the received signal strength indicator of the current 802.11
* network, in dBm.
*
* <p>Use {@link android.net.wifi.WifiManager#calculateSignalLevel} to convert this number into
* an absolute signal level which can be displayed to a user.
*
* @return the RSSI.
*/
public int getRssi() {
return mRssi;
}

/** @hide */
public void setRssi(int rssi) {
if (rssi < INVALID_RSSI)
rssi = INVALID_RSSI;
if (rssi > MAX_RSSI)
rssi = MAX_RSSI;
mRssi = rssi;
}

/**
* Returns the current link speed in {@link #LINK_SPEED_UNITS}.
* @return the link speed.
* @see #LINK_SPEED_UNITS
*/
public int getLinkSpeed() {
return mLinkSpeed;
}

/** @hide */
public void setLinkSpeed(int linkSpeed) {
this.mLinkSpeed = linkSpeed;
}

/**
* Returns the current frequency in {@link #FREQUENCY_UNITS}.
* @return the frequency.
* @see #FREQUENCY_UNITS
*/
public int getFrequency() {
return mFrequency;
}

/** @hide */
public void setFrequency(int frequency) {
this.mFrequency = frequency;
}

/**
* @hide
* TODO: makes real freq boundaries
*/
public boolean is24GHz() {
return ScanResult.is24GHz(mFrequency);
}

/**
* @hide
* TODO: makes real freq boundaries
*/
public boolean is5GHz() {
return ScanResult.is5GHz(mFrequency);
}

/**
* Record the MAC address of the WLAN interface
* @param macAddress the MAC address in {@code XX:XX:XX:XX:XX:XX} form
* @hide
*/
public void setMacAddress(String macAddress) {
this.mMacAddress = macAddress;
}

public String getMacAddress() {
return mMacAddress;
}

最后的这个String getMacAddress();这个方法 他返回了一个mMacAddress . 这个mMacAdress 在类的开头直接赋值
public static final String DEFAULT_MAC_ADDRESS = "02:00:00:00:00:00";
    private String mMacAddress = DEFAULT_MAC_ADDRESS;

所以他返回了的是一个 02:00:00 这样的一个值。


如果我们只需要在这个地方做一些修改。把他真正的mac地址返回去就可以了:

//add by vincent qq:514505874
public String getMacAddress() {

if(mMacAddress.equals(DEFAULT_MAC_ADDRESS)){


return getWireMacAddr();

}else{
return mMacAddress;
}


}

getWriteMacAddr() 这个方法里面实现的就是把获取到的mac地址反馈回去。 实现的方法有很多种

例如直接通过CMD命令行获取mac地址:

private static final String ETH0_MAC_ADDR = "/sys/class/net/wlan0/address" ;

BufferedReader reader = new BufferedReader(new FileReader(ETH0_MAC_ADDR), 256);
try {
return reader.readLine();
} finally {
reader.close();
}
当然方法不止有这种。目的都是一样,只要能把 getMacAddress 这个旧api 的return 给返回一个真正的mac地址就可以了

欢迎沟通交流:QQ:514505874