第6章7節《MonkeyRunner原始碼剖析》Monkey原理分析-事件源-事件源概覽-注入按鍵事件例項
在事件生成並放入到命令佇列後,Monkey類的runMonkeyCycles就會去呼叫相應事件源的getNextEvent來獲的事件來執行事件注入,那麼這一小節我們通過MonkeyKeyEvent這個事件的注入方法來看下事件注入過程是怎麼樣的。
往系統注入按鍵事件最終是通過呼叫InputManager提供的方法來實現的,在Android系統中,按鍵事件是由InputManager來收集並由WindowManagerService服務來分發給各個Activity處理的,這個系統服務。它是用於管理整個系統的輸入部分,包括鍵盤、滑鼠、觸控式螢幕等等。所以MonkeyKeyEvent往系統注入按鍵事件要做的事情就是要準備好InputManager注入事件的方法 injectInputEvent所需要的引數KeyEvent例項。而KeyEvent例項或者用於構建KeyEvent例項所需要用到的引數在MonkeyKeyEvent的成員變數中都有定義:
程式碼6-7-1 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;
以下我們先簡要描述下各個成員變數的意義,其中大部分變數都是用於構建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)勾搭。本文由天地會珠海分舵原創。轉載請自覺,是否投訴維權看心情。