Android 模擬螢幕點選和物理按鍵方式
在Android 中,有些特定的功能或者在除錯的時候需要模擬螢幕點選功能和物理按鍵等。
在實現上有2種方式:
首先是模擬螢幕點選的實現方式有兩種:
模擬螢幕點選
- 本程序內實現,就是隻有在自己的app上面實現。
- 跨程序實現,就是模擬點選手機螢幕的某個座標。
不跨程序實現方式:
假如我們需要模擬點選某個按鈕,這時候可以使用MotionEvent來實現,實現程式碼如下:
private void simulateClick(View view, float x, float y) {
long downTime = SystemClock.uptimeMillis();
final MotionEvent downEvent = MotionEvent.obtain(downTime, downTime,MotionEvent.ACTION_DOWN, x, y, 0);
downTime += 1000;
final MotionEvent upEvent = MotionEvent.obtain(downTime, downTime,MotionEvent.ACTION_UP, x, y, 0);
view.onTouchEvent(downEvent);
view.onTouchEvent(upEvent);
downEvent.recycle();
upEvent.recycle();
}
這實現原理就是模擬兩個MotionEvent (按下和提起) 然後用一個View 來處理這個Event 。 這樣就實現了模擬點選的操作,但是此種方式限制太大。本人覺得並沒有什麼用。
跨程序方式
跨程序方式其實就是整個手機系統中點選螢幕,並不侷限於在某一個app內。
這種情況只能適用於已經ROOT的手機,通過執行shell命令來執行模擬操作。
- getevent 命令 & sendevent 命令
工具的原始碼位於Android SDK的system/core/toolbox下(sendevent.c getevent.c)。
首先我這裡模擬用adb命令模擬一次操作,Window 系統下進入cmd命令列:
執行 :
adb shell getevent
輸出內容為:
add device 1: /dev/input/event4
name: ""
add device 2: /dev/input/event0
name: "Ft5x_dev"
add device 3: /dev/input/event5
name: "tegra-max98095 Headphone Jack"
add device 4: /dev/input/event6
name: "gpio-keys"
add device 5: /dev/input/event7
name: "Accelerometer"
could not get driver version for /dev/input/js0, Invalid argument
add device 6: /dev/input/event2
name: "compass"
add device 7: /dev/input/event3
name: "gyro"
add device 8: /dev/input/event1
name: "taos"
上面輸出資訊為裝置名稱和裝置的屬性,如果命令新增 -p 引數的話,就會顯示詳細資訊。
這時候我們如果觸控手機螢幕或者按了物理按鍵的時候,命令視窗就會打印出資訊:
如下:
/dev/input/event0: 0001 014a 00000001
/dev/input/event0: 0003 0000 000000f6
/dev/input/event0: 0003 0001 000002ed
/dev/input/event0: 0003 0035 000000f6
/dev/input/event0: 0003 0036 000002ed
/dev/input/event0: 0003 0032 00000001
/dev/input/event0: 0003 0039 00000000
/dev/input/event0: 0003 003a 00000043
/dev/input/event0: 0000 0002 00000000
這寫命令就是我們的操作的命令,輸出格式為 : device type code value
下面一一講解上面引數的意義:
- dev/input/event0指的是處理觸控和按鍵的輸入裝置。
- 0003 指的是事件型別,EV_SYN [0000] (同步事件),EV_KEY [0001] (按鍵事件),EV_ABS [0003] (絕對值事件)
- code 指的是0003代表的事件中支援的編碼。具體代表就我這裡就不寫出來。
- value 指的是值。
上面的getevent 命令的作用是檢視輸入裝置和檢視事件。
下面說說sendevent的功能。
用法為:adb shell sendevent device type code value
看到這裡,其實我們已經能實現功能了,比如,我要模擬點選一下home 鍵,首先我用getevent命令的到點選這個HOME鍵的事件,我在用sendevent命令在傳送一次同樣的事件過去就實現了模擬再次點選HOMT鍵了。
下面說另一中方式:
模擬點選的功能通常都是使用 /dev/input/event0 這個輸入裝置
假如我需要模擬一次點選BACK鍵:
back鍵的型別為 0001(按鍵事件)
根據getevent - p 輸出支援的資訊可知BACK的編碼為 0x9e 轉換為十進位制後即158(注意:sendevent 使用的進位制是十進位制)
那我們輸入如下命令即可模擬一次BACK鍵的按下和彈起:
adb shell sendevent /dev/input/event0 1 158 1
adb shell sendevent /dev/input/event0 1 158 0
input keyevent 命令
這個命令也可以模擬按鍵操作,使用格式為:input keyevent code
幾個常用的code 為:
input keyevent 3 // Home
input keyevent 4 // Back
input keyevent 19 //Up
input keyevent 20 //Down
input keyevent 21 //Left
input keyevent 22 //Right
input keyevent 23 //Select/Ok
input keyevent 24 //Volume+
input keyevent 25 // Volume-
input keyevent 82 // Menu 選單
input text 命令
這個命令是用來向輸入框輸入內容的。後面引數為 “字串”
input tap 命令
這個命令為模擬單擊事件 後面引數為: x y
比如在 30,30 單擊一下 : input tap 30 30
input swipe 命令
此命令為滑動事件。
比如我要從 30 10 滑動到 30 100 : input swipe 30 10 30 100
最後說明一下如何用程式碼實現:
/**
* 執行shell命令
*
* @param cmd
*/
private void execShellCmd(String cmd) {
try {
// 申請獲取root許可權,這一步很重要,不然會沒有作用
Process process = Runtime.getRuntime().exec("su");
// 獲取輸出流
OutputStream outputStream = process.getOutputStream();
DataOutputStream dataOutputStream = new DataOutputStream(
outputStream);
dataOutputStream.writeBytes(cmd);
dataOutputStream.flush();
dataOutputStream.close();
outputStream.close();
} catch (Throwable t) {
t.printStackTrace();
}
}