【Android测试】【第十二节】Uiautomator——API详解
◆版权声明:本文出自carter_dream的博客,转载必须注明出处。
转载请注明出处:http://www.cnblogs.com/by-dream/p/4921701.html
简单的例子
以一个简单的例子开始吧。我们完成一个 " 打开QQ,进入QQ空间,然后退出 " 的case。
代码如下:
package QQ; import java.io.IOException; import com.android.uiautomator.core.UiDevice;
import com.android.uiautomator.core.UiObject;
import com.android.uiautomator.core.UiObjectNotFoundException;
import com.android.uiautomator.core.UiSelector;
import com.android.uiautomator.testrunner.UiAutomatorTestCase; public class Test_qq extends UiAutomatorTestCase
{
public void testDemo() throws IOException, UiObjectNotFoundException { // 启应用
Runtime.getRuntime().exec("am start com.tencent.mobileqq/com.tencent.mobileqq.activity.SplashActivity");
sleep(3000); // 点击 "动态" tab
UiDevice device = getUiDevice();
int height = device.getDisplayHeight();
int width = device.getDisplayWidth();
device.click(width -50, height-50);
sleep(1000); // 点击 "好友动态" 按钮
UiObject obj_1 = new UiObject(new UiSelector().description("点击进入好友动态"));
obj_1.click();
sleep(2000); // 点击 左上角返回 "动态"按钮
UiObject obj_2 = new UiObject(new UiSelector().resourceId("com.tencent.mobileqq:id/ivTitleBtnLeft"));
obj_2.click();
sleep(1000); // 点击菜单键
device.pressMenu();
sleep(1000); // 点击退出qq
UiObject obj_3 = new UiObject(new UiSelector().text("退出QQ"));
obj_3.click();
sleep(1000); // 点击确定
UiObject obj_4 = new UiObject(new UiSelector().text("确定"));
obj_4.click();
}
}
脚本的运行效果如下:

代码详解
针对上面的例子的代码,我对每一句代码都做个详细的解释吧。
第一部分:启动应用

exec() 这个函数的意思,相当于是在你在输入adb shell 命令后,在Android手机系统的命令行下运行。所以上面这句话的意思和我们打开cmd框输入" adb shell am start *** " 是一样的的效果。
一般来说我们做App的自动化的时候,第一步都是把App打开,这个am start命令的就可以帮我们实现,类似与Monkeyrunner API中的startActivity() 函数。
第二部分:点击 “动态” tab
UiDevice对象会在API部分详细讲解,它是一个我们在Uiautomator中经常使用的一个对象。
这里我们首先用它获取到当前手机的宽和高的像素。然后观察到 “动态” tab位于右下方,因此在取得右下角的坐标点后,又进行了一个大概的坐标变化(这里为了简单只是向左和向上移动了50像素,如果要精确的可以进行等比转化),然后点击该坐标。
这里之所以用点击坐标的方法,一方面是因为这个控件Uiautomator不支持用API获得实例(上一节所说的NAF Nodes,如下图),另一方面也是想说明在一些控件没有固定的id、text和desc的时候,我们应该怎么处理。

第三部分:点击 “好友动态”
要想操作一个控件(例如),首先得获得一个UiObject对象,而UiObject对象可以通过UiSelector来构造,而UiSelector可以根据控件的id、text、content-desc来进行构造,这里就是用content-desc来构造。

如上图用 uiautomatorviewer 查到该控件的 content-desc 的内容是 “点击进入好友动态” ,因此我们就可以通过代码中的方法来得到UiObject对象了,然后调用click() 方法来达到点击效果。
第四部分:点击左上角返回按钮


同第三部分的方法,找到id后直接获得到UiObject对象,进行点击。
第五部分:点击菜单键

UiDevice 可以模拟点击home、back、menu 这三个键,代码应该大家都懂的怎么变化了吧。
第六部分:退出

