android虛擬事件
A. 如何實現給android系統發送一些鍵盤事件和屏幕事件
可能通過命令行 input 命令向android發送事件。
Android中,模擬事件全部是通過input命令來實現的。
input命令的使用:
usage: input ...
input text <string>
input keyevent <key code number or name>
input tap <x> <y>
input swipe <x1> <y1> <x2> <y2>
1. keyevent指的是android對應的keycode,比如home鍵的keycode=3,back鍵的keycode=4.
具體請查閱 <android keycode詳>
然後使用的話比較簡單,比如想模擬home按鍵:
adb shell input keyevent 3根據具體keycode編輯即可。
2. 關於tap的話,他模擬的是touch屏幕的事件,只需給出x、y坐標即可。
此x、y坐標對應的是真實的屏幕解析度,所以要根據具體手機具體看,比如想點擊屏幕(x, y) = (250, 250)位置:
adb shell input tap 250 250
3. 關於swipe同tap是一樣的,只是他是模擬滑動的事件,給出起點和終點的坐標即可。例如從屏幕(250, 250), 到屏幕(300, 300)即 adb shell input swipe 250 250 300 300 。
B. Android 模擬滑動事件
handleTouchEvent(MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_DOWN, 447, 245, 0),true);
handleTouchEvent(MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_MOVE, 245, 420, 0),true);
handleTouchEvent(MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_MOVE, 245, 406, 0),true);
handleTouchEvent(MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_MOVE, 245, 384, 0),true);
handleTouchEvent(MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_MOVE, 245, 328, 0),true
C. Android View 事件分發機制
Android 事件機制包含系統啟動流程、輸入管理(InputManager)、系統服務和 UI 的通信(WindowManagerService + ViewRootImpl + Window)、事件分發等一系列的環節。
Android 系統中將輸入事件定義為 InputEvent,根據輸入事件的類型又分為了 KeyEvent(鍵盤事件) 和 MotionEvent(屏幕觸摸事件)。這些事件統一由系統輸入管理器 InputManager 進行分發。
在系統啟動的時候,SystemServer 會啟動 WindowManagerService,WMS 在啟動的時候通過 InputManager 來負責監控鍵盤消息。
InputManager 負責從硬體接收輸入事件,並將事件通過 ViewRootImpl 分發給當前激活的窗口處理,進而分發給 View。
Window 和 InputManagerService 之間通過 InputChannel 來通信,底層通過 socket 進行通信。
Android Touch 事件的基礎知識:
KeyEvent 對應了鍵盤的輸入事件;MotionEvent 就是手勢事件,滑鼠、筆、手指、軌跡球等相關輸入設備的事件都屬於 MotionEvent。
InputEvent 統一由 InputManager 進行分發,負責與硬體通信並接收輸入事件。
system_server 進程啟動時會創建 InputManagerService 服務。
system_server 進程啟動時同時會啟動 WMS,WMS 在啟動的時候就會通過 IMS 啟動 InputManager 來監控鍵盤消息。
App 端與服務端建立了雙向通信之後,InputManager 就能夠將產生的輸入事件從底層硬體分發過來,Android 提供了 InputEventReceiver 類,以接收分發這些消息:
Window 和 IMS 之間通過 InputChannel 通信。InputChannel 是一個 pipe,底層通過 socket 進行通信。在 ViewRootImpl.setView() 過程中注冊 InputChannel。
Android 事件傳遞機制是 先分發再處理 ,先由外部的 View 接收,然後依次傳遞給其內層的 View,再從最內層 View 反向依次向外層傳遞。
三個方法的關系如下:
分發事件:
應用了樹的 深度優先搜索演算法 (Depth-First-Search,簡稱 DFS 演算法),每個 ViewGroup 都持有一個 mFirstTouchTarget, 當接收到 ACTION_DOWN 時,通過遞歸遍歷找到 View 樹中真正對事件進行消費的 Child,並保存在 mFirstTouchTarget 屬性中,依此類推組成一個完整的分發鏈。在這之後,當接收到同一事件序列的其它事件如 ACTION_MOVE、ACTION_UP 時,則會跳過遞歸流程,將事件直接分發給下一級的 Child。
ViewGroup 分發事件的主要的任務是找一個 Target,並且用這個 Target 處理事件,主要邏輯如下 :
為什麼倒序查找 TouchTarget?
如果按添加順序遍歷,當 View 重疊時(FrameLayout),先添加的 View 總是能消費事件,而後添加的 View 不可能獲取到事件。
攔截事件:
[1] Android 事件分發機制的設計與實現
[2] Android 事件攔截機制的設計與實現