Android之UI Automator框架源码分析(第九篇:UiDevice获取UiAutomation对象的过程分析)

前言

    学习UiDevice对象,就需要看它的构造方法,构造方法中有UiDevice对象持有一些对象,每个对象都是我们分析程序的重点,毕竟UiDevice对象的功能,依赖这些组合的对象

    备注:当前对象持有的对象,初始化的位置一般在实例变量创建时或者构造方法中,以下是UiDevice构造方法中正在做初始化对象的代码!

UiDevice(Instrumentation instrumentation) {mInstrumentation = instrumentation;mQueryController = new QueryController(instrumentation);mInteractionController = new InteractionController(instrumentation);// Enable multi-window support for API level 21 and upif (UiDevice.API_LEVEL_ACTUAL >= Build.VERSION_CODES.LOLLIPOP) {// Subscribe to window informationAccessibilityServiceInfo info = getUiAutomation().getServiceInfo();info.flags |= AccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS;getUiAutomation().setServiceInfo(info);}
}

 UiAutomation对象很重要

        我们看到getUiAutomation()方法在UiDevice构造方法中的调用 

AccessibilityServiceInfo info = getUiAutomation().getServiceInfo(); info.flags |= AccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS; getUiAutomation().setServiceInfo(info);

getUiAutomatrion()方法分析

位于UiDevice类中的getUiAutomation()方法,返回值是UiAutomation对象

    UiAutomation getUiAutomation() {return getUiAutomation(getInstrumentation());}

1、先调用一个getInstrumentation()方法

该方法返回的Instrumentation对象会再被传入到接受一个参数的getUiAutomation重载方法中

2、再次调用重载的getUiAutomation()方法

3、此重载方法的返回值将作为当前getUiAutomation()方法的返回值

我们先学习一下Instrumentation对象是如何获取到的,即getInstrumentation()的调用!

getInstrumentation()方法分析

    位于UiDevice中的getInstrumentation方法,返回值为Instrumentation对象

    Instrumentation getInstrumentation() {return mInstrumentation;}

    通过该方法就可以得到UiDevice对象持有的Instrumentation对象mInstrumentation,方法内部通过return语句返回mInstrumentation,说明Instrumentation对象已经初始化结束,这里只是返回

Instrumentation对象在哪初始化的

    通过代码得知,是创建UiDevice的时候,传入的一个Instrumentation对象

创建UiDevice对象

public static final UiDevice mDevice = UiDevice.getInstance(getInstrumentation());

这时候传入的其实是InstrumentationRegistry下的静态方法getInstrumentation()返回的Instrumenation对象。

public static Instrumentation getInstrumentation() {Instrumentation instance = instrumentationRef.get();if (null == instance) {throw new IllegalStateException("No instrumentation registered! " + "Must run under a registering instrumentation.");}return instance;
}

一个原子对象负责持有Instrumentation对象

找到了原子对象赋值的地方

我们需要找到registerInstance这个静态方法在哪里被调用即可

在MonitoringInstrumentation对象中的oncreate()方法中调用了

MonitoringInstrumentation对象,从名字上,果然是Instrumentation的子类,它是具体的对象,代码追踪到这里,只要再找到这个oncreate()方法在哪里调用即可!

很快找到了,追踪了整个Unit框架了都要

AndroidJUnitRunner是MonitoringInstrumentation的子类,看来AndroidJUnitRunner也是个Instrumentation!!

AndroidUnitRunner作为入口类

我们是在am instrument 指定的该类,这一切明白了,这个用到的Instrumentation对象,其实就是AndroidUnitRunner对象

$ADB shell am instrument -w -e class com.xxx.camauto.Common#unlockScreen com.xiaomi.camauto.test/androidx.test.runner.AndroidJUnitRunner

重载的静态方法getUiAutomation(Instrumentation)方法分析