这一部分也是先通过获取出控件属性中的text值,然后构造出UiObject对象,完成点击。
以上部分内容就是整个操作QQ这个小例子的全部代码讲解,看完之后对写Uiautomator代码有了更进一步的了解了吧。接下来写看看还有哪些API可以支持我们做更多的事情。
API 列举
UiDevice
概述:
UiDevice用与访问关设备状态的信息,也可以使用这个类来模拟用户在设备上的操作。可以通过下面的方法得到实例:
UiDevice mdevice = getUiDevice();
摘要:
| 函数返回值 | 函数体 | 说明 | 实例 |
| boolean | click(int x, int y) | 模拟用户在指定位置点击 | mdevice.click(200, 300) 点击屏幕的200,300坐标处 |
| String | getCurrentActivityName() | 获得的是应用程序在桌面上显示的名字 | 例如,在qq首页得到的是“QQ”,在微信登录页得到的是“微信”,注意,这个得到的不是Activity的名字 |
| String | getCurrentPackageName() | 获得当前显示的应用程序的包名 | 例如,在微信启动的时候,获得的是“com.tencent.mm” |
| int | getDisplayHeight() | 获得当前设备的屏幕分辨率的高 | 例如,我的手机1920*1080,得到的是 1920 |
| int | getDisplayWighth() | 获得当前设备的屏幕分辨率的宽 | 例如,我的手机1920*1080,得到的是 1080 |
| boolean | isScreenOn() | 判断手机当前是否灭屏 | 当手机灭屏的时候,得到是“false”,手机亮屏,得到的是“true” |
| void | wakeUp() | 点亮当前屏幕 | 调用后,相当于按下了电源键,如果手机设置了滑动锁屏,滑动锁屏还是在的,不会自动解开 |
| boolean | pressBack() | 点击back键 | |
| boolean | pressHome() | 点击home键 | |
| boolean | pressMenu() | 点击menu键 | |
| boolean | pressKeyCode(int keyCode) | 利用keycode值模拟一次按下事件 | 例如,需要按下数字1 数字1的keycode是 KEYCODE_NUMPAD_1,更多keycode可以在 http://developer.android.com/intl/zh-cn/reference/android/view/KeyEvent.html进行查询 |
| boolean | swipe(int startX, int startY, int endX, int endY, int steps) | 用指定的步长,从A点滑动B点 | 例如,需要从(10, 10)点用两步滑动到(100, 200)点,则需要mdevice.swipe(10, 10, 100, 200, 2) |
| boolean | takeScreenshot(File storePath) | 截取当前屏幕,保存到文件 | 例如,File files = new File("/sdcard/res.jpg"); mdevice.takeScreenshot(files); 即可将截图保存到sd卡中了。 |
UiSelector
概述:
按照一定的条件(例如控件的text值,资源id),定位界面上的元素。UiSelector对象的最终目的是去构造一个UiObject对象。
摘要:
1、根据text构造:
| 函数返回值 | 函数体 | 说明 | 用法 |
| UiSelector | text(String text) | 根据“控件text属性的内容”构造出UiSelector对象 | 例如,一个控件text的值是“发现”,UiSelector s = new UiSelector().text("发现"); |
| UiSelector | textContains(String text) | 根据“控件text属性包含的内容”构造出UiSelector对象 | 同上例子:UiSelector s = new UiSelector().textContains("现"); |
| UiSelector | textMatches(String regex) | 根据“控件text属性正则表达式的内容”构造出UiSelector对象 | 正则表达式语法参考网上资料即可。 |
| UiSelector | textStartsWith(String text) | 根据“控件text属性开始的内容”构造出UiSelector对象 | 同上例子:UiSelector s = new UiSelector().textStartsWith("发"); |
比较常用,准确度也比较高,中文查找的时候,如果遇到 “UiOjbectNotFoundException” 的时候,记得把项目的编码格式改为utf-8。
2、根据description构造:
| UiSelector | description(String desc) | 根据“控件content-desc属性的内容”构造出UiSelector对象 |
| UiSelector | descriptionContains(String desc) | 包含** |
| UiSelector | descriptionMatches(String regex) | 正则 |
| UiSelector | descriptionStartsWith(String desc) | 以**开始 |
同text的用法基本一致,也是比较靠谱的一种方式。
3、根据资源id:
| UiSelector | resourceId(String id) | 根据资源id获取对象,例如:UiSelector s = new UiSelector().resourceId("com.tencent.mm:id/b8m") |
| UiSelector | resourceIdMatches(String regex) | 根据资源id的正则表达式获取对象 |
4、根据类:
UiSelector className(String className):
根据控件的类名来找到UiSelector对象。
但是呢?因为一般Android布局的时候,同样的控件类名都是一样的。
因此我在微信的登录界面调用: UiSelector s = new UiSelector().className("android.widget.TextView") 这句话,它得到的就是我左上开始算第一个class名称为“android.widget.TextView”的控件。
UiSelector instance (int instance):
上面提到的假如我们想获取屏幕上电话号码的那个TextView使用这样方法,就可以使用instance:
UiSelector s = new UiSelector().className("android.widget.TextView").instance(1);
UiSelector index(int index):
用法和上面的instance差不多,谷歌的原文说这个方法是unreliable的,推荐使用instance方法。
UiSelector childSelector(UiSelector selector):
有的时候假如子控件不好获得,而其父控件比较好获得的时候,我们通常采用这样的方式,例如下面:

