android4.0拦截HOME键
由于android4.0和2.3里面的按键机制有所不同,今天做了这样一个demo可以监听到HOME在android4.0上面,好了废话不说了直接先上原理在贴代码。
frameworks\base\policy\src\com\android\internal\policy\impl\PhoneWindowManager.java这个类是android4.0里面的按键管理类,上层UI监听的所有按键都在这个里面进行分发,所以要想监听到HOME键就要在这个类里面做文章,怎么做很简单找到HOME按键在该类中的处理过程就好解决了,可以在分发HOME键的时候发送一个广播然后在应用程序里面接收该广播就可以了,这个就是原理接下来直接贴代码。
/** [email protected]} */ @Override public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags) { final boolean keyguardOn = keyguardOn(); final int keyCode = event.getKeyCode(); final int repeatCount = event.getRepeatCount(); final int metaState = event.getMetaState(); final int flags = event.getFlags(); final boolean down = event.getAction() == KeyEvent.ACTION_DOWN; final boolean canceled = event.isCanceled(); if (false) { Log.d(TAG, "interceptKeyTi keyCode=" + keyCode + " down=" + down + " repeatCount=" + repeatCount + " keyguardOn=" + keyguardOn + " mHomePressed=" + mHomePressed); } // If we think we might have a volume down & power key chord on the way // but we're not sure, then tell the dispatcher to wait a little while and // try again later before dispatching. if ((flags & KeyEvent.FLAG_FALLBACK) == 0) { if (mVolumeDownKeyTriggered && !mPowerKeyTriggered) { final long now = SystemClock.uptimeMillis(); final long timeoutTime = mVolumeDownKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS; if (now < timeoutTime) { return timeoutTime - now; } } if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN && mVolumeDownKeyConsumedByScreenshotChord) { if (!down) { mVolumeDownKeyConsumedByScreenshotChord = false; } return -1; } } // First we always handle the home key here, so applications // can never break it, although if keyguard is on, we do let // it handle it, because that gives us the correct 5 second // timeout. if (keyCode == KeyEvent.KEYCODE_HOME) { // If we have released the home key, and didn't do anything else // while it was pressed, then it is time to go home! Intent myHomeKey = new Intent("HomeKeyDispatch"); myHomeKey.putExtra("HomeKey", "HomeKeyIntent"); mContext.sendBroadcast(myHomeKey); if (mHomePressed && !down) { mHomePressed = false; if (!canceled) { // If an incoming call is ringing, HOME is totally disabled. // (The user is already on the InCallScreen at this point, // and his ONLY options are to answer or reject the call.) boolean incomingRinging = false; try { ITelephony telephonyService = getTelephonyService(); if (telephonyService != null) { incomingRinging = telephonyService.isRinging(); } } catch (RemoteException ex) { Log.w(TAG, "RemoteException from getPhoneInterface()", ex); } if (incomingRinging) { Log.i(TAG, "Ignoring HOME; there's a ringing incoming call."); } else { launchHomeFromHotKey(); } } else { Log.i(TAG, "Ignoring HOME; event canceled."); } return -1; } // If a system window has focus, then it doesn't make sense // right now to interact with applications. WindowManager.LayoutParams attrs = win != null ? win.getAttrs() : null; if (attrs != null) { final int type = attrs.type; if (type == WindowManager.LayoutParams.TYPE_KEYGUARD || type == WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG) { // the "app" is keyguard, so give it the key return 0; } final int typeCount = WINDOW_TYPES_WHERE_HOME_DOESNT_WORK.length; for (int i=0; i<typeCount; i++) { if (type == WINDOW_TYPES_WHERE_HOME_DOESNT_WORK[i]) { // don't do anything, but also don't pass it to the app return -1; } } } if (down) { if (repeatCount == 0) { mHomePressed = true; } else if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0) { if (!keyguardOn) { handleLongPressOnHome(); } } } return -1; } else if (keyCode == KeyEvent.KEYCODE_MENU) { // Hijack modified menu keys for debugging features final int chordBug = KeyEvent.META_SHIFT_ON; if (down && repeatCount == 0) { if (mEnableShiftMenuBugReports && (metaState & chordBug) == chordBug) { Intent intent = new Intent(Intent.ACTION_BUG_REPORT); mContext.sendOrderedBroadcast(intent, null); return -1; } else if (SHOW_PROCESSES_ON_ALT_MENU && (metaState & KeyEvent.META_ALT_ON) == KeyEvent.META_ALT_ON) { Intent service = new Intent(); service.setClassName(mContext, "com.android.server.LoadAverageService"); ContentResolver res = mContext.getContentResolver(); boolean shown = Settings.System.getInt( res, Settings.System.SHOW_PROCESSES, 0) != 0; if (!shown) { mContext.startService(service); } else { mContext.stopService(service); } Settings.System.putInt( res, Settings.System.SHOW_PROCESSES, shown ? 0 : 1); return -1; } } } else if (keyCode == KeyEvent.KEYCODE_SEARCH) { if (down) { if (repeatCount == 0) { mShortcutKeyPressed = keyCode; mConsumeShortcutKeyUp = false; } } else if (keyCode == mShortcutKeyPressed) { mShortcutKeyPressed = -1; if (mConsumeShortcutKeyUp) { mConsumeShortcutKeyUp = false; return -1; } } return 0; } else if (keyCode == KeyEvent.KEYCODE_APP_SWITCH) { if (down && repeatCount == 0) { showOrHideRecentAppsDialog(RECENT_APPS_BEHAVIOR_SHOW_OR_DISMISS); } return -1; } // Shortcuts are invoked through Search+key, so intercept those here // Any printing key that is chorded with Search should be consumed // even if no shortcut was invoked. This prevents text from being // inadvertently inserted when using a keyboard that has built-in macro // shortcut keys (that emit Search+x) and some of them are not registered. if (mShortcutKeyPressed != -1) { final KeyCharacterMap kcm = event.getKeyCharacterMap(); if (kcm.isPrintingKey(keyCode)) { mConsumeShortcutKeyUp = true; if (down && repeatCount == 0 && !keyguardOn) { Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode, metaState); if (shortcutIntent != null) { shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); try { mContext.startActivity(shortcutIntent); } catch (ActivityNotFoundException ex) { Slog.w(TAG, "Dropping shortcut key combination because " + "the activity to which it is registered was not found: " + KeyEvent.keyCodeToString(mShortcutKeyPressed) + "+" + KeyEvent.keyCodeToString(keyCode), ex); } } else { Slog.i(TAG, "Dropping unregistered shortcut key combination: " + KeyEvent.keyCodeToString(mShortcutKeyPressed) + "+" + KeyEvent.keyCodeToString(keyCode)); } } return -1; } }
粗体部分就是处理HOME键的地方我加了一个广播,在应用程序里面按下面的方式处理就能拦截到HOME键了
BroadcastReceiver myBroadcastReceivernew= new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { // TODO Auto-generated method stub String homeKey = intent.getExtras().get("HomeKey").toString(); Log.i(tag, homeKey); } }; IntentFilter intentFilter = new IntentFilter( "HomeKeyDispatch" ); registerReceiver( myBroadcastReceivernew , intentFilter);这样就可以拦截到HOME键了,希望大家相互讨论!