1. 程式人生 > >Android 長按電源鍵和短按電源鍵的詳細處理流程

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)定義如下:

  1. privatefinal Runnable mPowerLongPress = new Runnable() {    
  2.     public
    void run() {    
  3.         // The context isn't read  
  4.         if (mLongPressOnPowerBehavior < 0) {    
  5.             mLongPressOnPowerBehavior = mContext.getResources().getInteger(    
  6.                     com.android.internal.R.integer.config_longPressOnPowerBehavior);    
  7.         }    
  8.         switch (mLongPressOnPowerBehavior) {    
  9.         case LONG_PRESS_POWER_NOTHING:    
  10.             break;    
  11.         case LONG_PRESS_POWER_GLOBAL_ACTIONS:    
  12.             mPowerKeyHandled = true;    
  13.             performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);    
  14.             sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);    
  15.             showGlobalActionsDialog();    
  16.             break;    
  17.         case LONG_PRESS_POWER_SHUT_OFF:    
  18.             mPowerKeyHandled = true;    
  19.             performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);    
  20.             sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);    
  21.             ShutdownThread.shutdown(mContext, true);    
  22.             break;    
  23.         }    
  24.     }    
  25. };    

它是一個匿名內部類,它是一個實現Runnable的類的物件引用,因此

     new Runnable() {

         public void run(){

         ...

         }

     };

     它包括了定義這個類(只不過這個類沒有名字)和例項化這個類的物件。

      當超時時,其執行流程如下圖所示:

     

 3.2 reboot系統呼叫流程

 reboot系統呼叫流程如下圖所示:

 4. 如何處理短按和長按電源鍵

     長按電源鍵:彈出關機確認對話方塊(KeyDown之後,如果 500ms之內,沒有收到KeyUp則彈出關機確認對話方塊)

     短按電源鍵:執行待機(KeyUp時執行<wmActions=4>)或喚醒(KeyDown時執行<wmActions=2>)

     對於長按電源鍵,在PhoneWindowManager.java的interceptKeyBeforeQueueing函式中進行處理,其相關程式碼如下 :

  1. case KeyEvent.KEYCODE_POWER: {    
  2.     result &= ~ACTION_PASS_TO_USER;    
  3.     if (down) {    
  4.         if (isScreenOn && !mPowerKeyTriggered    
  5.                 && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {    
  6.             mPowerKeyTriggered = true;    
  7.             mPowerKeyTime = event.getDownTime();    
  8.             interceptScreenshotChord();    
  9.         }    
  10.         ...    
  11.         // Power Key down, set mPowerLongPress executing after 500ms  
  12.         interceptPowerKeyDown(!isScreenOn || hungUp    
  13.                 || mVolumeDownKeyTriggered || mVolumeUpKeyTriggered);    
  14.     } else {    
  15.         mPowerKeyTriggered = false;    
  16.         cancelPendingScreenshotChordAction();    
  17.         if (interceptPowerKeyUp(canceled || mPendingPowerKeyUpCanceled)) {    
  18.             result = (result & ~ACTION_POKE_USER_ACTIVITY) | ACTION_GO_TO_SLEEP;    
  19.         }    
  20.         // Power key up, remove the mPowerLongPress, that is, if user release  
  21.         // power key during 500ms, mPowerLongPress will not be execute, then execute sleep  
  22.         mPendingPowerKeyUpCanceled = false;    
  23.     }    
  24.     break;    
  25. }    
  1. privatevoid interceptPowerKeyDown(boolean handled) {    
  2.     mPowerKeyHandled = handled;    
  3.     if (!handled) {    
  4.         mHandler.postDelayed(mPowerLongPress, ViewConfiguration.getGlobalActionKeyTimeout()/*500ms*/);    
  5.     }    
  6. }    
  7. privateboolean interceptPowerKeyUp(boolean canceled) {    
  8.     if (!mPowerKeyHandled) {    
  9.         mHandler.removeCallbacks(mPowerLongPress);    
  10.         return !canceled;    
  11.     }    
  12.     returnfalse;    
  13. }