位于UiDevice类中的静态方法getUiAutomation(),它接受一个Instrumentation对象,最后会返回一个UiAutomation对象

    static UiAutomation getUiAutomation(final Instrumentation instrumentation) {int flags = Configurator.getInstance().getUiAutomationFlags();if (UiDevice.API_LEVEL_ACTUAL > Build.VERSION_CODES.M) {return instrumentation.getUiAutomation(flags);} else {// Custom flags not supported prior to N.if (flags != Configurator.DEFAULT_UIAUTOMATION_FLAGS) {Log.w(LOG_TAG, "UiAutomation flags not supported prior to N - ignoring.");}return instrumentation.getUiAutomation();}}

1、获取配置对象中的UiAutomation的标志位

首先通过Configurator对象的getUiAutomationFlags方法,得到一个int值,该值的初始值是0,然后再将该int值赋值给局部变量flags存储,flags存储的是关于UiAutomatrion对象的标志位(说明:Configurator对象存储着UI Automator测试框架用到的各种配置信息,此时局部变量flags存储的值正是从Configurator对象中获得,后面单独文章总结)

2、系统版本大于API 23获取UiAutomation对象的方式

接着做API版本判断,UiDevice类持有的API_LEVEL_ACTUAL代表API版本,根据API版本执行不同的逻辑

当API版本大于M(API==23)时,使用的传入的Instrumentation对象的接受一个整型参数的getUiAutomation()方法,此时会将局部变量flags传入进去,getUiAutomation(int)方法返回的是一个UiAutomation对象(看这个flags决定了获取对象的不同)

3、系统版本小于等于API 23获取UiAutomation对象的方式

当API版本小于等于M(API==23)时,使用的是传入的Instrumentation对象的无参数的getUiAutomation()方法,该方法也会返回一个UiAutomation对象

说明:最终getUiAutomation()方法中依赖Instrumentaion对象获取到的UiAutomation对象

找到具体的UiAutomation对象

    从前面的步骤得知这个Instumentation对象其实是AndroidJUnitRunner,而调用的getUiAutomation()获取到的UiAutomation()对象,由于java是单继承,我们只要沿着AndroidJunitRunner的继承树, 找到getUiAutomation()方法,就能知道具体的UiAutomation对象在哪里创建的!!

1、先从AndroidJunitRunner中找getUiAutomation()方法,发现该类没有该方法

2、只能继续从它的父类MonitoringInstrumentation中找getUiAutomation()方法,这是面向对象程序的特点,记住了各位,结果还是没有这个方法

3、继续从它的父类ExposedInstumentationApi中查找,发现还是没有

4、继续从父类Instrumentation中查找,总算找到了

原来是UiAutomation对象,必须创建的时候才会创建,必须创建是指:没创建与已经销毁

可以看到把当前App上下文的主线程Looper对象传递进去了

总结

1、追踪了一圈,也知道UiAutomation对象是在哪里创建!

2、面向对象程序,子类找不到的方法,按照继承结构,继续向上找就对了。。 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/267372.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

leedcode刷题--day7(字符串)

23 文章讲解 力扣地址 C class Solution { public:void reverseString(vector<char>& s) {int left 0;int right s.size() - 1; // right 应该初始化为 s.size() - 1while (left < right) {swap(s[left], s[right]); // 直接交换 s[left] 和 s[right] 的值lef…

蓝桥杯-单片机组基础5——外部中断与LED的控制(附小蜜蜂课程代码)

蓝桥杯单片机组备赛指南请查看这篇文章&#xff1a;戳此跳转蓝桥杯备赛指南文章 本文章针对蓝桥杯-单片机组比赛开发板所写&#xff0c;代码可直接在比赛开发板上使用。 型号&#xff1a;国信天长4T开发板&#xff08;绿板&#xff09;&#xff0c;芯片&#xff1a;IAP15F2K6…

Excel常用公式总结非常实用

16个最实用的Excel万能公式 1、多条件判断 IF(And(条件1,条件2..条件N),条件成立返回值) IF(or(条件1,条件2..条件N),条件成立返回值) 2、多条件查找 Lookup(1,0/((条件1*条件2*...条件N)),返回值区域&#xff09; 3、多条件求和 Sumifs(值区域,判断区域1,条件1,判断区域2,条…

1_SQL

文章目录 前端复习SQL数据库的分类关系型数据库非关系型数据库&#xff08;NoSQL&#xff09; 数据库的构成软件架构MySQL内部数据组织方式 SQL语言登录数据库数据库操作查看库创建库删除库修改库 数据库中表的操作选择数据库创建表删除表查看表修改表 数据库中数据的操作添加数…

GO—函数

Go 语言支持普通函数、匿名函数和闭包&#xff0c;从设计上对函数进行了优化和改进&#xff0c;让函数使用起来更加方便。 Go 语言的函数属于“一等公民”&#xff08;first-class&#xff09;&#xff0c;也就是说&#xff1a; 函数本身可以作为值进行传递。支持匿名函数和闭…

Android 混淆是啥玩意儿?

什么是混淆 Android混淆&#xff0c;是伴随着Android系统的流行而产生的一种Android APP保护技术&#xff0c;用于保护APP不被破解和逆向分析。简单的说&#xff0c;就是将原本正常的项目文件&#xff0c;对其类、方法、字段&#xff0c;重新命名a,b,c…之类的字母&#xff0c…

假如有n个台阶,一次只能上1个台阶或2个台阶,请问走到第n个台阶有几种走法?

说明如下:假如有 3个台阶&#xff0c;那么总计就有3种走法:第一种为每次上1个台阶&#xff0c;上3次;第二种为先上2个台阶&#xff0c;再上1个台阶;第三种为先上1个台阶&#xff0c;再上2个台阶。 解决方法&#xff1a;递归 代码展示&#xff1a; #include <stdio.h> …

SD NAND:为车载显示器注入智能与安全的心脏

SD NAND 在车载显示器的应用 在车载显示器上&#xff0c;SD NAND&#xff08;Secure Digital NAND&#xff09;可以有多种应用&#xff0c;其中一些可能包括&#xff1a; 导航数据存储&#xff1a; SD NAND 可以用于存储地图数据、导航软件以及车载系统的相关信息。这有助于提…

【Vue3】插槽使用和animate使用

插槽使用 插槽slot匿名插槽具名插槽插槽作用域简写 动态插槽transition动画组件自定义过渡class类名如何使用animate动画库组件动画生命周期appear transition- group过渡列表transition- group平面过渡代码展示 gsap动画库 状态过渡 插槽slot 插槽就是子组件中提供给父组件使…

备战蓝桥杯---状态压缩DP进阶题1

我们来看一看一道比较难的问题&#xff08;十分十分的巧妙&#xff09;&#xff1a; 显然我们应该一行一行放&#xff0c;又竖的会对下一行产生影响&#xff0c;我们令横着放为0&#xff0c;竖着放的上方为1. 对于下一行&#xff0c;前一行放1的下面为0&#xff0c;但是会出现…

Python 实现Excel自动化办公(中)

在上一篇文章的基础上进行一些特殊的处理&#xff0c;这里的特殊处理主要是涉及到了日期格式数据的处理&#xff08;上一篇文章大家估计也看到了日期数据的处理是不对的&#xff09;以及常用的聚合数据统计处理&#xff0c;可以有效的实现你的常用统计要求。代码如下&#xff1…

Python爬虫——Urllib库-2

编解码 问题引入 例如&#xff1a; https://www.baidu.com/s?wd章若楠 https://www.baidu.com/s?wd%E7%AB%A0%E8%8B%A5%E6%A5%A0 第二部分的一串乱码就是章若楠 如果这里是写的章若楠就会 产生这样的错误 所以我们就可以使用get请求方式的quote方法了 get请求方式的q…

YOLOv9:使用可编程梯度信息学习您想学习的内容

摘要 arxiv.org/pdf/2402.13616.pdf 当今的深度学习方法侧重于如何设计最合适的目标函数,以便模型的预测结果能最接近于实际结果。同时,还必须设计一个适当的架构,以便于获取足够的预测信息。现有的方法忽略了一个事实,即当输入数据经历层层特征提取和空间变换时,会损失…

(学习日记)2024.02.29:UCOSIII第二节

写在前面&#xff1a; 由于时间的不足与学习的碎片化&#xff0c;写博客变得有些奢侈。 但是对于记录学习&#xff08;忘了以后能快速复习&#xff09;的渴望一天天变得强烈。 既然如此 不如以天为单位&#xff0c;以时间为顺序&#xff0c;仅仅将博客当做一个知识学习的目录&a…

BUGKU 本地管理员

打开环境&#xff0c;先F12查看看到一串代码。Base64解码一下&#xff0c;得到的应该是密码&#xff0c;然后输入admin | test123试一下 使用BP抓包&#xff0c;修改XFF&#xff0c;得到flag

社区分享|中华保险基于MeterSphere开展接口自动化测试

中华联合保险集团股份有限公司&#xff08;以下简称为“中华保险”&#xff09;始创于1986年&#xff0c;是全国唯一一家以“中华”冠名的国有控股保险公司。截至2022年12月底&#xff0c;中华保险总资产为1006.06亿元&#xff0c;在全国拥有超过2900个营业网点&#xff0c;员工…

破解SQL Server迷局,彻底解决“管道的另一端无任何进程错误233”

问题描述&#xff1a;在使用 SQL Server 2014的时候&#xff0c;想用 SQL Server 身份方式登录 SQL Servcer Manager&#xff0c;结果报错&#xff1a; 此错误消息&#xff1a;表示SQL Server未侦听共享内存或命名管道协议。 问题原因&#xff1a;此问题的原因有多种可能 管道…

SpringBoot整合JdbcTemplate

✅作者简介:大家好,我是Leo,热爱Java后端开发者,一个想要与大家共同进步的男人😉😉 🍎个人主页:Leo的博客 💞当前专栏: 循序渐进学SpringBoot ✨特色专栏: MySQL学习 🥭本文内容:SpringBoot整合JdbcTemplate 📚个人知识库: Leo知识库,欢迎大家访问 目录 …

openGauss学习笔记-232 openGauss性能调优-系统调优-资源负载管理-资源管理准备-资源规划

文章目录 openGauss学习笔记-232 openGauss性能调优-系统调优-资源负载管理-资源管理准备-资源规划 openGauss学习笔记-232 openGauss性能调优-系统调优-资源负载管理-资源管理准备-资源规划 完成资源负载管理功能配置前&#xff0c;需要先根据业务模型完成租户资源的规划。业…

fastjson反序列化漏洞

fastjson反序列化漏洞 文章目录 fastjson反序列化漏洞1.漏洞原理2.探测方式2.1 查看回显2.2 LDAP/RMI服务测试 3.LDAP/RMI服务搭建要求4.漏洞复现4.1 fastjson <1.2.47 反序列化导致任意命令执行漏洞4.1.1 环境准备4.1.2 复现过程 4.2 fastjson <1.2.24 反序列化导致任意…