1、设备对象
引入uiautomator,获取设备对象<所谓设备对象可理解为:Android模拟器或者真机>
语法:from uiautomator import device as d
d 即为设备对象
1.1、获取设备信息
语法:d.info
返回值:
1
2
|
`
{
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
`
`
}
`
|
返回值解释如下:
displayRotation 0 代表竖屏 1 代表横屏
currentPackageName 当前的Activity的Package名字
productName 当前设备名称
displayWidth 当前设备屏幕宽度 当 displayRotation 取值为 1 时,也就是说当前是横屏状态时,displayWidth 取值会和 displayHeight 互换
displayHeight 当前设备屏幕高度 当 displayRotation 取值为 1 时,也就是说当前是横屏状态时,displayHeight 取值会和 displayWidth 互换
sdkInt 当前SDK版本
naturalOrientation 当 displayRotation 取值为 1 时,也就是说当前是横屏状态时,取值为False,为竖屏状态时,取值为:True
1.2、点亮或熄灭屏幕(Turn on/off screen)
1
2
3
4
5
6
7
8
9
|
# Turn on screen
d
.
screen
.
on
(
)
# Turn off screen
d
.
screen
.
off
(
)
# wakeup the device
d
.
wakeup
(
)
# sleep the device, same as turning off the screen.
d
.
sleep
(
)
|
检查屏幕状态,关闭OR点亮?
1
2
3
4
5
6
7
|
if
d
.
screen
==
"on"
:
# of d.screen != "off"
# do something in case of screen on
pass
if
d
.
screen
==
"off"
:
# of d.screen != "on"
# do something in case of screen off
pass
|
1.3、系统常用按键
1
2
3
4
5
6
7
8
9
|
# press home key
d
.
press
.
home
(
)
# press back key
d
.
press
.
back
(
)
# the normal way to press back key
d
.
press
(
"back"
)
# press keycode 0x07('0') with META ALT(0x02) on
d
.
press
(
0x07
,
0x02
)
|
下面的这些按键也是被支持的,如下:
Next keys are currently supported:
home #手机Home键
back #手机返回键
left #对应键盘上的向右键<-
right #对应键盘上的向右键->
up #对应键盘上的向上键
down #对应键盘上的向下键
center #选中?
menu #菜单
search #查找?
enter #对应键盘上的Enter键
delete
(ordel
) #对应键盘上的DEL键 用于删除recent
(recent apps) #任务切换volume_up #声音向上调整
volume_down #声音向下调整
volume_mute #静音按键
camera #拍照
power #电源键
1.4、与设备交互(单击、长按、滑动(手势密码)、拖拽)
单击屏幕坐标点
1
2
3
|
# click (x, y) on screen
d
.
click
(
x
,
y
)
|
长按屏幕坐标点
1
2
3
|
# long click (x, y) on screen
d
.
long_click
(
x
,
y
)
|
在屏幕上滑动
1
2
3
4
5
|
# swipe from (sx, sy) to (ex, ey)
d
.
swipe
(
sx
,
sy
,
ex
,
ey
)
# swipe from (sx, sy) to (ex, ey) with 10 steps
d
.
swipe
(
sx
,
sy
,
ex
,
ey
,
steps
=
10
)
|
在屏幕上拖拽
1
2
3
4
5
|
# drag from (sx, sy) to (ex, ey)
d
.
drag
(
sx
,
sy
,
ex
,
ey
)
# drag from (sx, sy) to (ex, ey) with 10 steps
d
.
drag
(
sx
,
sy
,
ex
,
ey
,
steps
=
10
)
|
1.5、屏幕操作及屏幕方向获取与控制<上述:displayRotation 0 代表竖屏 1 代表横屏>,竖屏分为 natural(自然的,正常的竖屏) 和 upsidedown(倒过来的竖屏),横屏分为向左和向右两个方向,分别为:left 和 right
设备属性:orientation 可能取得值为:
natural
orn
left
orl
right
orr
upsidedown
oru
(can not be set)
说明:在手机设备上,倒过来的屏幕很少见,因此:d.orientation 取值 upsidedown 的可能性几乎没有
1
2
3
4
5
6
7
8
|
# retrieve orientation, it may be "natural" or "left" or "right" or "upsidedown" 获取设备屏幕方向如下:
orientation
=
d
.
orientation
# set orientation and freeze rotation.
# notes: "upsidedown" can not be set until Android 4.3. 设置设备屏幕方向如下:
d
.
orientation
=
"l"
# or "left"
d
.
orientation
=
"r"
# or "right"
d
.
orientation
=
"n"
# or "natural"
|
锁屏/解除锁屏
1
2
3
4
5
|
# freeze rotation
d
.
freeze_rotation
(
)
#锁屏
# un-freeze rotation
d
.
freeze_rotation
(
False
)
#解锁
|
截屏操作
1
2
3
|
# take screenshot and save to local file "home.png", can not work until Android 4.2.
d
.
screenshot
(
"home.png"
)
|
打开通知或快速设置
1
2
3
4
5
|
# open notification, can not work until Android 4.3.
d
.
open
.
notification
(
)
# open quick settings, can not work until Android 4.3.
d
.
open
.
quick_settings
(
)
|
注意:(如果notification已经打开了,调用d.open.quick_settings()不会打开快速设置)
等待空闲或窗口更新(Wait for idle or window update)
1
2
3
4
5
|
# wait for current window to idle
d
.
wait
.
idle
(
)
# wait until window update event occurs
d
.
wait
.
update
(
)
|
2、uiautomator 选择器
选择器是在当前窗口中标识特定的UI对象。可理解为:UiObject对象
目前,在uiautomator中支持以下属性选择器:
1
2
3
4
5
6
7
8
9
|
text
,
textContains
,
textMatches
,
textStartsWith
className
,
classNameMatches
description
,
descriptionContains
,
descriptionMatches
,
descriptionStartsWith
checkable
,
checked
,
clickable
,
longClickable
scrollable
,
enabled
,
focusable
,
focused
,
selected
packageName
,
packageNameMatches
resourceId
,
resourceIdMatches
index
,
instance
|
下面依次进行解读:
2.1、text选择器(支持在uiautomator中Text属性不为空的元素)
例如:
具体用法如下:
1
2
3
4
5
6
|
d
(
text
=
"Maps"
)
.
click
(
)
#当然也可以多个属性在一块使用
d
(
text
=
"Maps"
,
className
=
"android.widget.TextView"
)
.
click
(
)
#或者
d
(
text
=
"Maps"
,
className
=
"android.widget.TextView"
,
packageName
=
"com.google.android.apps.nexuslauncher"
)
.
click
(
)
|
总之:要尽可能的使用选择器唯一确定一个被选择对象(UiObject)
除了可以进行选择UiObject对象以外,我们亦可以使用选择器设置某些元素的值,如下:

