Android上如何讓應用截獲系統按鍵
本文章主要講述Android智能機上,應用捕獲按鍵的處理。遙控器上按鍵分為兩種,普通按鍵和熱鍵。普通按鍵就是我們常用的數字鍵,上下左右功能鍵,設置,返回,確認等按鍵。而在android上,對于遙控器的映射中,規定某些按鍵應用是無法攔截到的,我們稱此為熱鍵,如靜音鍵,電源鍵,HOME鍵,直播鍵等等。
1. 應用攔截普通按鍵的處理:
// 攔截系統熱鍵 @Override public boolean dispatchKeyEvent(KeyEvent event) { int key = event.getKeyCode(); Log.i(TAG, "[test] dispatchKeyEvent event = " + event); if (key == KeyEvent.KEYCODE_VOLUME_DOWN || key == KeyEvent.KEYCODE_VOLUME_UP) { Log.i(TAG, "[test] catch event!! return true! "); return true; } return super.dispatchKeyEvent(event); }
在按鍵的處理過程中,若應用重寫了dispatchKeyEvent,并且對響應的按鍵進行了處理完后,直接return true,則系統將不再處理此按鍵的響應。如果不寫return true,super.dispatchKeyEvent(event)將會將按鍵再次交給系統進行處理。
----------------------------------------------------------------------------------
2.應用攔截熱鍵的處理:
[1]在Activity中重寫onAttachedToWindow方法,設置一個0x80000000的flags下去。//僅一個標志而已
@Override public void onAttachedToWindow() { System.out.println("onAttachedToWindow ............"); this.getWindow().addFlags(0x80000000);// super.onAttachedToWindow(); }
[2]修改phoneWindownManager.java.在相應按鍵的事件派發前進行如下處理:【以home鍵為例】
在進行事件處理前,先獲取當前WindowManager.LayoutParams,通過flags可以判斷應用是否可以處理該按鍵消息,若可以,直接return 0,不再進行按鍵處理,交留給應用去處理。如果flags判斷應用無法獲取該按鍵消息,將還會進行系統原有的按鍵處理流程。
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! 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 if(mHoldHomePressed == true){ mHoldHomePressed = false; }else{ mHoldHomePressed = false; 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; } } /** * 特殊處理,讓應用程序能攔截HOME按鍵 */ final int attrFlags = attrs.flags; if((attrFlags & 0x80000000) != 0) { return 0; } } if (down) { if (repeatCount == 0) { mHomePressed = true; } else if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0) { if (!keyguardOn) { //handleLongPressOnHome(); mHoldHomePressed = true; Intent intentShowRecent = new Intent("hi_action_show_recent"); mContext.sendBroadcast(intentShowRecent); } } } return -1; }
[3]熱鍵在應用中的處理:
參照普通按鍵的處理流程。重寫dispatchKeyEvent。
來自:http://my.oschina.net/hiliusl/blog/137541