1. 程式人生 > >第6章7節《MonkeyRunner原始碼剖析》Monkey原理分析-事件源-事件源概覽-注入按鍵事件例項

第6章7節《MonkeyRunner原始碼剖析》Monkey原理分析-事件源-事件源概覽-注入按鍵事件例項

在事件生成並放入到命令佇列後,Monkey類的runMonkeyCycles就會去呼叫相應事件源的getNextEvent來獲的事件來執行事件注入,那麼這一小節我們通過MonkeyKeyEvent這個事件的注入方法來看下事件注入過程是怎麼樣的。

往系統注入按鍵事件最終是通過呼叫InputManager提供的方法來實現的,在Android系統中,按鍵事件是由InputManager來收集並由WindowManagerService服務來分發給各個Activity處理的,這個系統服務。它是用於管理整個系統的輸入部分,包括鍵盤、滑鼠、觸控式螢幕等等。所以MonkeyKeyEvent往系統注入按鍵事件要做的事情就是要準備好InputManager注入事件的方法 injectInputEvent所需要的引數KeyEvent例項。而KeyEvent例項或者用於構建KeyEvent例項所需要用到的引數在MonkeyKeyEvent的成員變數中都有定義:

 27 public class MonkeyKeyEvent
 28   extends MonkeyEvent
 29 {
 30   private int mDeviceId;
 31   private long mEventTime;
 32   private long mDownTime;
 33   private int mAction;
 34   private int mKeyCode;
 35   private int mScanCode;
 36   private int mMetaState;
 37   private int mRepeatCount;
 38   private KeyEvent mKeyEvent;
程式碼6-7-1 MonkeyKeyEvent 成員變數

以下我們先簡要描述下各個成員變數的意義,其中大部分變數都是用於構建KeyEvent用的:

  • mDeviceId: 產生該事件的裝置ID
  • mEventTime:事件發生事件
  • mDownTime: 按鍵按下時間,用來判斷是點選還是長按
  • mAction: 按鍵動作,如ACTION_DOWN,ACTION_UP或ACTION_MULTIPLE
  • mKeyCode: 按鍵鍵碼
  • mScanCode: 按鍵硬體掃描碼
  • mMetatState: 指示哪個元鍵(如ALT這種控制類鍵)在按下狀態
  • mRepeatCount:代表按鍵鍵碼的重複次數
  • mKeyEvent: 系統按鍵事件。以上的變數在按鍵事件KeyEvent類中都有對應的變數

MonkeyKeyEvent支援多個建構函式,其中有兩個比較重要。呼叫者可以傳入除mKeyEvent外的所有其他變數進行初始化,也可以直接傳入一個KeyEvent例項進行初始化,因為剛才說過了KeyEvent裡面包含了所有其他變數。我們往下看下者兩個建構函式:

46   public MonkeyKeyEvent(long downTime, long eventTime, int action, int keyCode, int repeatCount, int metaState, int device, int scan    Code)
 47   {
 48     super(0);
 49     this.mDownTime = downTime;
 50     this.mEventTime = eventTime;
 51     this.mAction = action;
 52     this.mKeyCode = keyCode;
 53     this.mRepeatCount = repeatCount;
 54     this.mMetaState = metaState;
 55     this.mDeviceId = device;
 56     this.mScanCode = scanCode;
 57   }
 58 
 59   public MonkeyKeyEvent(KeyEvent e) {
 60     super(0);
 61     this.mKeyEvent = e;
 62   }
程式碼6-7-2 MonkeyKeyEvent建構函式

在準備好注入事件所需要的提供的資訊後,下一步就需要去看下MonkeyKeyEvent的注入事件這個方法是怎麼實現的了:

 99     @Override
100     public int injectEvent(IWindowManager iwm, IActivityManager iam, int verbose) {
101         if (verbose > 1) {
102             String note;
103             if (mAction == KeyEvent.ACTION_UP) {
104                 note = "ACTION_UP";
105             } else {
106                 note = "ACTION_DOWN";
107             }
108 
109             try {
110                 System.out.println(":Sending Key (" + note + "): "
111                         + mKeyCode + "    // "
112                         + MonkeySourceRandom.getKeyName(mKeyCode));
113             } catch (ArrayIndexOutOfBoundsException e) {
114                 System.out.println(":Sending Key (" + note + "): "
115                         + mKeyCode + "    // Unknown key event");
116             }
117         }
118 
119         KeyEvent keyEvent = mKeyEvent;
120         if (keyEvent == null) {
121             long eventTime = mEventTime;
122             if (eventTime <= 0) {
123                 eventTime = SystemClock.uptimeMillis();
124             }
125             long downTime = mDownTime;
126             if (downTime <= 0) {
127                 downTime = eventTime;
128             }
129             keyEvent = new KeyEvent(downTime, eventTime, mAction, mKeyCode,
130                     mRepeatCount, mMetaState, mDeviceId, mScanCode,
131                     KeyEvent.FLAG_FROM_SYSTEM, InputDevice.SOURCE_KEYBOARD);
132         }
133         if (!InputManager.getInstance().injectInputEvent(keyEvent,
134             InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_RESULT)) {
135             return MonkeyEvent.INJECT_FAIL;
136         }
137         return MonkeyEvent.INJECT_SUCCESS;
138     }
139 }
程式碼6-7-3 MonkeyKeyEvent - injectEvent
  • 103-107行: 確定這個按鍵事件是按下事件還起彈起事件
  • 119-132行: 如果MonkeyKeyEvent是用KeyEvent構造的,那麼直接使用這個KeyEvent,如果不是用KeyEvent而是用另外一個建構函式構造的,那麼用該建構函式傳進來的所有引數來構造一個KeyEvent來使用
  • 133-134行: 通過呼叫InputManager來把按鍵keyEvent注入到系統窗口裡面來實現注入一個按鍵事件的操作。

注:更多文章請關注公眾號:techgogogo或個人部落格http://techgogogo.com。當然,也非常歡迎您直接微信(zhubaitian1)勾搭。本文由天地會珠海分舵原創。轉載請自覺,是否投訴維權看心情。