uiautomator2


uiautomator2   

該項目正在火熱的開發中
uiautomator2 是一個可以使用Python對Android設備進行UI自動化的庫。其底層基於Google uiautomator,Google提供的 uiautomator 庫可以獲取屏幕上任意一個APP的任意一個控件屬性,並對其進行任意操作,但有兩個缺點:1. 測試腳本只能使用Java語言 2. 測試腳本必須每次被上傳到設備上運行。 我們希望測試能夠用一個更腳本化的語言,例如Python編寫,同時可以每次所見即所得地修改測試、運行測試。這里要非常感謝 Xiaocong He ( @xiaocong ),他將這個想法實現了出來(見 xiaocong/uiautomator ),原理是在手機上運行了一個http服務器,將uiautomator中的功能開放出來,然后再將這些http接口,封裝成Python庫。 我們的uiautomator2項目是對 xiaocong/uiautomator 的增強,主要有以下部分:
  • 設備和開發機可以脫離數據線,通過WiFi互聯(基於 atx-agent
  • 集成了 openstf/minicap加快截圖速度
  • 集成了 openstf/minitouch達到精確實時控制設備
  • 修復了xiaocong/uiautomator經常性退出的問題
  • 代碼進行了重構和精簡,方便維護
雖然我說的很簡單,但是實現起來用到了很多的技術和技巧,功能非常強,唯獨文檔有點少。哈哈
  QQ溝通群:   499563266

Installation

  1. Install uiautomator2
    # Since uiautomator2 is still under development, you have to add --pre to install the development version
    pip install --pre uiautomator2
     
    # Or you can install directly from github source
    pip install -e uiautomator2
     
    Optionally,   pillow   is needed to process screenshot data.
    pip install pillow
  2. Deploy associated daemons to a device    電腦連接上一個手機或多個手機, 確保adb已經添加到環境變量中,執行下面的命令會自動安裝本庫所需要的設備端程序: uiautomator-server   atx-agent openstf/minicap openstf/minitouch
    python -m uiautomator2 init
     
    安裝提示 success 即可

Usage 使用指南

部署   atx-agent 之后,設備可以和電腦通過WiFi鏈接,設備上的 atx-agent 安裝完成后會自動提示手機的IP是多少。下文中我們用 device_ip 這個變量來表示手機的IP,這個IP唯一標示一個設備。
如果手機的WiFi跟電腦不是一個網段的,不能使用WiFi互聯功能,需要通過數據線將手機連接到電腦上,使用命令 adb forward tcp:7912 tcp:7912   將手機上的服務端口7912轉發到電腦上,然后使用 device_ip=127.0.0.1 連接該手機。

命令行使用

  • init: 為設備安裝所需要的程序
  • install: 安裝apk,apk通過URL給出
    $ python -m uiautomator2 install $device_ip https://example.org/some.apk
    MainThread: 15:37:55,731 downloading 80.4 kB / 770.6 kB
    MainThread: 15:37:56,763 installing 770.6 kB / 770.6 kB
    MainThread: 15:37:58,780 success installed 770.6 kB / 770.6 kB
  • clear-cache: 清空緩存
    $ python -m uiautomator2 clear-cache
  • app-stop-all : 停止所有應用
    $ python -m uiautomator2 app-stop-all $device_ip
  • screenshot: 截圖
    $ python -m uiautomator2 screenshot $device_ip screenshot.jpg

QUICK START

There are two ways to connect to the device. Run the following Python code in a Python 2.7/3+ interpreter:
  1. Through WiFi (recommended) Suppose device IP is  10.0.0.1 and your PC is in the same network.  通過WiFi(推薦)假設你的設備ip是10.0.0.1並且你的PC在同一個網絡
import uiautomator2 as u2
 
d = u2.connect( ' 10.0.0.1 ') # alias for u2.connect_wifi('10.0.0.1') print(d.info)
  1. Through USB Suppose the device serial is  123456f (seen from  adb devices)  通過USB連接,假設你的設備的序列號是123456f
import uiautomator2 as u2
 
d = u2.connect( ' 123456f ') # alias for u2.connect_usb('123456f') print(d.info)
Calling   u2.connect()   with no argument,   uiautomator2   will obtain device IP from the environment variable   ANDROID_DEVICE_IP . If this environment variable is empty, uiautomator will fall back to   connect_usb   and you need to make sure that there is only one device connected to the computer.
當調用 u2.connect()不加參數時,uiautomator2 將會從環境變量獲取設備的IP,如果這個環境ANDROID_DEVICE_IP變量是空的話,uiautomator將會退而去調用connect_usb,你要保證只有一個設備連接着電腦.

一些常用但是不知道歸到什么類里的函數

先中文寫着了,國外大佬們先用Google Translate頂着

感覺肯定用得着的資料鏈接

檢查並維持設備端守護進程處於運行狀態

d.healthcheck()

連接本地USB設備

需要設備曾經使用 python -m uiautomator2 init 初始化過
d = u2.connect_usb( " {Your-Device-Serial} " )

一定時間內,出現則點擊

10s內如果出現Skip則點擊
clicked = d( text = ' Skip ' ).click_exists( timeout = 10.0 )

如何停用UiAutomator的守護程序

因為有 atx-agent 的存在,Uiautomator會被一直守護着,如果退出了就會被重新啟動起來。但是Uiautomator又是霸道的,一旦它在運行,手機上的輔助功能、電腦上的uiautomatorviewer 就都不能用了,除非關掉該框架本身的uiautomator。下面就說下兩種關閉方法
方法1:
直接打開 uiautomator   app(init成功后,就會安裝上的),點擊 關閉UIAutomator
方法2:
d.service( " uiautomator " ).stop()

打開調試開關

用於開發者或有經驗的使用者定位問題
>> > d.debug = True >> > d.info
12: 32: 47.182 $ curl -X POST -d ' {"jsonrpc": "2.0", "id": "b80d3a488580be1f3e9cb3e926175310", "method": "deviceInfo", "params": {} } ' ' http://127.0.0.1:54179/jsonrpc/0 ' 12: 32: 47.225 Response >> >
{ " jsonrpc ": " 2.0 ", " id ": " b80d3a488580be1f3e9cb3e926175310 ", " result ":{ " currentPackageName ": " com.android.mms ", " displayHeight ": 1920, " displayRotation ": 0, " displaySizeDpX ": 360, " displaySizeDpY ": 640, " displayWidth ": 1080, " productName "
: " odin ", " screenOn ":true, " sdkInt ": 25, " naturalOrientation ":true}}
<< < END
Notes:   In below examples, we use   d   to represent the uiautomator2 object for the connected device.

Table of Contents  目錄

App management

This part showcases how to perform app management    

Install an app

We only support installing an APK from a URL
d.app_install( ' http://some-domain.com/some.apk ' )

Launch an app

d.app_start( " com.example.hello_world " ) # start with package name

Stop an app

# equivalent to `am force-stop`, thus you could lose data
d.app_stop( " com.example.hello_world ")
# equivalent to `pm clear`
d.app_clear( ' com.example.hello_world ')

Stop all running apps

# stop all
d.app_stop_all()
# stop all app except for com.examples.demo
d.app_stop_all( excludes =[ ' com.examples.demo '])

Push and pull files

  • push a file to the device
    # push to a folder
    d.push( " foo.txt ", " /sdcard/ ")
    # push and rename
    d.push( " foo.txt ", " /sdcard/bar.txt ")
    # push fileobj with open( " foo.txt ", ' rb ') as f:
    d.push(f, " /sdcard/ ")
    # push and change file access mode
    d.push( " foo.sh ", " /data/local/tmp/ ", mode = 0o 755)
  • pull a file from the device
    d.pull( " /sdcard/tmp.txt ", " tmp.txt ")
     
    # FileNotFoundError will raise if the file is not found on the device
    d.pull( " /sdcard/some-file-not-exists.txt ", " tmp.txt ")

Auto click permission dialogs

注意注意   disable_popups 函數,檢測發現很不穩定,暫時不要使用,等候通知。
Import in version 0.1.1
d.disable_popups() # automatic skip popups
d.disable_popups( False) # disable automatic skip popups
If this method is not working on your device, You can make a pull request or create an issue to enhance this function. I'll show you how to do it.
  1. Open  uiautomatorviewer.bat
  2. Get popup hierarchy
Now you know the button text and current package name. Make a pull request by update function   disable_popups   or create an   issue   if you are not familar with git and python.

Basic API Usages

This part showcases how to perform common device operations:

Shell commands

  • Run a short-lived shell command with a timeout protection. (Default timeout 10 minutes)
    d.adb_shell( ' pwd ')
    d.adb_shell( ' ls ', ' -l ')
    d.adb_shell( ' ls -l ')
     
    This returns a UTF-8 encoded string for stdout merged with stderr. Note for binary mode stdouts, the output is encoded as a UTF-8 string not a bytearray. If the command is a blocking command,   adb_shell   will also block until the command is completed or the timeout kicks in. No partial output will be received during the execution of the command. This API is not suitable for long-running commands. The shell command given runs in a similar environment of   adb shell , which has a Linux permission level of   adb   or   shell   (higher than an app permission).
  • Run a long-running shell command   TODO: not implemented yet
    d.adb_shell_longrunning( ' getevent ' , ' -lt ' )
     
    This API returns a generator.

Session

Session represent an app lifestyle. Can be used to start app, detect app crash.
  • Launch app
    sess = d.session( " com.netease.cloudmusic " ) # start 網易雲音樂
  • Attach to the running app
    sess = d.session( " com.netease.cloudmusic " , attach = True )
  • Detect app crash
    # When app is still running
    sess( text = " Music ").click() # operation goes normal
     
    # If app crash or quit
    sess( text = " Music ").click() # raise SessionBrokenError # other function calls under session will raise SessionBrokenError too
     
    # check if session is ok. # Warning: function name may change in the future
    sess.running() # True or False

Retrieve the device info

Get basic information
d.info
Below is a possible output:
{
u'displayRotation': 0,
u'displaySizeDpY': 640,
u'displaySizeDpX': 360,
u'currentPackageName': u'com.android.launcher',
u'productName': u'takju',
u'displayWidth': 720,
u'sdkInt': 18,
u'displayHeight': 1184,
u'naturalOrientation': True
}
Get window size
print(d.window_size())
# device upright output example: (1080, 1920) # device horizontal output example: (1920, 1080)
Get current app info. For some android devices, the output could be empty (see   Output example 3 )
print(d.current_app())
# Output example 1: {'activity': '.Client', 'package': 'com.netease.example', 'pid': 23710} # Output example 2: {'activity': '.Client', 'package': 'com.netease.example'} # Output example 3: {'activity': None, 'package': None}
Get device serial number
print(d.serial)
# output example: 74aAEDR428Z9

Key Events

  • Turn on/off screen
    d.screen_on() # turn on the screen
    d.screen_off() # turn off the screen
  • Get current screen status
    d.info.get( ' screenOn ' ) # require Android >= 4.4
  • Press hard/soft key
    d.press( " home ") # press the home key, with key name
    d.press( " back ") # press the back key, with key name
    d.press( 0x 07, 0x 02) # press keycode 0x07('0') with META ALT(0x02)
  • These key names are currently supported:
    • home
    • back
    • left
    • right
    • up
    • down
    • center
    • menu
    • search
    • enter
    • delete ( or del)
    • recent (recent apps)
    • volume_up
    • volume_down
    • volume_mute
    • camera
    • power
You can find all key code definitions at   Android KeyEvnet
  • Unlock screen
    d.unlock()
    # This is equivalent to # 1. launch activity: com.github.uiautomator.ACTION_IDENTIFY # 2. press the "home" key

Gesture interaction with the device

  • Click on the screen
    d.click(x, y)
  • Long click on the screen
    d.long_click(x, y)
    d.long_click(x, y, 0.5) # long click 0.5s (default)
  • Swipe
    d.swipe(sx, sy, ex, ey)
    d.swipe(sx, sy, ex, ey, 0.5) # swipe for 0.5s(default)
  • Drag
    d.drag(sx, sy, ex, ey)
    d.drag(sx, sy, ex, ey, 0.5) # swipe for 0.5s(default)
  • Swipe points
    # swipe from point(x0, y0) to point(x1, y1) then to point(x2, y2) # time will speed 0.2s bwtween two points
    d.swipe((x0, y0), (x1, y1), (x2, y2), 0.2)
     
    多用於九宮格解鎖,提前獲取到每個點的相對坐標(這里支持百分比), 更詳細的使用參考這個帖子   使用u2實現九宮圖案解鎖
Note: click, swipe, drag operations support percentage position values. Example:
d.long_click(0.5, 0.5)   means long click center of screen

Screen-related

  • Retrieve/Set device orientation
    The possible orientations:
    • natural or  n
    • left or  l
    • right or  r
    • upsidedown or  u (can not be set)
  • # retrieve orientation. the output could be "natural" or "left" or "right" or "upsidedown"
    orientation = d.orientation
     
    # WARNING: not pass testing in my TT-M1 # set orientation and freeze rotation. # notes: setting "upsidedown" requires Android>=4.3.
    d.set_orientation( ' l ') # or "left"
    d.set_orientation( " l ") # or "left"
    d.set_orientation( " r ") # or "right"
    d.set_orientation( " n ") # or "natural"
  • Freeze/Un-freeze rotation
    # freeze rotation
    d.freeze_rotation()
    # un-freeze rotation
    d.freeze_rotation( False)
  • Take screenshot
    # take screenshot and save to a file on the computer, require Android>=4.2.
    d.screenshot( " home.jpg ")
     
    # get PIL.Image formatted images. Naturally, you need pillow installed first
    image = d.screenshot()
    image.save( " home.jpg ") # or home.png. Currently, only png and jpg are supported
     
    # get opencv formatted images. Naturally, you need numpy and cv2 installed first import cv2
    image = d.screenshot( format = ' opencv ')
    cv2.imwrite( ' home.jpg ', image)
  • Dump UI hierarchy
    # get the UI hierarchy dump content (unicoded).
    xml = d.dump_hierarchy()
  • Open notification or quick settings
    d.open_notification()
    d.open_quick_settings()

Selector

Selector is a handy mechanism to identify a specific UI object in the current window. 選擇器是在當前窗口中標識特定UI對象的一種簡便機制。
# Select the object with text 'Clock' and its className is 'android.widget.TextView'
d( text = ' Clock ', className = ' android.widget.TextView ')
Selector supports below parameters. Refer to   UiSelector Java doc   for detailed information.
  • texttextContainstextMatchestextStartsWith
  • classNameclassNameMatches
  • descriptiondescriptionContainsdescriptionMatchesdescriptionStartsWith
  • checkablecheckedclickablelongClickable
  • scrollableenabled, focusablefocusedselected
  • packageNamepackageNameMatches
  • resourceIdresourceIdMatches
  • indexinstance

Children and siblings

    • children
      # get the children or grandchildren
      d( className = " android.widget.ListView ").child( text = " Bluetooth ")
    • siblings
      # get siblings
      d( text = " Google ").sibling( className = " android.widget.ImageView ")
    • children by text or description or instance
      # get the child matching the condition className="android.widget.LinearLayout" # and also its children or grandchildren with text "Bluetooth"
      d( className = " android.widget.ListView ", resourceId = " android:id/list ") \
      .child_by_text( " Bluetooth ", className = " android.widget.LinearLayout ")
       
      # get children by allowing scroll search
      d( className = " android.widget.ListView ", resourceId = " android:id/list ") \
      .child_by_text(
      " Bluetooth ",
      allow_scroll_search = True,
      className = " android.widget.LinearLayout "
      )
      • child_by_description   is to find children whose grandchildren have the specified description, other parameters being similar to   child_by_text .
      • child_by_instance   is to find children with has a child UI element anywhere within its sub hierarchy that is at the instance specified. It is performed on visible views   without scrolling .
See below links for detailed information:
      • UiScrollablegetChildByDescriptiongetChildByTextgetChildByInstance
      • UiCollectiongetChildByDescriptiongetChildByTextgetChildByInstance
Above methods support chained invoking, e.g. for below hierarchy
    • < node index= " 0 " text= " " resource-id= " android:id/list " class= " android.widget.ListView " ...>
      < node index= " 0 " text= " WIRELESS & NETWORKS " resource-id= " " class= " android.widget.TextView " .../>
      < node index= " 1 " text= " " resource-id= " " class= " android.widget.LinearLayout " ...>
      < node index= " 1 " text= " " resource-id= " " class= " android.widget.RelativeLayout " ...>
      < node index= " 0 " text= " Wi‑Fi " resource-id= " android:id/title " class= " android.widget.TextView " .../>
      </ node>
      < node index= " 2 " text= " ON " resource-id= " com.android.settings:id/switchWidget " class= " android.widget.Switch " .../>
      </ node>
      ...
      </ node>
To click the switch widget right to the TextView 'Wi‑Fi', we need to select the switch widgets first. However, according to the UI hierarchy, more than one switch widgets exist and have almost the same properties. Selecting by className will not work. Alternatively, the below selecting strategy would help:
    • d( className = " android.widget.ListView ", resourceId = " android:id/list ") \
      .child_by_text( " Wi‑Fi ", className = " android.widget.LinearLayout ") \
      .child( className = " android.widget.Switch ") \
      .click()
    • relative positioning
      Also we can use the relative positioning methods to get the view:   left ,   right ,   top ,   bottom .
      • d(A).left(B), selects B on the left side of A.
      • d(A).right(B), selects B on the right side of A.
      • d(A).up(B), selects B above A.
      • d(A).down(B), selects B under A.
So for above cases, we can alternatively select it with:
  • # # select "switch" on the right side of "Wi‑Fi"
    d( text = " Wi‑Fi ").right( className = " android.widget.Switch ").click()
  • Multiple instances
    Sometimes the screen may contain multiple views with the same properties, e.g. text, then you will have to use the "instance" property in the selector to pick one of qualifying instances, like below:
    d( text = " Add new " , instance = 0 ) # which means the first instance with text "Add new"
     
    In addition, uiautomator2 provides a list-like API (similar to jQuery):
    # get the count of views with text "Add new" on current screen
    d( text = " Add new ").count
     
    # same as count property len(d( text = " Add new "))
     
    # get the instance via index
    d( text = " Add new ")[ 0]
    d( text = " Add new ")[ 1]
    ...
     
    # iterator for view in d( text = " Add new "):
    view.info # ...
     
    Notes : when using selectors in a list fashion, you must ensure that the UI elements on the screen keep unchanged. Otherwise, when Element-Not-Found error could occur when iterating through the list.

Get the selected ui object status and its information

  • Check if the specific UI object exists
    d( text = " Settings ").exists # True if exists, else False
    d.exists( text = " Settings ") # alias of above property.
  • Retrieve the info of the specific UI object
    d( text = " Settings " ).info
     
    Below is a possible output:
    { u'contentDescription': u'',
    u'checked': False,
    u'scrollable': False,
    u'text': u'Settings',
    u'packageName': u'com.android.launcher',
    u'selected': False,
    u'enabled': True,
    u'bounds': {u'top': 385,
    u'right': 360,
    u'bottom': 585,
    u'left': 200},
    u'className': u'android.widget.TextView',
    u'focused': False,
    u'focusable': True,
    u'clickable': True,
    u'chileCount': 0,
    u'longClickable': True,
    u'visibleBounds': {u'top': 385,
    u'right': 360,
    u'bottom': 585,
    u'left': 200},
    u'checkable': False
    }
  • Get/Set/Clear text of an editable field (e.g., EditText widgets)
    d( text = " Settings ").get_text() # get widget text
    d( text = " Settings ").set_text( " My text... ") # set the text
    d( text = " Settings ").clear_text() # clear the text

Perform the click action on the selected UI object

  • Perform click on the specific object
    # click on the center of the specific ui object
    d( text = " Settings ").click()
    # wait element to appear for at most 10 seconds and then click
    d( text = " Settings ").click( timeout = 10)
    # alias of click
    d( text = " Settings ").tap()
   # tap immediately    d(text="Settings").tap_nowait() ```
  • Perform long click on the specific UI object
    # long click on the center of the specific UI object
    d( text = " Settings ").long_click()

Gesture actions for the specific UI object

  • Drag the UI object towards another point or another UI object
    # notes : drag can not be used for Android<4.3. # drag the UI object to a screen point (x, y), in 0.5 second
    d( text = " Settings ").drag_to(x, y, duration = 0.5)
    # drag the UI object to (the center position of) another UI object, in 0.25 second
    d( text = " Settings ").drag_to( text = " Clock ", duration = 0.25)
  • Two-point gesture from one point to another
    d( text = " Settings " ).gesture((sx1, sy1), (sx2, sy2), (ex1, ey1), (ex2, ey2))
  • Two-point gesture on the specific UI object
    Supports two gestures:
    • In, from edge to center
    • Out, from center to edge
  • # notes : pinch can not be set until Android 4.3. # from edge to center. here is "In" not "in"
    d( text = " Settings ").pinch_in( percent = 100, steps = 10)
    # from center to edge
    d( text = " Settings ").pinch_out()
  • Wait until the specific UI appears or disappears
    # wait until the ui object appears
    d( text = " Settings ").wait( timeout = 3.0) # return bool # wait until the ui object gone
    d( text = " Settings ").wait_gone( timeout = 1.0)
     
    The default timeout is 20s. see   global settings   for more details
  • Perform fling on the specific ui object(scrollable)
    Possible properties:
    • horiz or  vert
    • forward or  backward or  toBeginning or  toEnd
  • # fling forward(default) vertically(default)
    d( scrollable = True).fling()
    # fling forward horizontally
    d( scrollable = True).fling.horiz.forward()
    # fling backward vertically
    d( scrollable = True).fling.vert.backward()
    # fling to beginning horizontally
    d( scrollable = True).fling.horiz.toBeginning( max_swipes = 1000)
    # fling to end vertically
    d( scrollable = True).fling.toEnd()
  • Perform scroll on the specific ui object(scrollable)
    Possible properties:
    • horiz or  vert
    • forward or  backward or  toBeginning or  toEnd, or  to
  • # scroll forward(default) vertically(default)
    d( scrollable = True).scroll( steps = 10)
    # scroll forward horizontally
    d( scrollable = True).scroll.horiz.forward( steps = 100)
    # scroll backward vertically
    d( scrollable = True).scroll.vert.backward()
    # scroll to beginning horizontally
    d( scrollable = True).scroll.horiz.toBeginning( steps = 100, max_swipes = 1000)
    # scroll to end vertically
    d( scrollable = True).scroll.toEnd()
    # scroll forward vertically until specific ui object appears
    d( scrollable = True).scroll.to( text = " Security ")

Watcher

You can register   watchers   to perform some actions when a selector does not find a match.    當選擇器沒有找到匹配項時,可以注冊觀察者來執行某些操作。
  • Register Watcher
    When a selector can not find a match, uiautomator2 will run all registered watchers.
    • Click target when conditions match
  • d.watcher( " AUTO_FC_WHEN_ANR ").when( text = " ANR ").when( text = " Wait ") \
    .click( text = " Force Close ")
    # d.watcher(name) ## creates a new named watcher. # .when(condition) ## the UiSelector condition of the watcher. # .click(target) ## perform click action on the target UiSelector.
    • Press key when a condition becomes true
  • d.watcher( " AUTO_FC_WHEN_ANR ").when( text = " ANR ").when( text = " Wait ") \
    .press( " back ", " home ")
    # d.watcher(name) ## creates a new named watcher. # .when(condition) ## the UiSelector condition of the watcher. # .press(<keyname>, ..., <keyname>.() ## press keys one by one in sequence.
  • Check if the named watcher triggered
    A watcher is triggered, which means the watcher was run and all its conditions matched.
    d.watcher( " watcher_name ").triggered
    # true in case of the specified watcher triggered, else false
  • Remove a named watcher
    # remove the watcher
    d.watcher( " watcher_name ").remove()
  • List all watchers
    d.watchers
    # a list of all registered watchers
  • Check for any triggered watcher
    d.watchers.triggered
    # true in case of any watcher triggered
  • Reset all triggered watchers
    # reset all triggered watchers, after that, d.watchers.triggered will be false.
    d.watchers.reset()
  • Remove watchers
    # remove all registered watchers
    d.watchers.remove()
    # remove the named watcher, same as d.watcher("watcher_name").remove()
    d.watchers.remove( " watcher_name ")
  • Force to run all watchers
    # force to run all registered watchers
    d.watchers.run()
另外文檔還是有很多沒有寫,推薦直接去看源碼 init .py

Global settings

# set delay 1.5s after each UI click and click
d.click_post_delay = 1.5 # default no delay
 
# set default element wait timeout (seconds)
d.wait_timeout = 30.0 # default 20.0

Input method

這種方法通常用於不知道控件的情況下的輸入。第一步需要切換輸入法,然后發送adb廣播命令,具體使用方法如下
d.set_fastinput_ime( True) # 切換成FastInputIME輸入法
d.send_keys( " 你好123abcEFG ") # adb廣播輸入
d.clear_text() # 清除輸入框所有內容(Require android-uiautomator.apk version >= 1.0.7)
d.set_fastinput_ime( False) # 切換成正常的輸入法

Toast

顯示Toast
d.make_toast( " Hello world ")
d.make_toast( " Hello world ", 1.5) # show for 1.5s

測試方法

$ adb forward tcp:9008 tcp:9008
$ curl 127.0.0.1:9008/ping
# expect: pong
 
$ curl -d ' {"jsonrpc":"2.0","method":"deviceInfo","id":1} ' 127.0.0.1:9008/jsonrpc/0
# expect JSON output

Google uiautomator與uiautomator2的區別

  1. API相似但是不完全兼容
  2. uiautomator2是安卓項目,而uiautomator是Java項目
  3. uiautomator2可以輸入中文,而uiautomator的Java工程需借助utf7輸入法才能輸入中文
  4. uiautomator2必須明確EditText框才能向里面輸入文字,uiautomator直接指定父類也可以在子類中輸入文字
  5. uiautomator2獲取控件速度比uiautomator快

常見問題

  1. 提示 502 錯誤
    嘗試手機連接PC,然后運行下面的命令
    adb shell am instrument -w -r -e debug false -e class com.github.uiautomator.stub.Stub \
    com.github.uiautomator.test/android.support.test.runner.AndroidJUnitRunner
     
    如果運行正常,啟動測試之前增加一行代碼 d.healthcheck()
   如果報錯,可能是缺少某個設備組件沒有安裝,使用下面的命令重新初始化   python -m uiautomator2 init --reinstall

實驗室功能

遠程查看

手機 python -m uiautomator2 init 之后,瀏覽器輸入 <device_ip:7912>,會發現一個遠程控制功能,延遲非常低噢。^_^

手機USB連接后,自動調用init命令

項目歷史

CHANGELOG (generated by pbr)

依賴項目

Contributors

Other   contributors

LICENSE

MIT


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM