Android上如何讓應用截獲系統按鍵

jopen 11年前發布 | 60K 次閱讀 Android 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

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!