首先大家应该先了解一种情况,就是 Android 在应用中是无法拦截 Home 键的,今天我们带大家看一下 Home 键的三种情况。
当我们在应用中按下 Home 键时界面会启动到桌面,我们在 frameworks\base\policy\src\com\android\internal\policy\impl\PhoneWindowManager.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);
创建一个启动到桌面的 Intent。
在 Android 应用中如果想监听 Home 键可以使用广播机制,这个在源码中也有体现。
- 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();
- }
- }
- }
- }
这样就可以监听 Home 的是否被按下。
在 frameworks\base\policy\src\com\android\internal\policy\impl\PhoneWindowManager.java 文件中我们首先看一下 interceptKeyBeforeDispatching() 方法。
- 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();
- }
进入 launchHomeFromHotKey 方法。
- 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();
- }
- }
- }
以上方法可处理 Home 键的拦截操作,接下来我们进入 startDockOrHome 方法。
- 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);
- }
好啦,这里就对 Home 键进行简单的监听和拦截。
来源: