2018年10月3日 星期三

05-按下那個按鍵!猴子!(MonkeyDevice.press)

終於,咱們可以開始學習對 Android 裝置下達第一道命令了~按下一個實體按鍵: MonkeyDevice.press (string name, integer type)

所謂的實體按鍵就是諸如電源鍵或聲音鍵這種可以實際觸摸到的硬體,而不是由電腦繪製的 icon 類型的按鈕。以前的 Android 手機上還有 Home key 這種按鍵,但現在也常是以 icon 的形式被表現於手機上了。但即使如此,通常還是可以利用 MonkeyDevice.press() 送出一個模擬 Home key 被按下的訊息給沒有 Home key 的手機,讓其表現按下 Home key 時應有的行為。

參數:
name 按鍵的名稱。可查閱 KeyEvent 裡以 KEYCODE_ 為開頭的名稱,注意是其名稱,而非其 constant value
type 按鍵的動作。可有 DOWN、UP 與 DOWN_AND_UP 三種,但其實目前 DOWN 的表現與 DOWN_AND_UP 相同,所以 UP 等於沒作用。

咱們舉幾個實例來看看 MonkeyDevice.press() 在使用上需要注意些什麼:
  • 按下音量增大鍵 1 次
    咱們可以撰寫腳本如下:
    # 匯入所需模組
    from com.android.monkeyrunner import MonkeyDevice, MonkeyImage, MonkeyRunner
    
    # 連接 Android 裝置
    device = MonkeyRunner.waitForConnection()
    
    # 按 1 次音量增大鍵
    device.press('KEYCODE_VOLUME_UP', MonkeyDevice.DOWN_AND_UP)
    
    是的!和 02-Monkeyrunner的程式架構與執行 章節的例子完全一樣,依此章節所載方法執行後,看官們會觀察到手機的表現確實和音量增大鍵被按了 1 次後的行為一致。
     
  • 連續按 2 次音量增大鍵
    聰明的看官們一定會想:「按 1 次時是呼叫 MonkeyDevice.press() 1 次,那連續按 2 次不就只要寫 2 次就好了唄!」於是撰寫了腳本如下:
    # 匯入所需模組
    from com.android.monkeyrunner import MonkeyDevice, MonkeyImage, MonkeyRunner
    
    # 連接 Android 裝置
    device = MonkeyRunner.waitForConnection()
    
    # 按第 1 次音量增大鍵
    device.press('KEYCODE_VOLUME_UP', MonkeyDevice.DOWN_AND_UP)
    
    # 按第 2 次音量增大鍵
    device.press('KEYCODE_VOLUME_UP', MonkeyDevice.DOWN_AND_UP)
    
    一切看起來都很完美!
    看官們興高采烈地執行了腳本,並深信自己的程式一定沒問題!但是,很遺憾地,程式設計之神是不會讓人如願的!看官們若幸運的話,會觀察到手機的表現只和被按了 1 次音量增大鍵的行為一樣;若不幸,腳本會死掉,並顯示一堆錯誤訊息,第一行的訊息可能是:
    180928 15:10:22.068:S [main] [com.android.chimpchat.adb.AdbChimpDevice] Error sending press event: KEYCODE_VOLUME_UP DOWN

    「咦!!這是什麼!?咱們的腳本沒錯阿!!為什麼會這樣!?」看官們發出陣陣地哀嚎聲~~
    04-寶寶乖~寶寶睡 所述,monkeyrunner 會因不明原因的 exception 而導致腳本死掉,所以咱們需做點小手段:
    # 匯入所需模組
    from com.android.monkeyrunner import MonkeyDevice, MonkeyImage, MonkeyRunner
    
    # 連接 Android 裝置
    device = MonkeyRunner.waitForConnection()
    
    # 按第 1 次音量增大鍵
    device.press('KEYCODE_VOLUME_UP', MonkeyDevice.DOWN_AND_UP)
    
    # 暫停腳本 0.5 秒
    MonkeyRunner.sleep(0.5)
    
    # 按第 2 次音量增大鍵
    device.press('KEYCODE_VOLUME_UP', MonkeyDevice.DOWN_AND_UP)
    
    看到了嗎?咱們在原本的 2 個 device.press() 之間插入了 1 個 MonkeyRunner.sleep(0.5),好讓它們的執行有段緩衝時間。咱們再執行一次修改過後的腳本,會觀察到手機的表現確實和按了 2 次音量增大鍵的行為一致。
     
  • 長壓按鍵
    MonkeyDevice.press() 有提供 DOWN 和 UP 這兩個動作,所以咱們一定會想只要像下面這樣寫,就一定能成功模擬長壓按鍵:
    # 匯入所需模組
    from com.android.monkeyrunner import MonkeyDevice, MonkeyImage, MonkeyRunner
    
    # 連接 Android 裝置
    device = MonkeyRunner.waitForConnection()
    
    # 壓下音量增大鍵
    device.press('KEYCODE_VOLUME_UP', MonkeyDevice.DOWN)
    
    # 暫停腳本 3 秒
    MonkeyRunner.sleep(3)
    
    # 放開音量增大鍵
    device.press('KEYCODE_VOLUME_UP', MonkeyDevice.UP)
    
    但非常遺憾!Android 大神又搧了我們一記耳光 Q ___ Q
    手機的表現和按了 1 次音量增大鍵一樣,也就是說,DOWN 和 DOWN_AND_UP 的作用都是對按鍵執行 1 次按下後放開﹒﹒﹒
    怎辦呢?難道咱們不能模擬長壓按鍵這一功能了嗎?不!雖然 MonkeyDevice.press() 無法做到,但俗話說:「山不轉路轉,路不轉人轉。」咱們依然可以利用 MonkeyDevice.shell() 直接發送底層指令來模擬,這部分就等講到 adb shell 時再說明喽~

沒有留言:

張貼留言