1. 状态栏信号图标
1.1 WIFI信号显示
WIFI信号在状态栏的显示如下图所示
当WiFi状态为关闭时,状态栏不会有任何显示。当WiFi状态打开时,会如上图所示,左侧表示有可用WiFi,右侧表示当前WiFi打开但未连接。
当WiFi状态连接时,会如上图所示,显示信号连接强度和数据连接状态。
1.2 图标更新流程框架
如图所示,WiFi图标的显示流程主要是通过监听系统的WiFi状态,然后通知UI去事实的刷新图标资源。NetworkController.java 继承 BroadcastReceiver 监听系统WiFi状态的变化。
2. WIFI图标更新流介绍
2.1 重要类
frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
定义相关函数,继承BroadcastReceiver监听系统广播,动态注册广播接收器。是状态栏WiFi图标更新的核心类。
frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiIcons.java
定义了 Wifi 信号更新所需的图标资源。
frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
与signal_cluster_view.xml文件相对应,定义了状态上信号簇以及图片资源更新的相关方法。
2.2 WIFI图标更新流程
(1)NetworkController实例化,在PhoneStatusBar.java进行实例化
protected PhoneStatusBarView makeStatusBarView() {
final Context context = mContext;
//此处省略部分代码
//...
mNetworkController = new NetworkController(mContext);
mBluetoothController = new BluetoothController(mContext);
mRotationLockController = new RotationLockController(mContext);
final SignalClusterView signalCluster =
(SignalClusterView)mStatusBarView.findViewById(R.id.signal_cluster);
mNetworkController.addSignalCluster(signalCluster);
signalCluster.setNetworkController(mNetworkController);
//此处省略部分代码
//...
}
(2) 初次更新WIFI图标
NetworkController.java
/**
* Construct this controller object and register for updates.
*/
public NetworkController(Context context) {
mContext = context;
//此处省略部分代码...
//...
// broadcasts
IntentFilter filter = new IntentFilter();
filter.addAction(WifiManager.RSSI_CHANGED_ACTION);
filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
filter.addAction(TelephonyIntents.SPN_STRINGS_UPDATED_ACTION);
filter.addAction(SimManager.INSERT_SIMS_CHANGED_ACTION);
//此处省略部分代码...
//...
/* @} */
context.registerReceiver(this, filter);
//此处省略部分代码...
//...
}
public void addSignalCluster(SignalCluster cluster) {
mSignalClusters.add(cluster);
refreshSignalCluster(cluster);
}
public void refreshSignalCluster(SignalCluster cluster) {
if (mDemoMode) {return;}
cluster.setWifiIndicators(
// only show wifi in the cluster if connected or if wifi-only
mWifiEnabled, mWifiConnected,
mWifiIconId,
mWifiActivityIconId,
mContentDescriptionWifi);
//此处省略部分代码...
//...
}
SignalClusterView.java
@Override
public void setWifiIndicators(boolean visible,boolean connected, int strengthIcon, int activityIcon,
String contentDescription) {
mWifiVisible = visible;
mWifiConnected = connected;
mWifiStrengthId = strengthIcon;
mWifiActivityId = activityIcon;
mWifiDescription = contentDescription;
apply(0);
}
// Run after each indicator change.
private void apply(int phoneId) {
//此处省略部分代码...
//...
if (mWifiVisible && !mVoWifiVisible) {
mWifiGroup.setVisibility(View.VISIBLE);
mWifiSignal.setImageResource(mWifiStrengthId);
mWifiActivity.setImageResource(mWifiActivityId);
mWifiGroup.setContentDescription(mWifiDescription);
} else {
mWifiGroup.setVisibility(View.GONE);
}
//此处省略部分代码...
//...
}
(3)WiFi状态变化时更新状态栏图标
当WiFi状态变化时会收到状态变化的广播
NetworkController.java
@Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
/* SPRD: for multi-sim @{ */
Log.d(TAG, "action: "+intent.getAction());
mDDS = TelephonyManager.getDefault().getDefaultDataPhoneId(context);
if (action.equals(WifiManager.RSSI_CHANGED_ACTION)
|| action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)
|| action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
updateWifiState(intent);
refreshViews(mDDS);
}
//此处省略部分代码...
//...
}
从intent中获取WiFi参数,是否连接,信号强度等
private void updateWifiState(Intent intent) {
final String action = intent.getAction();
if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
mWifiEnabled = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
WifiManager.WIFI_STATE_UNKNOWN) == WifiManager.WIFI_STATE_ENABLED;
} else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
final NetworkInfo networkInfo = (NetworkInfo) intent
.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
boolean wasConnected = mWifiConnected;
mWifiConnected = networkInfo != null && networkInfo.isConnected();
// If we just connected, grab the inintial signal strength and ssid
if (mWifiConnected && !wasConnected) {
// try getting it out of the intent first
WifiInfo info = (WifiInfo) intent
.getParcelableExtra(WifiManager.EXTRA_WIFI_INFO);
if (info == null) {
info = mWifiManager.getConnectionInfo();
}
if (info != null) {
mWifiSsid = huntForSsid(info);
} else {
mWifiSsid = null;
}
} else if (!mWifiConnected) {
mWifiSsid = null;
}
} else if (action.equals(WifiManager.RSSI_CHANGED_ACTION)) {
mWifiRssi = intent.getIntExtra(WifiManager.EXTRA_NEW_RSSI, -200);
mWifiLevel = WifiManager.calculateSignalLevel(mWifiRssi,
WifiIcons.WIFI_LEVEL_COUNT - 1) + 1;
}
updateWifiIcons();
}
根据数据匹配对应的图标id
private void updateWifiIcons() {
if (mWifiConnected) {
mWifiIconId = WifiIcons.WIFI_SIGNAL_STRENGTH[mInetCondition][mWifiLevel];
mQSWifiIconId = WifiIcons.QS_WIFI_SIGNAL_STRENGTH[mInetCondition][mWifiLevel];
mContentDescriptionWifi = mContext
.getString(AccessibilityContentDescriptions.WIFI_CONNECTION_STRENGTH[mWifiLevel]);
/* SPRD: Add for VoWifi in bug 629758. @{ */
int length = mSignalClusters.size();
for (int i = 0; i < length; i++) {
mSignalClusters.get(i).setWifiLevel(mWifiLevel);
}
/* @} */
} else {
if (mDataAndWifiStacked) {
mWifiIconId = 0;
mQSWifiIconId = 0;
} else {
mWifiIconId = mWifiEnabled ? R.drawable.stat_sys_wifi_signal_null
: 0;
mQSWifiIconId = mWifiEnabled ? R.drawable.ic_qs_wifi_no_network
: 0;
}
mContentDescriptionWifi = mContext
.getString(R.string.accessibility_no_wifi);
}
}
根据匹配好的图标id通过refreshSignalCluster(cluster)进行状态栏刷新
void refreshViews(int phoneId) {
//此处省略部分代码...
//...
if (mLastPhoneSignalIconId[phoneId] != mPhoneSignalIconId[phoneId]
|| mLastDataDirectionOverlayIconId[phoneId] != combinedActivityIconId
|| mLastWifiIconId != mWifiIconId
|| mLastWimaxIconId != mWimaxIconId
|| mLastDataTypeIconId[phoneId] != mDataTypeIconId[phoneId]
|| mLastAirplaneMode != mAirplaneMode || mLastLocale != mLocale
|| mLastWifiActivityIconId != mWifiActivityIconId
// SPRD: modify for bug328207: refresh roaming icon immediately if changed
|| mLastMobileDataRoamingId[phoneId] != mMobileDataRoamingId[phoneId]
// SPRD: Reliance UI spec 1.8. See bug #622109.
|| mLastMobileVoLTEId[phoneId] != mMobileVoLTEId[phoneId]
/* SPRD: to fix bug 255331: icon dont't update timely {@ */
|| mLastDataSignalIconId[phoneId] != mDataSignalIconId[phoneId]
|| mLastMobileActivityIconId[phoneId] != mMobileActivityIconId[phoneId]
|| (isSupportLTE && (mLastPhoneSignalIconId[mLTEId] != mPhoneSignalIconId[mLTEId]))) {
/* @} */
// NB: the mLast*s will be updated later
for (SignalCluster cluster : mSignalClusters) {
refreshSignalCluster(cluster);
}
for (NetworkSignalChangedCallback cb : mSignalsChangedCallbacks) {
notifySignalsChangedCallbacks(cb);
}
}
//此处省略部分代码...
//...
}
WifiIcons.java代码如下:
class WifiIcons {
static final int[][] WIFI_SIGNAL_STRENGTH = {
{R.drawable.stat_sys_wifi_signal_0,
R.drawable.stat_sys_wifi_signal_1_fully,
R.drawable.stat_sys_wifi_signal_2_fully,
R.drawable.stat_sys_wifi_signal_3_fully,
R.drawable.stat_sys_wifi_signal_4_fully },
{R.drawable.stat_sys_wifi_signal_0,
R.drawable.stat_sys_wifi_signal_1_fully,
R.drawable.stat_sys_wifi_signal_2_fully,
R.drawable.stat_sys_wifi_signal_3_fully,
R.drawable.stat_sys_wifi_signal_4_fully }
};
static final int[][] QS_WIFI_SIGNAL_STRENGTH = {
{ R.drawable.ic_qs_wifi_0,
R.drawable.ic_qs_wifi_1,
R.drawable.ic_qs_wifi_2,
R.drawable.ic_qs_wifi_3,
R.drawable.ic_qs_wifi_4 },
{ R.drawable.ic_qs_wifi_0,
R.drawable.ic_qs_wifi_full_1,
R.drawable.ic_qs_wifi_full_2,
R.drawable.ic_qs_wifi_full_3,
R.drawable.ic_qs_wifi_full_4 }
};
static final int WIFI_LEVEL_COUNT = WIFI_SIGNAL_STRENGTH[0].length;
}