Android 長按電源鍵和短按電源鍵的詳細處理流程
1 Android
Android4.x在Framework的PhoneWindowManager對Power(KeyEvent.KEYCODE_POWER)和Home(KeyEvent.KEYCODE_HOME)鍵做了處理,不會把這些鍵傳送上層應用程式。如需要把這些鍵傳送給Activity和Service,需要在PhoneWindowManager處理這些鍵時“傳送一個廣播出去,然後在應用程式接收到廣播後做處理”。
如果應用程式只需要獲取獲取待機、喚醒、關機、網路狀態變化訊息,則可監聽以下廣播訊息:
1) 待機:
廣播訊息:android.intent.action.SCREEN_OFF (程式碼)
2) 喚醒:
廣播訊息:android.intent.action.SCREEN_ON (程式碼)
3) 關機:
廣播訊息:android.intent.action.ACTION_SHUTDOWN (XML或程式碼)
4) 網路狀態變化:
廣播訊息:android.net.conn.CONNECTIVITY_CHANGE (XML或程式碼)
然後呼叫下面的isNetworkAvailable獲取當前網路狀態。
public static boolean isNetworkAvailable(Context context) {
ConnectivityManager mgr = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo[] info = mgr.getAllNetworkInfo();
if (info != null) {
for (int i = 0; i < info.length; i++) {
if (info[i].getState() == NetworkInfo.State.CONNECTED) {
return true;
}
}
}
return false;
}
2. 短按Power鍵處理流程
短按Power鍵處理流程如下圖所示:
3. 長按Power鍵處理流程
長按Power鍵處理流程如下圖所示:
3.1 Message超時處理流程
如果長按Power鍵(超過500ms),則此訊息(Message.callback為mPowerLongPress)將被執行。mPowerLongPress (PhoneWindowManager.java)定義如下:
- privatefinal Runnable mPowerLongPress = new Runnable() {
-
public
- // The context isn't read
- if (mLongPressOnPowerBehavior < 0) {
- mLongPressOnPowerBehavior = mContext.getResources().getInteger(
- com.android.internal.R.integer.config_longPressOnPowerBehavior);
- }
-
switch (mLongPressOnPowerBehavior) {
- case LONG_PRESS_POWER_NOTHING:
- break;
- case LONG_PRESS_POWER_GLOBAL_ACTIONS:
- mPowerKeyHandled = true;
- performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
- sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
- showGlobalActionsDialog();
- break;
- case LONG_PRESS_POWER_SHUT_OFF:
- mPowerKeyHandled = true;
- performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
- sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
- ShutdownThread.shutdown(mContext, true);
- break;
- }
- }
- };
它是一個匿名內部類,它是一個實現Runnable的類的物件引用,因此
new Runnable() {
public void run(){
...
}
};
它包括了定義這個類(只不過這個類沒有名字)和例項化這個類的物件。
當超時時,其執行流程如下圖所示:
3.2 reboot系統呼叫流程
reboot系統呼叫流程如下圖所示:
4. 如何處理短按和長按電源鍵
長按電源鍵:彈出關機確認對話方塊(KeyDown之後,如果 500ms之內,沒有收到KeyUp則彈出關機確認對話方塊)
短按電源鍵:執行待機(KeyUp時執行<wmActions=4>)或喚醒(KeyDown時執行<wmActions=2>)
對於長按電源鍵,在PhoneWindowManager.java的interceptKeyBeforeQueueing函式中進行處理,其相關程式碼如下 :
- case KeyEvent.KEYCODE_POWER: {
- result &= ~ACTION_PASS_TO_USER;
- if (down) {
- if (isScreenOn && !mPowerKeyTriggered
- && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
- mPowerKeyTriggered = true;
- mPowerKeyTime = event.getDownTime();
- interceptScreenshotChord();
- }
- ...
- // Power Key down, set mPowerLongPress executing after 500ms
- interceptPowerKeyDown(!isScreenOn || hungUp
- || mVolumeDownKeyTriggered || mVolumeUpKeyTriggered);
- } else {
- mPowerKeyTriggered = false;
- cancelPendingScreenshotChordAction();
- if (interceptPowerKeyUp(canceled || mPendingPowerKeyUpCanceled)) {
- result = (result & ~ACTION_POKE_USER_ACTIVITY) | ACTION_GO_TO_SLEEP;
- }
- // Power key up, remove the mPowerLongPress, that is, if user release
- // power key during 500ms, mPowerLongPress will not be execute, then execute sleep
- mPendingPowerKeyUpCanceled = false;
- }
- break;
- }
- privatevoid interceptPowerKeyDown(boolean handled) {
- mPowerKeyHandled = handled;
- if (!handled) {
- mHandler.postDelayed(mPowerLongPress, ViewConfiguration.getGlobalActionKeyTimeout()/*500ms*/);
- }
- }
- privateboolean interceptPowerKeyUp(boolean canceled) {
- if (!mPowerKeyHandled) {
- mHandler.removeCallbacks(mPowerLongPress);
- return !canceled;
- }
- returnfalse;
- }