xiaocong/uiautomator
uiautomator
uiautomator
import
device
as
d
Installation
Pre-requirements
- Install Android SDK, and set ANDROID_HOME environment to the correct path.
- Enable ADB setting on device and connect your android device using usb with your PC.
- Allow apps to install from unknown sources on device settings.
import uiautomator
- If ANDROID_SERIAL is defined in environment, or there is only one device connected:from
uiautomator
import
device
as
d - Speficy the serial number when retrieving the device objectfrom
uiautomator
import
Deviced
=
Device('014E05DE0F02000E') - Speficy the adb server host and port running on other computerAlthough adb supports -a option since SDK 4.3, but now it has a bug on it. The only way to start adb server listenning on all interfaces instead of localhost, is adb -a -P 5037 fork-server server &from
uiautomator
import
Deviced
=
Device('014E05DE0F02000E',
adb_server_host='192.168.1.68',
adb_server_port=5037)
Table of Contents 目录
- Screen Actions of the
device 设备的屏幕操作
- How to selector the
Child and sibling UI object 怎么选择子标签和兄弟标签 - Perform
the click action on the seleted UI object 在指定的UI对象上执行单机操作
Basic API Usages
- Retrieve the device infod.infoBelow is a possible result:{ 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}
Key Event Actions of the device
- Turn on/off screen#
Turn on screend.screen.on()#
Turn off screend.screen.off()Alternative method is:#
wakeup the deviced.wakeup()#
sleep the device, same as turning off the screen.d.sleep() - Check if the screen is on or offif
d.screen
==
"on":
#
of d.screen != "off"#
do something in case of screen onpassif
d.screen
==
"off":
#
of d.screen != "on"#
do something in case of screen offpass - Press hard/soft key#
press home keyd.press.home()#
press back keyd.press.back()#
the normal way to press back keyd.press("back")#
press keycode 0x07('0') with META ALT(0x02) ond.press(0x07,
0x02) - Next keys 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
Gesture interaction of the device
- Click the screen#
click (x, y) on screend.click(x, y) - Long click the screen#
long click (x, y) on screend.long_click(x, y) - Swipe 滑动#
swipe from (sx, sy) to (ex, ey)d.swipe(sx, sy, ex, ey)#
swipe from (sx, sy) to (ex, ey) with 10 stepsd.swipe(sx, sy, ex, ey,
steps=10) - Drag#
drag from (sx, sy) to (ex, ey)d.drag(sx, sy, ex, ey)#
drag from (sx, sy) to (ex, ey) with 10 stepsd.drag(sx, sy, ex, ey,
steps=10)
Screen Actions of the device
- Retrieve/Set Orientation 获取/设置 (手机)方向The possible orientation is:
- natural or n
- left or l
- right or r
- upsidedown or u (can not be set) 颠倒
- #
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" - Freeze/Un-Freeze rotation 锁定/解锁方向#
freeze rotationd.freeze_rotation()#
un-freeze rotationd.freeze_rotation(False) - Take screenshot#
take screenshot and save to local file "home.png", can not work until Android 4.2.d.screenshot("home.png") - Dump Window Hierarchy 存储窗口结构#
dump the widown hierarchy and save to local file "hierarchy.xml"d.dump("hierarchy.xml")#
or get the dumped content(unicode) from return.xml
=
d.dump() - Open notification or quick settings 打开通知栏/快速设置栏#
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() - Wait for idle or window update 等待空闲或窗口更新#
wait for current window to idled.wait.idle()#
wait until window update event occursd.wait.update()
Watcher 观察者
- Register WatcherWhen a selector can not find a match, uiautomator 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 conditions match
- d.watcher("AUTO_FC_WHEN_ANR").when(text="ANR").when(text="Wait") \.press.back.home()#
Alternative way to define it as belowd.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.#
Alternavie way defining key sequence is press(<keybname>, ..., <keyname>) - Check if the named watcher triggeredA 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 named watcher#
remove the watcherd.watcher("watcher_name").remove() - List all watchersd.watchers#
a list of all registered wachers' names - Check if there is any watcher triggeredd.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() - Remvoe watchers#
remove all registered watchersd.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 watchersd.watchers.run()
Handler
fc_close(device):
device(text='Force Close').exists:
True
#
return True means to break the loop of handler callback functions.
turn on the handler callback function
turn off the handler callback function
Selector
To seleted the object ,text is 'Clock' and its className is 'android.widget.TextView'
className='android.widget.TextView')
- 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
Child and sibling UI object
- child#
get the child or grandchildd(className="android.widget.ListView").child(text="Bluetooth") - sibling#
get sibling or child of siblingd(text="Google").sibling(className="android.widget.ImageView") - child by text or description or instance#
get the child match className="android.widget.LinearLayout"#
and also it or its child or grandchild contains text "Bluetooth"d(className="android.widget.ListView",
resourceId="android:id/list") \.child_by_text("Bluetooth",
className="android.widget.LinearLayout")#
allow scroll search to get the childd(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 child which or which's grandchild contains the specified description, others are the same as child_by_text.
- child_by_instance is to find child which has a child UI element anywhere within its sub hierarchy that is at the instance specified. It is performed on visible views without scrolling.
- UiScrollable, getChildByDescription, getChildByText, getChildByInstance
- UiCollection, getChildByDescription, getChildByText, getChildByInstance
- <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>

- 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 positionAlso we can use the relative position methods to get the view: left, right, top, bottom.
- d(A).left(B), means selecting B on the left side of A.
- d(A).right(B), means selecting B on the right side of A.
- d(A).up(B), means selecting B above A.
- d(A).down(B), means selecting B under A.
- ## 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 e.g. text, then you will have to use "instance" properties in selector like below:d(text="Add new",
instance=0)
#
which means the first instance with text "Add new"However, uiautomator provides list like methods to use it.#
get the count of views with text "Add new" on current screend(text="Add new").count#
same as count propertylen(d(text="Add new"))#
get the instance via indexd(text="Add new")[0]d(text="Add new")[1]...#
iteratorfor
view
in
d(text="Add new"):view.info
#
...Notes: when you are using selector like a list, you must make sure the screen keep unchanged, else you may get ui not found error.
Get the selected ui object status and its information
- Check if the specific ui object existsd(text="Settings").exists
#
True if exists, else Falsed.exists(text="Settings")
#
alias of above property. - Retrieve the info of the specific ui objectd(text="Settings").infoBelow is a possible result:{ 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}
- Set/Clear text of editable fieldd(text="Settings").clear_text()
#
clear the textd(text="Settings").set_text("My text...")
#
set the text
Perform the click action on the seleted ui object
- Perform click on the specific ui object#
click on the center of the specific ui objectd(text="Settings").click()#
click on the bottomright corner of the specific ui objectd(text="Settings").click.bottomright()#
click on the topleft corner of the specific ui objectd(text="Settings").click.topleft()#
click and wait until the new window updated(text="Settings").click.wait() - Perform long click on the specific ui object#
long click on the center of the specific ui objectd(text="Settings").long_click()#
long click on the bottomright corner of the specific ui objectd(text="Settings").long_click.bottomright()#
long click on the topleft corner of the specific ui objectd(text="Settings").long_click.topleft()
Gesture action for the specific ui object
- Drag the ui object to another point or ui object#
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)d(text="Settings").drag.to(text="Clock",
steps=50) - Swipe from the center of the ui object to its edgeSwipe supports 4 directions: 滑动支持4种方向
- left
- right
- top
- bottom
- 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 anotherd(text="Settings").gesture((sx1, sy1), (sx2, sy2)) \.to((ex1, ey1), (ex2, ey2))
- Two point gesture on the specific ui objectSupports 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 edged(text="Settings").pinch.Out() - 3 point gestured().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))
- Wait until the specific ui object appears or gone#
wait until the ui object appearsd(text="Settings").wait.exists(timeout=3000)#
wait until the ui object goned(text="Settings").wait.gone(timeout=1000) - 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 horizentallyd(scrollable=True).fling.horiz.forward()#
fling backward verticallyd(scrollable=True).fling.vert.backward()#
fling to beginning horizentallyd(scrollable=True).fling.horiz.toBeginning(max_swipes=1000)#
fling to end verticallyd(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 horizentallyd(scrollable=True).scroll.horiz.forward(steps=100)#
scroll backward verticallyd(scrollable=True).scroll.vert.backward()#
scroll to beginning horizentallyd(scrollable=True).scroll.horiz.toBeginning(steps=100,
max_swipes=1000)#
scroll to end verticallyd(scrollable=True).scroll.toEnd()#
scroll forward vertically until specific ui object appearsd(scrollable=True).scroll.to(text="Security")
Contribution 贡献
- Fork the repo, and clone to your computer.
- Checkout a new branch from develop branch
- Install requirements: pip install -r requirements.txt
- Make your changes, and update tests. Don't forget adding your name at the end of 'Contributors' section
- Pass all tests and your code must be covered: tox.
- Commit your changes and submit pull request to develop branch.
Contributors
- Xiaocong He (@xiaocong)
- Yuanyuan Zou (@yuanyuan)
- Qian Jin (@QianJin2013)
- Xu Jingjie (@xiscoxu)
- Xia Mingyuan (@mingyuan-xia)
Issues & Discussion 问题与讨论
Notes
- Android uiautomator works on Android 4.1+, so before using it, make sure your device is Android4.1+.
- Some methods are only working on Android 4.2/4.3, so you'd better read detailed java documentation of
uiautomatorbefore using it. - The module uses uiautomator-jsonrpc-server as its daemon to communicate with devices. daemon:
- The module is only tested on python2.7/3.2/3.3/pypy.
FAQ
- Could not start JSONRPC server: raise IOError("RPC server not started!")It may be caused by network, device, or environment. So when you meet the issue, please follow below steps and try to manually start the JSONRPC server.
- Follow steps at uiautomator-jsonrpc-server to start jsonrpc server.
- Check if jsonrpc server is ok:curl -d '{"jsonrpc":"2.0","method":"deviceInfo","id":1}' localhost:9008/jsonrpc/0If you see message like {"jsonrpc":"2.0","id":1,"result":{"currentPackageName":"android","displayHeight":1280,"displayRotation":0,"displaySizeDpX":0,"displaySizeDpY":0,"displayWidth":720,"productName":"falcon","sdkInt":17,"naturalOrientation":true}}, it means the server is up.
- Error httplib.BadStatusLine: ''JsonRPC server needs to access temp directory on device, but on some low tier devices, it may meet error during accessing temp files without SD-CARD attached. So if you met the error, please insert a SD-CARD and then try again.
License
xiaocong/uiautomator的更多相关文章
- [python学习篇] uiautomator xiaocong
Skip to content This repository Pull requests Issues Marketplace Gist Sign out Watch103 ...
- uiautomator +python 实现安卓自动化
很多人看到这个题目我相信他们可能会说,uiautomator不是java开发的吗?python怎么用呢,其实呢 ,一开始我也是这么想的,看了金阳光老师的视频,也是用java写的,我表示不服,我要科学上 ...
- Android高手速成--第四部分 开发工具及测试工具
第四部分 开发工具及测试工具 主要介绍和Android开发工具和测试工具相关的开源项目. 一.开发效率工具 Json2Java根据JSon数据自动生成对应的Java实体类,还支持Parcel.Gson ...
- Android开源项目分类汇总
目前包括: Android开源项目第一篇——个性化控件(View)篇 包括ListView.ActionBar.Menu.ViewPager.Gallery.GridView.ImageView. ...
- android 很多牛叉布局github地址(转)
原文地址 http://blog.csdn.net/luo15309823081/article/details/41449929 点击可到达github-------https://github.c ...
- GitHub上史上最全的Android开源项目分类汇总 (转)
GitHub上史上最全的Android开源项目分类汇总 标签: github android 开源 | 发表时间:2014-11-23 23:00 | 作者:u013149325 分享到: 出处:ht ...
- 【Android】Android开源项目分类汇总
第一部分 个性化控件(View) 主要介绍那些不错个性化的View,包括ListView.ActionBar.Menu.ViewPager.Gallery.GridView.ImageView.Pro ...
- Github上的andoird开源组件整理
http://blog.csdn.net/findsafety/article/details/50623627 第一部分 个性化控件(View) 主要介绍那些不错个性化的View,包括ListVie ...
- Android开源项目汇总【转】
主要介绍那些不错个性化的View,包括ListView.ActionBar.Menu.ViewPager.Gallery.GridView.ImageView.ProgressBar.TextView ...
随机推荐
- .NET Utils 辅助类
using System;using System.Diagnostics;using System.IO;using System.Reflection;using System.Runtime.I ...
- DB2锁机制
相比较Oracle来说,DB2的锁机制麻烦了很多,而且这个麻烦带来的不是性能的上升而是下降,不过如果细致了解的话,只能感慨不愧是数据库理论诞生的公司,在实现数据库理论上比Oracle全面得多. ...
- mysql thread_cache 和 thread_pool 之间的关系
线程池是Mysql5.6的一个核心功能,对 于服务器应用而言,无论是web应用服务还是DB服务,高并发请求始终是一个绕不开的话题.当有大量请求并发访问时,一定伴随着资源的不断创建和释放,导 致资源利用 ...
- Jmeter If Controller中设置多个条件用“与”进行连接
"${noteID}"!="NOT FOUND" && "${securitiesId}"!="0P00011FQ ...
- sqoop 安装使用
安装配置: 1.将sqoop-1.4.4.tar.gz 上传到/usr/local/ 2.解压 tar -zxvf sqoop-1.4.4.tar.gz 3.配置 vim /etc/profile 在 ...
- 2018.08.30 NOIP模拟 kfib(矩阵快速幂+exgcd)
[输入] 一行两个整数 n P [输出] 从小到大输出可能的 k,若不存在,输出 None [样例输入 1] 5 5 [样例输出] 2 [样例解释] f[0] = 2 f[1] = 2 f[2] = ...
- 19. Fight over Fox-hunting 猎狐引发的冲突
. Fight over Fox-hunting 猎狐引发的冲突 ① Foxes and farmers have never got on well.These small dog-like ani ...
- Django入门与实践-第22章:基于类的视图
http://127.0.0.1:8000/boards/1/topics/2/posts/2/edit/ http://127.0.0.1:8000/ #boards/views.py from d ...
- 【转】Paxos算法1-算法形成理论
——转自:{老码农的专栏} Paxos算法的难理解与算法的知名度一样令人敬仰,从我个人的经历而言,难理解的原因并不是该算法高深到大家智商不够,而在于Lamport在表达该算法时过于晦涩且缺乏一个完整的 ...
- GoogleStyle格式化代码
<div class="iteye-blog-content-contain" style="font-size: 14px"></div&g ...