zoukankan      html  css  js  c++  java
  • [置顶] Android4.x对长按电源键(挂断键)和短按电源键(挂断键)的详细处理流程

    1. 简介

            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. private final 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.         ...  
    12.         // Power Key down, set mPowerLongPress executing after 500ms  
    13.         interceptPowerKeyDown(!isScreenOn || hungUp  
    14.                 || mVolumeDownKeyTriggered || mVolumeUpKeyTriggered);  
    15.     } else {  
    16.         mPowerKeyTriggered = false;  
    17.         cancelPendingScreenshotChordAction();  
    18.         if (interceptPowerKeyUp(canceled || mPendingPowerKeyUpCanceled)) {  
    19.             result = (result & ~ACTION_POKE_USER_ACTIVITY) | ACTION_GO_TO_SLEEP;  
    20.         }  
    21.         // Power key up, remove the mPowerLongPress, that is, if user release  
    22.         // power key during 500ms, mPowerLongPress will not be execute, then execute sleep  
    23.         mPendingPowerKeyUpCanceled = false;  
    24.     }  
    25.     break;  
    26. }  
    1. private void interceptPowerKeyDown(boolean handled) {  
    2.     mPowerKeyHandled = handled;  
    3.     if (!handled) {  
    4.         mHandler.postDelayed(mPowerLongPress, ViewConfiguration.getGlobalActionKeyTimeout()/*500ms*/);  
    5.     }  
    6. }  
    7.   
    8. private boolean interceptPowerKeyUp(boolean canceled) {  
    9.     if (!mPowerKeyHandled) {  
    10.         mHandler.removeCallbacks(mPowerLongPress);  
    11.         return !canceled;  
    12.     }  
    13.     return false;  
    14. }  





  • 相关阅读:
    [Linux 流量管理] Cacti的插件安装和使用
    expdp impdp 数据库导入导出命令详解
    Dropping all user tables/sequences in Oracle
    Oracle RMAN 的 show,list,crosscheck,delete命令整理
    EXP00041错误,遇到字符集问题的解决方式
    ORA00312的解决方法
    如何禁止MSN传递文件
    如何解决Parallel query大于1的问题
    bzoj5028小Z的加油店(线段树+差分)
    [转]C# 互操作性入门系列(三):平台调用中的数据封送处理
  • 原文地址:https://www.cnblogs.com/james1207/p/3297161.html
Copyright © 2011-2022 走看看