我们目前选中的是LinearLayout,这个Android中的一种布局,它的里面嵌套了两个控件,一个是ImageView,另一个是EditText。这们这里就通过LinearLayout这个控件找到它的子控件。
很明显,父控件id已经给定。我们先得到父控件:UiSelector s_p = new UiSelector().resourceId("com.tencent.mm:id/axj");
其次 UiSelector s_c= s_p.childSelector( new UiSelector().className("android.widget.EditText") );
在它的父控件的childSelector方法中传入一个带有一定特征的UiSelector对象,即可得到子控件,这里 s_c 就是输入框的UiSelector对象。
UiSelector fromParent(UiSelector selector):
有的时候父控件也不好获得,而是同级的控件(同属一个parent)比较好获取,那么使用这样方法,还拿上面的举例:
我们先得到EditText的UiSelector对象:UiSelector s1 = new UiSelector().resourceId("com.tencent.mm:id/axc");
得到和它同样一个父控件的ImageView的UiSelector对象:UiSelector s2 = fromParent( new UiSelector().className("android.widget.ImageView") );
5、根据特有属性:
| UiSelector | checked(boolean val) | 根据是否可check来构造出UiSelector对象 |
| UiSelector | chickable(boolean val) | |
| UiSelector | enabled(boolean val) | |
| UiSelector | focusable(boolean val) | |
| UiSelector | longClickable(boolean val) | |
| UiSelector | scrollable(boolean val) | |
| UiSelector | selected(boolean val) |
举个简单的例如,假如当前的界面,只有一个checkbox是勾选状态,你就可以这样得到:UiSelector s2 = new UiSelector().checked(true)
UiCollection
概述: 用的不多,直接参考文档
摘要: http://android.toolib.net/tools/help/uiautomator/UiCollection.html
UiScrollable
概述: 用的不多,直接参考文档
摘要: http://www.cnblogs.com/by-dream/p/4921701.html
UiObject
概述:可以理解为 直接操作界面ui元素的实例。
摘要:
|
返回值 |
函数 |
|
void |
ClearTextField() |
|
boolean |
click() |
|
boolean |
clickAndWaiForNewWindow(long timeout) |
|
boolean |
clickAndWaiForNewWindow() |
|
boolean |
clickBottomRight() |
|
boolean |
clickTopLeft() |
|
boolean |
exists() |
|
Rect |
getBounds() |
|
UiObject |
getChild(UiSelector selector) |
|
int |
getChildCount() |
|
String |
getContentDescription() |
|
UiObject |
getFromParent(UiSelector selector) |
|
String |
getPackageName() |
|
final UiSelector |
getSelector() |
|
String |
getText() |
|
Rect |
getVisibleBounds() |
|
boolean |
isCheckable() |
|
boolean |
isChecked() |
|
boolean |
isClickable() |
|
boolean |
isEnabled() |
|
boolean |
|
|
boolean |
isFocused() |
|
boolean |
isLongClickable() |
|
boolean |
isScrollable() |
|
boolean |
|
|
boolean |
|
|
boolean |
|
|
boolean |
|
|
boolean |
|
|
boolean |
|
|
boolean |
|
|
boolean |
|
|
boolean |
|
|
boolean |
|
|
boolean |
【Android测试】【第十二节】Uiautomator——API详解的更多相关文章
- Uiautomator ——API详解(转载http://www.cnblogs.com/by-dream/p/4921701.html)
转载来源: 简单的例子 以一个简单的例子开始吧.我们完成一个 " 打开QQ,进入QQ空间,然后退出 " 的case. 代码如下: package QQ; import java.i ...
- (转)Uiautomator——API详解
原文链接:http://www.cnblogs.com/by-dream/p/4921701.html#3328376 以一个简单的例子开始吧.我们完成一个 " 打开QQ,进入QQ空间,然后 ...
- Uiautomator ——API详解
版权声明:本文出自carter_dream的博客,转载必须注明出处. 转载请注明出处:http://www.cnblogs.com/by-dream/p/4921701.html 简单的例子 以一个简 ...
- [Android 测试] 压力稳定性测试之: Monkey 详解分析脚本(转载)
一.什么是稳定性测试? 通过随机点击屏幕一段时间,看看app会不会奔溃,能不能维持正常运行. 二. Money是什么? Monkey测试是Android平台自动化测试的一种手段,通过Monkey程序模 ...
- Android Developer -- Bluetooth篇 开发实例之四 API详解
http://www.open-open.com/lib/view/open1390879771695.html 这篇文章将会详细解析BluetoothAdapter的详细api, 包括隐藏方法, 每 ...
- --系统编程-网络-tcp客户端服务器编程模型、socket、htons、inet_ntop等各API详解、使用telnet测试基本服务器功能
PART1 基础知识 1. 字节序 网络字节序是大端字节序(低地址存放更高位的字节), 所以,对于字节序为小端的机器需要收发网络数据的场景,要对这些数据进行字节序转换. 字节序转换函数,常用的有四个: ...
- hibernate学习(2)——api详解对象
1 Configuration 配置对象 /详解Configuration对象 public class Configuration_test { @Test //Configuration 用户 ...
- 转】Mahout推荐算法API详解
原博文出自于: http://blog.fens.me/mahout-recommendation-api/ 感谢! Posted: Oct 21, 2013 Tags: itemCFknnMahou ...
- 百度地图API详解之事件机制,function“闭包”解决for循环和监听器冲突的问题:
原文:百度地图API详解之事件机制,function"闭包"解决for循环和监听器冲突的问题: 百度地图API详解之事件机制 2011年07月26日 星期二 下午 04:06 和D ...
随机推荐
- BZOJ4584 : [Apio2016]赛艇
首先将值域离散化成$O(n)$个连续段. 设$f[i][j][k]$表示第$i$个学校派出的数量在第$j$个连续段,在第$j$个连续段一共有$k$个学校的方案数.用组合数以及前缀和转移即可. 时间复杂 ...
- [转]基于gulp和webpack的前端工程化
本文样例代码 :https://github.com/demohi/learning-gulp 本文主要简单介绍一下基于gulp和webpack的前端工程化. 技术栈 React.js reFlux ...
- gulp顺序执行任务
gulp的任务的执行是异步的. 所以,当我写完一系列的任务,准备一股脑地执行. # gulp.task('prod', ['clean', 'compass', 'image', 'style', ' ...
- ajax与HTML5 history pushState/replaceState实例
一.本文就是个实例展示 三点: 我就TM想找个例子,知道如何个使用,使用语法什么的滚粗 跟搜索引擎搞基 自己备忘 精力总是有限的,昨天一冲动,在上海浦东外环之外订了个90米的房子,要借钱筹首付.贷款和 ...
- ACM: Billboard 解题报告-线段树
Billboard Time Limit:8000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u Descript ...
- 【CodeVS】p1038 一元三次方程求解
题目描述 Description 有形如:ax3+bx2+cx+d=0 这样的一个一元三次方程.给出该方程中各项的系数(a,b,c,d 均为实数),并约定该方程存在三个不同实根(根的范围在-100 ...
- BZOJ4556: [Tjoi2016&Heoi2016]字符串
Description 佳媛姐姐过生日的时候,她的小伙伴从某东上买了一个生日礼物.生日礼物放在一个神奇的箱子中.箱子外边写了 一个长为n的字符串s,和m个问题.佳媛姐姐必须正确回答这m个问题,才能打开 ...
- SolrCloud-5.2.1 集群部署及测试
一. 说明 Solr5内置了Jetty服务,所以不用安装部署到Tomcat了,网上部署Tomcat的资料太泛滥了. 部署前的准备工作: 1. 将各主机IP配置为静态IP(保证各主机可以正常通信,为避免 ...
- Linux查看操作系统时间
date命令的功能是显示和设置系统日期和时间. 该命令的一般格式为: date [选项] 显示时间格式(以+开头,后面接格式) date 设置时间格式 命令中各选项的含义分别为: -d datestr ...
- 注解@PostConstruct与@PreDestroy讲解及实例
从Java EE 5规范开始,Servlet中增加了两个影响Servlet生命周期的注解(Annotion):@PostConstruct和@PreDestroy.这两个注解被用来修饰一个非静态的vo ...