2018年10月28日 星期日

14-繞遠路雖愚蠢但有用 (screencap)

screencap 是 Android shell 提供來擷取目前螢幕畫面的工具程式,本喵只使用過以下語法:
語法 說明
screencap -p [FILENAME] [FILENAME],截圖儲存在 Android 裝置上的檔案路徑,格式為 png。

什麼時候會需要以 screencap 來取代 MonkeyDevice.takeSnapshot() 呢?本喵遇過的情境如下:
  • 無法避免 MonkeyDevice.takeSnapshot() 的 exception
    本喵曾在測試手機時經常性的遇到 MonkeyDevice.takeSnapshot() 發出的 exception,即使藉由 try ... except 語法來重新呼叫 MonkeyDevice.takeSnapshot() 也沒多大改善。最後本喵只能想到利用 screencap 來截圖,即便這是迂迴的作法。
  • MonkeyDevice.takeSnapshot() 無法使用
    這情況實在是蠻特別的,本喵從沒想過會發生這種事,但它卻實實在在出現在 Nexus 5 (Android 8.1.0) 上,而且還是只有與某些電腦搭配時才會讓 MonkeyDevice.takeSnapshot() 無法運作。因本喵不知為何會發生這問題,所以也無從排解,只好以 screencap 替代了。

那要怎麼在 Python 內使用 screencap 呢?鑒於 MonkeyDevice.shell() 也可能失效的因素,加上只連接一台 Android 裝置,所以本喵會類似如下來使用 screencap:
# 匯入所需模組
import os

from com.android.monkeyrunner import MonkeyDevice, MonkeyImage, MonkeyRunner

# 連接 Android 裝置
device = MonkeyRunner.waitForConnection()

# 擷取目前畫面並儲存到 Android 裝置
pic_name = 'tmp_snapshot.png'
remote_path = '/sdcard/' + pic_name
os.system('adb shell screencap -p "%s"' % remote_path)

# 將擷取的畫面由 Android 裝置複製到電腦端
local_path = os.path.join(os.path.dirname(__file__), pic_name)
os.system('adb pull "%s" "%s"' % (remote_path, local_path))

# 將圖檔載入
img = MonkeyRunner.loadImageFromFile(local_path)
非常囉嗦又費時吧!但卻是有用的!至少不會有無法取得畫面和出現 exception 的困惱,如果沒其他意外的話。___。

其實,在第 16 行是有可能出錯的,這錯誤應該算是 adb pull 這個工具程式的 bug,即當看官的腳本是放在根目錄下,比如若以上程式內容是儲存在 E:\test_monkeyrunner.py 這個腳本內的話,當運行時,會出現如下錯誤:
adb: error: cannot create file/directory 'e:\tmp_snapshot.png': No such file or directory

原因很簡單,就是若 adb pull 的 local 路徑的父路徑就是根目錄,那 adb pull 必須如下使用:
E:\> adb pull /sdcard/tmp_snapshot.png  e:\.\tmp_snapshot.png
這確實很奇怪~但沒辦法~既然如此,咱們只能想法子繞開。至於如何做,就請看官們各發奇想喽~~喵~

沒有留言:

張貼留言