1
2
3
4
5
|
#输入短信目标手机号
d
(
text
=
"To"
)
.
set_text
(
"10086"
)
#如果本窗口中有多个text为To的元素,我们也可以使用多属性选择
d
(
text
=
"To"
,
packageName
=
"com.google.android.apps.messaging"
)
.
set_text
(
"10086"
)
.
set_text
(
"10086"
)
|
textContains,textMaches,textStartsWith 分别代表:包含,正则表达式,以XXX开头等
例如:
d(text="Name").set_text("John")
d(textContains="ame").set_text("John")
d(textStartsWith="Nam").set_text("John")
2.2、className,classNameMatches 类选择器 及 description, descriptionContains, descriptionMatches, descriptionStartsWith 描述选择器 及 packageName, packageNameMatches 包选择器 及 resourceId, resourceIdMatches ResId选择器用法和text选择器类似,都可以多属性选择器结合在一起使用。
示例代码如下:
1
2
3
4
5
6
|
# To seleted the object ,text is 'Clock' and its className is 'android.widget.TextView'
d
(
text
=
'Clock'
,
className
=
'android.widget.TextView'
)
d
(
description
=
"add new contact"
)
.
click
(
)
d
(
descriptionContains
=
"new contact"
)
.
click
(
)
d
(
descriptionStartsWith
=
"add new"
)
.
click
(
)
|
1
2
3
4
5
6
7
8
9
10
11
|
#resourceid选择器
d
(
resourceId
=
"com.android.contacts:id/menu_save"
)
.
click
(
)
#text选择器
d
(
textStartsWith
=
"Nam"
)
.
set_text
(
"John"
)
#描述选择器
d
(
descriptionContains
=
"new contact"
)
.
click
(
)
#多属性结合
d
(
text
=
"Name"
,
className
=
"android.widget.EditText"
)
.
set_text
(
"John"
)
#index选择器和child选择器
d
(
resourceId
=
"com.android.settings:id/list"
)
.
child
(
className
=
"android.widget.LinearLayout"
,
index
=
2
)
.
child
(
resourceId
=
"android:id/widget_frame"
)
.
child
(
resourceId
=
"android:id/switch_widget"
)
.
click
(
)
|
在此,说明下child、sibling选择器和index选择器及instance选择器(严格讲instance不是选择器,仅仅只是在输出多个结果的情况下,可以通过索引(下标)进行选择)
首先说明child选择器,sibling选择器:分别可理解为:子选择器(可嵌套),兄弟姐妹选择器

