UiAutomator源码学习(1)-- UiDevice
UiDevice提供对设备状态信息的访问。 也可以使用此类来模拟设备上的用户操作,例如按键盘或按Home和Menu按钮。UiDevice类的完整源码 UiDevice.java
废话不多说,我们首先根据用法来来看看Android Uiautomator 访问设备的原理。
device = UiDevice.getInstance(getInstrumentation());
device.pressHome(); // Bring up the default launcher by searching for a UI component
// that matches the content description for the launcher button.
UiObject allAppsButton = device
.findObject(new UiSelector().description("Apps")); // Perform a click on the button to load the launcher.
allAppsButton.clickAndWaitForNewWindow();
根据这个用法实例,我们先看一下它的构造函数:
/** Private constructor. Clients should use {@link UiDevice#getInstance(Instrumentation)}. */
private UiDevice(Instrumentation instrumentation) {
mInstrumentation = instrumentation;
UiAutomation uiAutomation = instrumentation.getUiAutomation();
mUiAutomationBridge = new InstrumentationUiAutomatorBridge(
instrumentation.getContext(), uiAutomation);
// Enable multi-window support for API level 21 and up
if (UiDevice.API_LEVEL_ACTUAL >= Build.VERSION_CODES.LOLLIPOP) {
// Subscribe to window information
AccessibilityServiceInfo info = uiAutomation.getServiceInfo();
info.flags |= AccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS;
uiAutomation.setServiceInfo(info);
}
}
/**
* Retrieves a singleton instance of UiDevice
*
* @return UiDevice instance
*/
public static UiDevice getInstance(Instrumentation instrumentation) {
if (sInstance == null) {
sInstance = new UiDevice(instrumentation);
}
return sInstance;
}
这是一个单例模式的类,负责创建自己的对象,以确保UiDevcie对象的唯一性。在构造方法中除了初始化唯一的uiDevice对象,还初始化了UiAutomoatorBridge对象。UiAutomatorBridge这个类非常的重要,获取设备界面信息、注入事件以及截图都需要经过UiAutomatorBridge。稍后会做详细的介绍。
接下来我们来看,是如何获取设备信息以及模拟用户操作的。
/**
* Returns the display size in dp (device-independent pixel)
*
* The returned display size is adjusted per screen rotation. Also this will return the actual
* size of the screen, rather than adjusted per system decorations (like status bar).
*
* @return a Point containing the display size in dp
*/
public Point getDisplaySizeDp() {
Tracer.trace();
Display display = getAutomatorBridge().getDefaultDisplay();
Point p = new Point();
display.getRealSize(p);
DisplayMetrics metrics = new DisplayMetrics();
display.getRealMetrics(metrics);
float dpx = p.x / metrics.density;
float dpy = p.y / metrics.density;
p.x = Math.round(dpx);
p.y = Math.round(dpy);
return p;
}
getDisplaySizeDp()方法返回的是一个以dp为单位的坐标点。同样可以获取设备的宽度或者高度:
/**
* Gets the width of the display, in pixels. The width and height details
* are reported based on the current orientation of the display.
* @return width in pixels or zero on failure
*/
public int getDisplayWidth() {
Display display = getDefaultDisplay();
Point p = new Point();
display.getSize(p);
return p.x;
}
以上都是设备属性,接下来看模拟用户的操作。操作的第一步就是获取屏幕的焦点。获取到UiObject后就可以对屏幕上的这些控件进行模拟用户操作。
/**
* Returns a UiObject which represents a view that matches the specified selector criteria.
*
* @param selector
* @return UiObject object
*/
public UiObject findObject(UiSelector selector) {
return new UiObject(this, selector);
}
获取到屏幕上布局对象以后,操作无外乎就是点击、长按、滑动 以及键盘等操作。
/**
* Simulates a short press on the HOME button.
* @return true if successful, else return false
* @since API Level 16
*/
public boolean pressHome() {
Tracer.trace();
waitForIdle();
return getAutomatorBridge().getInteractionController().sendKeyAndWaitForEvent(
KeyEvent.KEYCODE_HOME, 0, AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED,
KEY_PRESS_EVENT_TIMEOUT);
} /**
* Perform a click at arbitrary coordinates specified by the user
*
* @param x coordinate
* @param y coordinate
* @return true if the click succeeded else false
* @since API Level 16
*/
public boolean click(int x, int y) {
Tracer.trace(x, y);
if (x >= getDisplayWidth() || y >= getDisplayHeight()) {
return (false);
}
return getAutomatorBridge().getInteractionController().clickNoSync(x, y);
}
/**
* Performs a swipe from one coordinate to another using the number of steps
* to determine smoothness and speed. Each step execution is throttled to 5ms
* per step. So for a 100 steps, the swipe will take about 1/2 second to complete.
*
* @param startX
* @param startY
* @param endX
* @param endY
* @param steps is the number of move steps sent to the system
* @return false if the operation fails or the coordinates are invalid
* @since API Level 16
*/
public boolean swipe(int startX, int startY, int endX, int endY, int steps) {
Tracer.trace(startX, startY, endX, endY, steps);
return getAutomatorBridge().getInteractionController()
.swipe(startX, startY, endX, endY, steps);
}
不难看出,所有的操作都离不开 uiAutomatorBridge。在该类的方法getInteractionController()获取InteractionController 对象。InteractionController类将用户的键盘事件注入到android系统中,与系统进行交互。稍后会做详细的介绍。
除了这些操作,UiDevice还提供了其他的方法,如打开通知栏、点亮屏幕、执行adb命令、检查电源管理器,屏幕是否打开、等待屏幕更新、获取当前窗口的布局层次结构、截图等。
UiAutomator源码学习(1)-- UiDevice的更多相关文章
- UiAutomator源码学习(2)-- UiAutomationBridge
从上一章对UiDevice的学习,可以看出几乎所有的操作都离不开 UiAutomationBridge.重新看一下UIDevice的构造方法: private UiDevice(Instrumenta ...
- UiAutomator源码分析之UiAutomatorBridge框架
上一篇文章<UIAutomator源码分析之启动和运行>我们描述了uitautomator从命令行运行到加载测试用例运行测试的整个流程,过程中我们也描述了UiAutomatorBridge ...
- UiAutomator源码分析之获取控件信息
根据上一篇文章<UiAutomator源码分析之注入事件>开始时提到的计划,这一篇文章我们要分析的是第二点: 如何获取控件信息 我们在测试脚本中初始化一个UiObject的时候通常是像以下 ...
- UiAutomator源码分析之注入事件
上一篇文章<UiAutomator源码分析之UiAutomatorBridge框架>中我们把UiAutomatorBridge以及它相关的类进行的描述,往下我们会尝试根据两个实例将这些类给 ...
- Java集合专题总结(1):HashMap 和 HashTable 源码学习和面试总结
2017年的秋招彻底结束了,感觉Java上面的最常见的集合相关的问题就是hash--系列和一些常用并发集合和队列,堆等结合算法一起考察,不完全统计,本人经历:先后百度.唯品会.58同城.新浪微博.趣分 ...
- jQuery源码学习感想
还记得去年(2015)九月份的时候,作为一个大四的学生去参加美团霸面,结果被美团技术总监教育了一番,那次问了我很多jQuery源码的知识点,以前虽然喜欢研究框架,但水平还不足够来研究jQuery源码, ...
- MVC系列——MVC源码学习:打造自己的MVC框架(四:了解神奇的视图引擎)
前言:通过之前的三篇介绍,我们基本上完成了从请求发出到路由匹配.再到控制器的激活,再到Action的执行这些个过程.今天还是趁热打铁,将我们的View也来完善下,也让整个系列相对完整,博主不希望烂尾. ...
- MVC系列——MVC源码学习:打造自己的MVC框架(三:自定义路由规则)
前言:上篇介绍了下自己的MVC框架前两个版本,经过两天的整理,版本三基本已经完成,今天还是发出来供大家参考和学习.虽然微软的Routing功能已经非常强大,完全没有必要再“重复造轮子”了,但博主还是觉 ...
- MVC系列——MVC源码学习:打造自己的MVC框架(二:附源码)
前言:上篇介绍了下 MVC5 的核心原理,整篇文章比较偏理论,所以相对比较枯燥.今天就来根据上篇的理论一步一步进行实践,通过自己写的一个简易MVC框架逐步理解,相信通过这一篇的实践,你会对MVC有一个 ...
随机推荐
- airpods2隐藏的使用技巧(十)点
airpods的凭借出色的外观.不错的音质以及非常人性化的用户体验秒杀了同类型的许多真无线蓝牙耳机,以下是第二代产品airpods2一些使用的技巧,推荐给大家. 一. 随时随地查看airpods2 ...
- Python模拟用户登录场景
简单模拟登录场景,将已知的用户名及密码固化,通过用户输入内容和已固化的内容比较进行判断用户名和密码是否输入正确. 在用户输入时,将密码隐藏需要导入模块getpass import getpass _u ...
- 【 转】百度地图Canvas实现十万CAD数据秒级加载
Github上看到: https://github.com/lcosmos/map-canvas 这个实现台风轨迹,这个数据量非常庞大,当时打开时,看到这么多数据加载很快,感到有点震惊,然后自己研究了 ...
- c常用函数-sprintf
sprintf sprinti函数的作用是把一个字符串格式化后输入到另一个字符串中,然后返回写入的·字符数量. Sprinf在用法上和1.2.3节的prinf函数一致,区别是sprintf输出结果到指 ...
- 附024.Kubernetes_v1.18.3高可用部署架构二
kubeadm介绍 kubeadm概述 参考<附003.Kubeadm部署Kubernetes>. kubeadm功能 参考<附003.Kubeadm部署Kubernetes> ...
- 涨姿势了解一下Kafka消费位移可好?
摘要:Kafka中的位移是个极其重要的概念,因为数据一致性.准确性是一个很重要的语义,我们都不希望消息重复消费或者丢失.而位移就是控制消费进度的大佬.本文就详细聊聊kafka消费位移的那些事,包括: ...
- VS Code WebApi系列——1、配置
Knowledge should be Shared in Free. 最近在研究VS code下的webapi,看了很多文档,还是微软官方的例子好,不过不太适应国人习惯,所以写点东西. 直接了当 开 ...
- router-view中绑定key='$route.fullPath'
原文链接https://www.jianshu.com/p/cf2fb443620f 来源:简书 作者:myzony 不设置 router-view 的 key 属性 由于 Vue 会复用相同组件, ...
- c++. Run-Time Check Failure #2 - Stack around the variable 'cc' was corrupted.
Run-Time Check Failure #2 - Stack around the variable 'cc' was corrupted. char cc[1024]; //此处如果索引值 ...
- Matlab 常用语法速记 1
===快捷帮助=== 查找帮助:doc 函数名 强制终止: ctrl + c 注释: % 清屏 clc,清临时变量窗口 clear NaN: not a number inf: infinite == ...