-
和傳統終端的狀態欄一樣,Android狀態欄同樣提供了電量信息、蜂窩信息、SMS、MMS、郵件、WiFi信號、藍牙信號、鬧鐘等系統的狀態信息。另外,Android狀態欄還提供了應用的安裝、數據的下載等智能終端特有的狀態信息。除此之外,Android狀態欄還承擔着通知欄的功能,使用戶能以最少的操作查看收到的信息。狀態欄的框架如圖1-10所示。
在狀態欄框架中,起主要作用的是StatusBarPolicy,它承擔着接收系統發來的Intent信息、更新狀態顯示的功能,它是服務StatusBarManagerService的客戶端。 StatusBarManagerService在創建時會加載config_statusBarIcons數組。在frameworks\base\core\res\res\values\目錄下的config.xml中定義的config_statusBarIcons數組確定了狀態圖標的加載順序。
整個狀態欄框架是通過StatusBarService來實現的。在StatusBarService初始化時初始化了一個用於顯示statusbar 的StatusBarView。在StatusBarView中定義了狀態欄的實現佈局,而具體的佈局文件是在frameworks\base\packages\systemui\res\layout\ status_bar.xml中實現的。
下面介紹狀態欄的隱藏及幾種重要狀態的更新實現。
1. 狀態欄的隱藏
通過AndroidManifest.xml設置全屏的方法如下:
<activity android:name="GL2JNIActivity"
android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen">
...
</activity>下面是通過Java設置全屏的方法:
//將視圖設爲全屏,隱藏狀態欄
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
requestWindowFeature(Window.FEATURE_NO_TITLE); //隱藏標題欄考慮到在執行onCreate()方法時,已經加載了視圖,在通過Java代碼實現隱藏狀態欄、標題欄時,用戶在視覺上可以感受到隱藏的過程。如果不希望用戶有這樣的感受,可通過AndroidManifest.xml設置全屏。
以上隱藏狀態欄的方法只適合靜態場景,在隱藏標題欄後再動態顯示狀態欄已經超出以上兩種方法的能力了。此時,可通過下面的方法實現動態隱藏和顯示狀態欄:
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);//隱藏
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);//顯示2. 電量信息
當StatusBarPolicy收到Action爲ACTION_BATTERY_CHANGED的Intent時,StatusBarPolicy會通知StatusBarManager進行電量圖標的更新,示例如下:
private final void updateBattery(Intent intent) {
final int id = intent.getIntExtra("icon-small", 0);
int level = intent.getIntExtra("level", 0);
mService.setIcon("battery", id, level);
boolean plugged = intent.getIntExtra("plugged", 0) != 0;
level = intent.getIntExtra("level", -1);
if (false) {
Slog.d(TAG, "updateBattery level=" + level
+ " plugged=" + plugged
+ " mBatteryPlugged=" + mBatteryPlugged
+ " mBatteryLevel=" + mBatteryLevel
+ " mBatteryFirst=" + mBatteryFirst);
}
boolean oldPlugged = mBatteryPlugged;
mBatteryPlugged = plugged;
mBatteryLevel = level;
if (mBatteryFirst) {
mBatteryFirst = false;
}
if (false) {
Slog.d(TAG, "plugged=" + plugged + " oldPlugged=" + oldPlugged + " level=" + level);
}
}除了Action爲ACTION_BATTERY_CHANGED的Intent外,StatusBarPolicy還能響應Action爲ACTION_BATTERY_LOW、ACTION_BATTERY_OKAY、ACTION_POWER_CONNECTED的Intent。
3. 蜂窩信息
Android對蜂窩協議的支持十分充分,目前內置的支持包括GSM、UMTS、CDMA、4G等。
4. WiFi信號
對於WiFi信號,Android可以響應Action爲WifiManager.NETWORK_STATE_CHANGED_ ACTION、WifiManager.WIFI_STATE_CHANGED_ACTION、WifiManager.RSSI_CHANGED_ ACTION的Intent,相應的更新方法如代碼清單1-5所示。
代碼清單1-5 WiFi信號的更新
private final void updateWifi(Intent intent) {
final String action = intent.getAction();
if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
final boolean enabled = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
WifiManager.WIFI_STATE_UNKNOWN) == WifiManager.WIFI_STATE_ENABLED;
if (!enabled) {
// 如果WiFi關閉,隱藏WiFi圖標
mService.setIconVisibility("wifi", false);
}
} else if (action.equals(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION)) {
final boolean enabled = intent.getBooleanExtra(
WifiManager.EXTRA_SUPPLICANT_CONNECTED,false);
if (!enabled) {
mService.setIconVisibility("wifi", false);
}
} else if (action.equals(WifiManager.RSSI_CHANGED_ACTION)) {
int iconId;
final int newRssi = intent.getIntExtra(WifiManager.EXTRA_NEW_RSSI, -200);
int newSignalLevel = WifiManager.calculateSignalLevel(newRssi, sWifiSignalImages[0].length);
if (newSignalLevel != mLastWifiSignalLevel) {
mLastWifiSignalLevel = newSignalLevel;
if (mIsWifiConnected) {
iconId = sWifiSignalImages[mInetCondition][newSignalLevel];
} else {
iconId = sWifiTemporarilyNotConnectedImage;
}
mService.setIcon("wifi", iconId, 0);
}
}
}另外,Android還對WiMax提供了內置支持。
5. 藍牙信號
對於藍牙信號,Android目前可以響應BluetoothAdapter、BluetoothHeadset、BluetoothA2dp和BluetoothPbap的狀態變化,相應的更新方法如代碼清單1-6所示。
代碼清單1-6 藍牙信號的更新
private final void updateBluetooth(Intent intent) {
int iconId = R.drawable.stat_sys_data_bluetooth;
String action = intent.getAction();
if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);
mBluetoothEnabled = state == BluetoothAdapter.STATE_ON;
} else if (action.equals(BluetoothHeadset.ACTION_STATE_CHANGED)) {
mBluetoothHeadsetState = intent.getIntExtra(
BluetoothHeadset.EXTRA_STATE,BluetoothHeadset.STATE_ERROR);
} else if (action.equals(BluetoothA2dp.ACTION_SINK_STATE_CHANGED)) {
BluetoothA2dp a2dp = new BluetoothA2dp(mContext);
if (a2dp.getConnectedSinks().size() != 0) {
mBluetoothA2dpConnected = true;
} else {
mBluetoothA2dpConnected = false;
}
} else if (action.equals(BluetoothPbap.PBAP_STATE_CHANGED_ACTION)) {
mBluetoothPbapState = intent.getIntExtra(
BluetoothPbap.PBAP_STATE,BluetoothPbap.STATE_DISCONNECTED);
} else {
return;
}
if (mBluetoothHeadsetState == BluetoothHeadset.STATE_CONNECTED || mBluetoothA2dpConnected ||
mBluetoothPbapState == BluetoothPbap.STATE_CONNECTED) {
iconId = R.drawable.stat_sys_data_bluetooth_connected;
}
mService.setIcon("bluetooth", iconId, 0);
mService.setIconVisibility("bluetooth", mBluetoothEnabled);
}6. 鬧鐘
當StatusBarPolicy收到Action爲ACTION_ALARM_CHANGED的Intent時, StatusBarPolicy會通知StatusBarManager進行鬧鐘圖標的更新,相應示例如下:
private final void updateAlarm(Intent intent) {
boolean alarmSet = intent.getBooleanExtra("alarmSet", false);
mService.setIconVisibility("alarm_clock", alarmSet);
}
狀態欄框架-- 深入Android應用開發:核心技術解析與最佳實踐
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.