如上图右边部分,从上到下层次分为四层,最后一层的两个元素可理解为兄弟姐妹,在此,我们如果要选择最下面的那个元素就可以用到child选择器及sibling选择器,当然,本人不建议使用孩子,兄妹选择器,如果能用其他方法实现,建议用其他方法:
在此,我写的方法如下:<没有具体验证,仅仅只是演示>
1
2
3
|
#孩子选择器及兄弟姐妹选择器的用法:child/sibling
d
(
resourceId
=
"id/pager"
)
.
child
(
className
=
"android.widget.FrameLayout"
)
.
child
(
resourceId
=
"id/empty_view"
)
.
child
(
resourceId
=
"id/empty_image_hint"
)
.
sibling
(
packageName
=
"com.google.android.apps.messaging"
)
|
2.3、index选择器及instance,比较容易混淆的两个,一个是选择器,一个代表索引,如下:
index选择器对应uiautomator的index属性,如下:

其用法和text选择器大同小异,不过在此需要指出的是,有些窗体中index取值会发生改变,因此,能不用index选择器的,尽可能不用!
1
2
3
|
#index选择器
d
(
className
=
"android.widget.LinearLayout"
,
index
=
2
)
.
click
(
)
|
instance 的用法:当你的选择器返回的结果不是指向唯一元素时(两个或者多个),你可以通过instance进行选择。
贺晓聪原文:
Multiple instances
Sometimes the screen may contain multiple views with the same e.g. text, then you will have to use "instance" properties in selector like below:
1
2
|
d
(
text
=
"Add new"
,
instance
=
0
)
# which means the first instance with text "Add new"
|
However, uiautomator provides list like methods to use it.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
# 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
# ...
|
2.4、获取选定的UI对象状态及其信息(Get the selected ui object status and its information)
检测特定的UI对象是否存在(Check if the specific ui object exists)
两种写法,如下:
1
2
3
|
d
(
text
=
"Settings"
)
.
exists
# True if exists, else False
d
.
exists
(
text
=
"Settings"
)
# alias of above property.
|
检索特定UI对象的信息(Retrieve the info of the specific ui object)
1
2
|
d
(
text
=
"Settings"
)
.
info
|
(结果为列表List),如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
{
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
}
|
设置/清除字段或编辑文本
1
2
3
|
d
(
text
=
"Settings"
)
.
clear_text
(
)
# clear the text
d
(
text
=
"Settings"
)
.
set_text
(
"My text..."
)
# set the text
|
执行单击特定的UI对象
1
2
3
4
5
6
7
8
9
|
# click on the center of the specific ui object
d
(
text
=
"Settings"
)
.
click
(
)
# click on the bottomright corner of the specific ui object 单击右下方
d
(
text
=
"Settings"
)
.
click
.
bottomright
(
)
# click on the topleft corner of the specific ui object 单击左上方
d
(
text
=
"Settings"
)
.
click
.
topleft
(
)
# click and wait until the new window update 单击并等待窗体响应
d
(
text
=
"Settings"
)
.
click
.
wait
(
)
|
长时间点击特定的ui对象,双击?
1
2
3
4
5
6
7
|
# long click on the center of the specific ui object
d
(
text
=
"Settings"
)
.
long_click
(
)
# long click on the bottomright corner of the specific ui object 右下角
d
(
text
=
"Settings"
)
.
long_click
.
bottomright
(
)
# long click on the topleft corner of the specific ui object 左上角
d
(
text
=
"Settings"
)
.
long_click
.
topleft
(
)
|
将UI对象拖动到另一点
1
2
3
4
5
6
|
# notes : drag can not be set until Android 4.3.
# drag the ui object to point (x, y)
d
(
text
=
"Settings"
)
.
drag
.
to
(
x
,
y
,
steps
=
100
)
# drag the ui object to another ui object(center) 拖拽到text='Clock'的对象位置上
d
(
text
=
"Settings"
)
.
drag
.
to
(
text
=
"Clock"
,
steps
=
50
)
|
滑动UI对象
滑动分为四个方向:left ,right,top ,bottom 即:左滑动 右滑动 上滑动 及向下滑动
1
2
3
4
5
|
d
(
text
=
"Settings"
)
.
swipe
.
right
(
)
d
(
text
=
"Settings"
)
.
swipe
.
left
(
steps
=
10
)
d
(
text
=
"Settings"
)
.
swipe
.
up
(
steps
=
10
)
d
(
text
=
"Settings"
)
.
swipe
.
down
(
)
|
Two point gesture from one point to another
1
2
|
d
(
text
=
"Settings"
)
.
gesture
(
(
sx1
,
sy1
)
,
(
sx2
,
sy2
)
)
.
to
(
(
ex1
,
ey1
)
,
(
ex2
,
ey2
)
)
|
Two point gesture on the specific ui object
Supports two gestures:
In
, from edge to centerOut
, from center to edge
1
2
3
4
5
6
|
# 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
(
)
|
3 point gesture
1
2
3
4
|
d
(
)
.
gestureM
(
(
sx1
,
sy1
)
,
(
sx2
,
sy2
)
,
(
sx3
,
sy3
)
)
\
.
to
(
(
ex1
,
ey1
)
,
(
ex2
,
ey2
)
,
(
ex3
,
ey3
)
)
d
(
)
.
gestureM
(
(
100
,
200
)
,
(
300
,
200
)
,
(
600
,
200
)
,
(
100
,
600
)
,
(
300
,
600
)
,
(
600
,
900
)
)
|
等到特定的UI对象出现或消失
1
2
3
4
5
|
# wait until the ui object appears
d
(
text
=
"Settings"
)
.
wait
.
exists
(
timeout
=
3000
)
# wait until the ui object gone
d
(
text
=
"Settings"
)
.
wait
.
gone
(
timeout
=
1000
)
|
在具体的UI对象执行甩(滚动)Perform scroll on the specific ui object(scrollable)
Possible properties:
horiz
orvert
forward
orbackward
ortoBeginning
ortoEnd
1
2
3
4
5
6
7
8
9
10
11
|
# fling forward(default) vertically(default)
d
(
scrollable
=
True
)
.
fling
(
)
# fling forward horizentally
d
(
scrollable
=
True
)
.
fling
.
horiz
.
forward
(
)
# fling backward vertically
d
(
scrollable
=
True
)
.
fling
.
vert
.
backward
(
)
# fling to beginning horizentally
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)-在具体的UI对象执行甩(滚动)
Possible properties:
horiz
orvert
forward
orbackward
ortoBeginning
ortoEnd
, orto
1
2
3
4
5
6
7
8
9
10
11
12
13
|
# scroll forward(default) vertically(default)
d
(
scrollable
=
True
)
.
scroll
(
steps
=
10
)
# scroll forward horizentally
d
(
scrollable
=
True
)
.
scroll
.
horiz
.
forward
(
steps
=
100
)
# scroll backward vertically
d
(
scrollable
=
True
)
.
scroll
.
vert
.
backward
(
)
# scroll to beginning horizentally
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"
)
|