文章目录
1 概要
本文主要讲述了安卓导航栏里WiFi信号的获取流程
安卓版本:各版本通用
2 整体架构流程
2.1 安卓10及其以下
a)跟WiFi UI强相关的内容,一般可以到如下目录中去寻找:packages/apps/Settings/src/com/android/settings/wifi/
b)在packages/apps/Settings/src/com/android/settings/wifi/details/下有一个WifiDetailPreferenceController.java 类,该类中会对WiFi的信息进行配置。
c)在WifiDetailPreferenceController中,首先可以看到其注册了一个BroadcastReceiver,主要接收的广播有:CONFIGURED_NETWORKS_CHANGED_ACTION、
NETWORK_STATE_CHANGED_ACTION、RSSI_CHANGED_ACTION,这里我们只关心RSSI_CHANGED_ACTION这个广播,在接受广播之后是调用了refreshPage()方法。
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
switch (intent.getAction()) {
case WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION:
if (!intent.getBooleanExtra(WifiManager.EXTRA_MULTIPLE_NETWORKS_CHANGED,
false /* defaultValue */)) {
// only one network changed
WifiConfiguration wifiConfiguration = intent
.getParcelableExtra(WifiManager.EXTRA_WIFI_CONFIGURATION);
if (mAccessPoint.matches(wifiConfiguration)) {
mWifiConfig = wifiConfiguration;
}
}
// fall through
case WifiManager.NETWORK_STATE_CHANGED_ACTION:
case WifiManager.RSSI_CHANGED_ACTION:
refreshPage();
break;
}
}
};
d)在refreshPage()方法中,首先会通过updateAccessPoint()来判断AP的信息是否有更新,有更新的话其次则会refresh各类信息,这里我们只关心refreshRssiViews()。
private void refreshPage() {
if(!updateAccessPoint()) {
return;
}
Log.d(TAG, "Update UI!");
// refresh header
refreshEntityHeader();
// refresh Buttons
refreshButtons();
// Update Connection Header icon and Signal Strength Preference
refreshRssiViews();
// Frequency Pref
refreshFrequency();
// Transmit Link Speed Pref
refreshTxSpeed();
// Receive Link Speed Pref
refreshRxSpeed();
// IP related information
refreshIpLayerInfo();
// SSID Pref
refreshSsid();
// MAC Address Pref
refreshMacAddress();
}
e)在refreshRssiViews()方法中,首先就会调用mAccessPoint.getLevel()来获取当前信号强度信息;其次则会判断RSSI是否在指定范围,如果不在指定范围则将其控件不显示,并且将信号强度设置为-1;最后则是通过mIconInjector.getIcon(mRssiSignalLevel)和mSignalStrengthPref.setIcon(wifiIconDark)来设置界面的WiFi信号强度。
private void refreshRssiViews() {
int signalLevel = mAccessPoint.getLevel();
// Disappears signal view if not in range. e.g. for saved networks.
if (mIsOutOfRange) {
mSignalStrengthPref.setVisible(false);
mRssiSignalLevel = -1;
return;
}
if (mRssiSignalLevel == signalLevel) {
return;
}
mRssiSignalLevel = signalLevel;
Drawable wifiIcon = mIconInjector.getIcon(mRssiSignalLevel);
if (mEntityHeaderController != null) {
mEntityHeaderController
.setIcon(redrawIconForHeader(wifiIcon)).done(mFragment.getActivity(),
true /* rebind */);
}
Drawable wifiIconDark = wifiIcon.getConstantState().newDrawable().mutate();
wifiIconDark.setTintList(Utils.getColorAttr(mContext, android.R.attr.colorControlNormal));
mSignalStrengthPref.setIcon(wifiIconDark);
mSignalStrengthPref.setSummary(mSignalStr[mRssiSignalLevel]);
mSignalStrengthPref.setVisible(true);
}
f)在AccessPoint.getLevel()方法中,会调用WifiManager.calculateSignalLevel(mRssi, SIGNAL_LEVELS)来获取到RSSI以及信号强度。
PS:AccessPoint类中都是一些WiFi的信息,例如BSSID、SSID、安全类型、RSSI等。
/**
* Returns the number of levels to show for a Wifi icon, from 0 to {@link #SIGNAL_LEVELS}-1.
*
* <p>Use {@#isReachable()} to determine if an AccessPoint is in range, as this method will
* always return at least 0.
*/
public int getLevel() {
return WifiManager.calculateSignalLevel(mRssi, SIGNAL_LEVELS);
}
g)在WifiManager.calculateSignalLevel()方法中,会通过传进来的RSSI进行信号强度的计算。首先会判断当前的Rssi是否小于最小的Rssi,并且大于最大的Rssi(MIN_RSSI=-100、MAX_RSSI=-55);其次如果当前Rssi符合要求的话,则会对WiFi信号强度进行计算,最后会对计算出的结果进行取整,并返回到UI界面中。
例:如果当前的Rssi为-60,则计算来的WiFi信号强度为:(-60+100)* 4 / (-55+100)= 3.55555556 ,最后对结果进行向下取整,最后输出的WiFi信号强度等级为3。
/**
* Calculates the level of the signal. This should be used any time a signal
* is being shown.
*
* @param rssi The power of the signal measured in RSSI.
* @param numLevels The number of levels to consider in the calculated
* level.
* @return A level of the signal, given in the range of 0 to numLevels-1
* (both inclusive).
*/
public static int calculateSignalLevel(int rssi, int numLevels) {
if (rssi <= MIN_RSSI) {
return 0;
} else if (rssi >= MAX_RSSI) {
return numLevels - 1;
} else {
float inputRange = (MAX_RSSI - MIN_RSSI);
float outputRange = (numLevels - 1);
return (int)((float)(rssi - MIN_RSSI) * outputRange / inputRange);
}
}
如上就是大致的获取WiFi信号强度的流程 ,但是这只适用于安卓10以及安卓10以下的版本,安卓11及其以上,在WifiManager.calculateSignalLevel()的使用上会有些许差别。
2.2 安卓11及其以上
a)安卓10和安卓11的差别在于AccessPoint.getLevel()方法,可以看到安卓10传进了两个参数,而安卓11只传进了一个参数。
安卓10:WifiManager.calculateSignalLevel(mRssi, SIGNAL_LEVELS)
安卓11:getWifiManager().calculateSignalLevel(mRssi)
b)其次在WifiManager中可以看到, calculateSignalLevel(int rssi, int numLevels)是被废弃的接口,而真正被使用的是calculateSignalLevel(int rssi)这个接口。在calculateSignalLevel()方法中则会调用WifiServiceImpl的calculateSignalLevel()方法。
c)在WifiServiceImpl.calculateSignalLevel()方法中,会调用RssiUtil.calculateSignalLevel()。
@Override
public int calculateSignalLevel(int rssi) {
return RssiUtil.calculateSignalLevel(mContext, rssi);
}
d)在RssiUtil.calculateSignalLevel()方法中首先会通过getRssiLevelThresholds()来获取到rssi对应的信号强度;其次通过循环计算出当前的信号强度为多少。
数组thresholds的具体数值如下:
<integer-array translatable="false" name="config_wifiRssiLevelThresholds">
<!-- RSSI RSSI Level -->
<item>-88</item> <!-- (-infinity, -88) 0 -->
<item>-77</item> <!-- [-88, -77) 1 -->
<item>-66</item> <!-- [-77, -66) 2 -->
<item>-55</item> <!-- [-66, -55) 3 -->
<!-- [-55, +infinity) 4 -->
</integer-array>
例:如果当前的Rssi为-60,首先会对比thresholds[0],-60>-88;继续进行对比thresholds[1],-60>-77;继续进行对比thresholds[2],-60>-66;继续进行对比thresholds[3]。-60<-55,所以当前RSSI对应的信号强度为:3。
/** Calculate RSSI level from RSSI using overlaid RSSI level thresholds. */
public static int calculateSignalLevel(Context context, int rssi) {
int[] thresholds = getRssiLevelThresholds(context);
for (int level = 0; level < thresholds.length; level++) {
if (rssi < thresholds[level]) {
return level;
}
}
return thresholds.length;
}
@NonNull
private static int[] getRssiLevelThresholds(Context context) {
// getIntArray() will never return null, it will throw instead
return context.getResources().getIntArray(R.array.config_wifiRssiLevelThresholds);
}
3 小结
RSSI对应的信号强度差不多就是通过如上流程来获取的,如果要是客户有一些定制化的需求,例如要修改RSSI的阈值:
a)安卓10及其以下则可以通过修改WifiManager.calculateSignalLevel()中计算RSSI对应信号强度的逻辑来达到目的。(rssi在某个范围内就返回多少的信号强度)
b)在安卓11及其以上则可以通过修改packages/modules/Wifi/service/ServiceWifiResources/res/values/config.xml中config_wifiRssiLevelThresholds的<item>值来达到目的。
标签:return,calculateSignalLevel,int,安卓,WiFi,信号强度,RSSI From: https://blog.csdn.net/weixin_45316524/article/details/136596119