天天看點

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;  

    } 

    短按power鍵處理流程如下圖所示:

Android 長按電源鍵和短按電源鍵的詳細處理流程

      長按power鍵處理流程如下圖所示:       

Android 長按電源鍵和短按電源鍵的詳細處理流程

      如果長按power鍵(超過500ms),則此消息(message.callback為mpowerlongpress)将被執行。mpowerlongpress (phonewindowmanager.java)定義如下:

[java] view

plaincopy

Android 長按電源鍵和短按電源鍵的詳細處理流程
Android 長按電源鍵和短按電源鍵的詳細處理流程

private final runnable mpowerlongpress = new runnable() {    

    public void run() {    

        // 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();    

        case long_press_power_shut_off:    

            shutdownthread.shutdown(mcontext, true);    

    }    

};    

它是一個匿名内部類,它是一個實作runnable的類的對象引用,是以

     new runnable() {

         public void run(){

         ...

         }

     };

     它包括了定義這個類(隻不過這個類沒有名字)和執行個體化這個類的對象。

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

Android 長按電源鍵和短按電源鍵的詳細處理流程

 reboot系統調用流程如下圖所示:

Android 長按電源鍵和短按電源鍵的詳細處理流程

     長按電源鍵:彈出關機确認對話框(keydown之後,如果 500ms之内,沒有收到keyup則彈出關機确認對話框)

     短按電源鍵:執行待機(keyup時執行<wmactions=4>)或喚醒(keydown時執行<wmactions=2>)

     對于長按電源鍵,在phonewindowmanager.java的interceptkeybeforequeueing函數中進行處理,其相關代碼如下 :

Android 長按電源鍵和短按電源鍵的詳細處理流程
Android 長按電源鍵和短按電源鍵的詳細處理流程

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;    

}    

Android 長按電源鍵和短按電源鍵的詳細處理流程
Android 長按電源鍵和短按電源鍵的詳細處理流程

private void interceptpowerkeydown(boolean handled) {    

    mpowerkeyhandled = handled;    

    if (!handled) {    

        mhandler.postdelayed(mpowerlongpress, viewconfiguration.getglobalactionkeytimeout()/*500ms*/);    

private boolean interceptpowerkeyup(boolean canceled) {    

    if (!mpowerkeyhandled) {    

        mhandler.removecallbacks(mpowerlongpress);    

        return !canceled;    

    return false;    

}    

繼續閱讀