語法 | input keyevent [--longpress] <key code number or name> |
---|---|
說明 | 與 MonkeyDevice.press(<key name>, MonkeyDevice.DOWN_AND_UP) 的行為類似。 |
Key name,可查閱 KeyEvent 裡以 KEYCODE_ 為開頭的名稱。 | |
Key code number,可查閱 KeyEvent 裡以 KEYCODE_ 為開頭的名稱的 constant value。 | |
--longpress 此參數目前無法達成長壓按鍵的效果。 |
咱們直接看例子:
# 匯入所需模組
import os
from com.android.monkeyrunner import MonkeyDevice, MonkeyImage, MonkeyRunner
# 連接 Android 裝置
device = MonkeyRunner.waitForConnection()
# A: 連續送出 5 次 MonkeyDevice.shell()
for i in range(5):
device.shell('input keyevent KEYCODE_VOLUME_UP')
# B: 連續送出 5 次 adb shell
for i in range(5):
os.system('adb shell input keyevent KEYCODE_VOLUME_UP')
# C: 送出 1 次 MonkeyDevice.shell()
param = ''
for i in range(5):
param += 'input keyevent KEYCODE_VOLUME_UP; '
device.shell(param)
# D: 送出 1 次 adb shell
param = ''
for i in range(5):
param += 'input keyevent KEYCODE_VOLUME_UP; '
os.system('adb shell ' + param)
以上 A、B、C 和 D 四種都是合法的 shell 命令(雖然按鍵被按下後到要按下一個按鍵之間停頓的時間會不同,但稍微想一下應該就能明白為什麼會有這現象),所以大部分看官應該會認為這四種都能正常執行。也或許有些看官會想起 05-按下那個按鍵!猴子!(MonkeyDevice.press) 裡遇到的「連續送出 MonkeyDevice.press() 時會丟出 exception」的問題,所以認為會有失敗的測項,咱們直接跑看看吧:
ASUS Z00LD (Android 6.0.1) | Nexus 5 (Android 8.1.0) | |
---|---|---|
A | Pass | Pass |
B | Pass | Pass |
C | Fail | Pass |
D | Pass | Pass |
非常奇妙!Nexus 5 (Android 8.1.0) 在這四個項目都可正常運作,但 ASUS Z00LD (Android 6.0.1) 卻會死在 C 測項。想當然耳來看, C 與 D 是一樣的,但結果卻與手機的版本似乎有點關係?!
若看官遇到的 exception 也和本喵一樣是 com.android.ddmlib.ShellCommandUnresponsiveException 的話,那原因多半是因為執行逾時了!還記得 13-最終兵器MonkeyDevice.shell 裡所說的 MonkeyDevice.shell() 可以接受一個 timeout 的參數嗎?預設上是 5 秒內要完成指令,可是因為要求執行的命令太多了,有些裝置無法在限時內完成,所以便丟出 exception。解決方法很簡單,只要指定更長的 timeout 給 MonkeyDevice.shell() 就好了:
# C: 送出 1 次 MonkeyDevice.shell()
param = ''
for i in range(5):
param += 'input keyevent KEYCODE_VOLUME_UP; '
# 將 timeout 設為 30 秒
device.shell(param, 30 * 1000)
如此一來,ASUS Z00LD (Android 6.0.1) 便可完成測項 C 了!只是每次都要對不同裝置和指令微調 timeout 的設定並不是一件輕鬆的事情,若非必要,本喵還是覺得直接用 Python 的 os.system() 或 subprocess.Popen() 來呼叫 shell 比較方便。
那麼來看看為什麼 --longpress 這個參數沒作用的原因吧!咱們當然是由原始碼 Input.java 來下手喽:
private void sendKeyEvent(int inputSource, int keyCode, boolean longpress) {
long now = SystemClock.uptimeMillis();
injectKeyEvent(new KeyEvent(
now,
now,
KeyEvent.ACTION_DOWN,
keyCode,
0,
0,
KeyCharacterMap.VIRTUAL_KEYBOARD,
0,
0,
inputSource
));
if (longpress) {
injectKeyEvent(new KeyEvent(
now,
now,
KeyEvent.ACTION_DOWN,
keyCode,
1,
0,
KeyCharacterMap.VIRTUAL_KEYBOARD,
0,
KeyEvent.FLAG_LONG_PRESS,
inputSource
));
}
injectKeyEvent(new KeyEvent(
now,
now,
KeyEvent.ACTION_UP,
keyCode,
0,
0,
KeyCharacterMap.VIRTUAL_KEYBOARD,
0,
0,
inputSource
));
}
看官們理解原因所在了嗎?雖然第 16 行會送出代表 long press 的 KeyEvent,但 KeyEvent.ACTION_DOWN 和 KeyEvent.ACTION_UP 兩個事件之間的間隔實在太短了,根本無法觸發裝置執行對應的動作 O___Oa
沒有留言:
張貼留言