Android中Home键的监听和拦截

scott_tiger 8年前
   <p>首先大家应该先了解一种情况,就是Android在应用中是无法拦截Home键的,今天我们带大家看一下Home键的三种情况。</p>    <h2>1、在应用中按下Home键的逻辑处理</h2>    <p>当我们在应用中按下Home键时界面会启动到桌面,我们在frameworks\base\policy\src\com\android\internal\policy\impl\PhoneWindowManager.java类中可以看到其实现原理,其不外乎就是调用了以下代码。</p>    <pre>  <code class="language-java">Intent mHomeIntent;      mHomeIntent = new Intent(Intent.ACTION_MAIN, null);      mHomeIntent.addCategory(Intent.CATEGORY_HOME);      mHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);        startActivity(mHomeIntent);</code></pre>    <p>创建一个启动到桌面的Intent。</p>    <h2>2、在应用中监听Home键</h2>    <p>在Android应用中如果想监听Home键可以使用广播机制,这个在源码中也有体现。</p>    <pre>  <code class="language-java">static public final String SYSTEM_DIALOG_REASON_KEY = "reason";      static public final String SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS = "globalactions";      static public final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps";      static public final String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey";      static public final String SYSTEM_DIALOG_REASON_ASSIST = "assist";        @Override      public void onReceive(Context arg0, Intent arg1) {          String action = arg1.getAction();          //按下Home键会发送ACTION_CLOSE_SYSTEM_DIALOGS的广播          if (action.equals(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)) {                String reason = arg1.getStringExtra(SYSTEM_DIALOG_REASON_KEY);              if (reason != null) {                  if (reason.equals(SYSTEM_DIALOG_REASON_HOME_KEY)) {                      // 短按home键                      Toast.makeText(arg0, "短按Home键", Toast.LENGTH_SHORT).show();                  } else if (reason.equals(SYSTEM_DIALOG_REASON_RECENT_APPS)) {                      // RECENT_APPS键                      Toast.makeText(arg0, "RECENT_APPS", Toast.LENGTH_SHORT).show();                  }              }          }      }</code></pre>    <p>这样就可以监听Home的是否被按下。</p>    <h2>3、在Frameworks层拦截Home键</h2>    <p>在frameworks\base\policy\src\com\android\internal\policy\impl\PhoneWindowManager.java文件中我们首先看一下interceptKeyBeforeDispatching()方法。</p>    <pre>  <code class="language-java">public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags) {        //......      if (keyCode == KeyEvent.KEYCODE_HOME) {            //......          handleShortPressOnHome();      }  }    //进入handleShortPressOnHome  private void handleShortPressOnHome() {          // If there's a dream running then use home to escape the dream          // but don't actually go home.          if (mDreamManagerInternal != null && mDreamManagerInternal.isDreaming()) {              mDreamManagerInternal.stopDream(false /*immediate*/);              return;          }            // Go home!          launchHomeFromHotKey();      }</code></pre>    <p>进入launchHomeFromHotKey方法。</p>    <pre>  <code class="language-java">static public final String SYSTEM_DIALOG_REASON_KEY = "reason";      static public final String SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS = "globalactions";      static public final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps";      static public final String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey";      static public final String SYSTEM_DIALOG_REASON_ASSIST = "assist";    void launchHomeFromHotKey() {          if (isKeyguardShowingAndNotOccluded()) {              // don't launch home if keyguard showing          } else if (!mHideLockScreen && mKeyguardDelegate.isInputRestricted()) {              // when in keyguard restricted mode, must first verify unlock              // before launching home              mKeyguardDelegate.verifyUnlock(new OnKeyguardExitResult() {                  @Override                  public void onKeyguardExitResult(boolean success) {                      if (success) {                          try {                              ActivityManagerNative.getDefault().stopAppSwitches();                          } catch (RemoteException e) {                          }                          sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);                          startDockOrHome();                      }                  }              });          } else {              // no keyguard stuff to worry about, just launch home!              try {                  ActivityManagerNative.getDefault().stopAppSwitches();              } catch (RemoteException e) {              }              if (mRecentsVisible) {                  // Hide Recents and notify it to launch Home                  awakenDreams();                  sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);                  hideRecentApps(false, true);              } else {                  // Otherwise, just launch Home                  sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);                  //启动Launcher界面                  startDockOrHome();              }          }      }</code></pre>    <p>以上方法可处理Home键的拦截操作,接下来我们进入startDockOrHome方法。</p>    <pre>  <code class="language-java">void startDockOrHome() {            if (OptConfig.LC_RAM_SUPPORT) {              try {                  ActivityManagerNative.getDefault().startHomePre();              } catch (RemoteException re) {                }          }            awakenDreams();            Intent dock = createHomeDockIntent();          if (dock != null) {              try {                  startActivityAsUser(dock, UserHandle.CURRENT);                  return;              } catch (ActivityNotFoundException e) {              }          }            //intent的相关设置          mHomeIntent =  new Intent(Intent.ACTION_MAIN, null);          mHomeIntent.addCategory(Intent.CATEGORY_HOME);          mHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK                  | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);            startActivityAsUser(mHomeIntent, UserHandle.CURRENT);      }</code></pre>    <p>好啦,这里就对Home键进行简单的监听和拦截。</p>    <p> </p>    <p>来自:http://blog.csdn.net/dongxianfei/article/details/55049991</p>    <p> </p>