因为工作需要,使用到UIAutomator2中watcher(观察者)的功能,在官方文档查阅后,觉得对我个人来说有些不够直接,所以在本地尝试的基础上,将watcher的功能进行介绍如下,如若存在纰漏请您指出。【文末附有Watcher的官方文档】
* 本篇文章整理的时候基于uiautomator2 0.3.3,现在已经是2.0.0了,不过功能应当还是适配的,阅读时请尽可能参考官方文档
* 2020.04.13 uiautomator2最新文档里面,watchers已经都替换为watcher了,使用时请注意,以下内容为保持一致性,暂不修改
一、watcher是什么
与大多语言一样,watcher是一个观察者,它可以检测到设备页面中的变化,比如某个文本/描述/类名等的出现或者改变,然后进行下一步的点击/按钮操作
二、watcher怎么用
Step.1 注册一个watcher
d.watcher("WATCHER_NAME").when(text="确认").click(text="确认")
# Same as
d.watcher("ALERT").when(text="OK").click()
这句话表示:注册一个名字为“WATCHER_NAME”的watcher,当存在UiSelector满足“text='确认'”的时候,执行点击操作
d.watcher("WATCHER_NAME2").when(text="OK").when(text="Wait").press("back", "home")
下面这句则表示:注册一个名字为“WATCHER_NAME2”的watcher,当满足两个条件时,依次按back与home键
Step.2 watcher注册了,并不代表已经生效,需要手动开启它
开启方法(1)
# enable auto trigger watchers
d.watchers.watched = True
使用这种方法,则会启动所有的观察者,并一直运行在手机后台,在你不想使用它的时候,需要使用d.watchers.watched = False手动关闭;当然,你也可以使用下方的remove方法移除某个watcher,如此它便不会再生效
开启方法(2)
# force to run all registered watchers
d.watchers.run()
使用d.watchers.run(),则与方法(1)不同,它是在这条命令执行的瞬时启动一次,结束后便不会再触发
其他功能
1. 查看当前所有watcher(当然要搭配print使用啦)
d.watchers
# a list of all registered watchers
2. 从已注册的watchers移除某个/全部观察者
# remove the named watcher
d.watcher("watcher_name").remove()
# or this way
d.watchers.remove("watcher_name")
# remove all registered watchers
d.watchers.remove()
3. 判断 某个/所有观察者中的某个 是否已经被触发过
d.watcher("watcher_name").triggered
# true in case of the specified watcher triggered, else false
d.watchers.triggered
# true in case of any watcher triggered
如果一个watcher被触发过,这个信息经过我本地测试 应当也是被存储在手机后台的,你需要使用d.watchers.reset()来重置
# reset all triggered watchers, after that, d.watchers.triggered will be false.
d.watchers.reset()
三、watcher使用案例
watcher的设计思路主要是为了解决一些 弹窗 或者 确认框 问题,比如需要点击“确定”、“下一步”、“允许”等,这里我以 手机自动挂断功能 为例来展示watcher的简单使用:
(1)如果是使用d.watchers.watched = True,那么你可以先执行脚本,结束后再进行呼叫,来测试watcher是不是运行在手机后台
import uiautomator2 as u2
# 连接被叫设备
d = u2.connect('******')
# 注册一个名字为"DECLINE"的watcher,当存在UiSelector的description="拒绝"时,点击
d.watcher("DECLINE").when(description="拒绝").click()
# 查看DECLINE是否已经 注册 且 触发过
print("Triggered 1:", d.watcher("DECLINE").triggered)
# 启动方法1:后台启动,持续监控
d.watchers.watched = True
# d.watchers.watched = False
# 启动方法2:瞬时启动
# d.watchers.run()
# 查看DECLINE是否已经 注册 且 触发过
print("Triggered 2:", d.watcher("DECLINE").triggered)
# 重置watchers的triggered状态
d.watchers.reset()
# 重置后,查看DECLINE是否已经 注册 且 触发过
print("Triggered 3:", d.watcher("DECLINE").triggered)
# 查看当前已经注册的watchers
print("Watchers 1:", d.watchers)
# 移除DECLINE这个watcher
# d.watcher("DECLINE").remove()
# 移除后,查看当前已经注册的watchers
# print("Watchers 2:", d.watchers)
首先运行脚本后结果如下:
然后我们进行拨打电话,会发现被叫主动拒接电话。
之后,我们再次运行脚本,可以看到,因为刚才成功触发了watcher,triggered变为了True:
另外,如果你想要这个watcher失效,需要手动触发d.watchers.watched=False,或者移除d.watcher("DECLINE").remove()
(2)如果是使用d.watchers.run(),则需要在电话已经处于呼叫的过程中,触发脚本
import uiautomator2 as u2
# 连接被叫设备
d = u2.connect('******')
# 注册一个名字为"DECLINE"的watcher,当存在UiSelector的description="拒绝"时,点击
d.watcher("DECLINE").when(description="拒绝").click()
# 查看DECLINE是否已经 注册 且 触发过
print("Triggered 1:", d.watcher("DECLINE").triggered)
# 启动方法1:后台启动,持续监控
# d.watchers.watched = True
# d.watchers.watched = False
# 启动方法2:瞬时启动
d.watchers.run()
# 查看DECLINE是否已经 注册 且 触发过
print("Triggered 2:", d.watcher("DECLINE").triggered)
# 重置watchers的triggered状态
d.watchers.reset()
# 重置后,查看DECLINE是否已经 注册 且 触发过
print("Triggered 3:", d.watcher("DECLINE").triggered)
# 查看当前已经注册的watchers
print("Watchers 1:", d.watchers)
# 移除DECLINE这个watcher
d.watcher("DECLINE").remove()
# 移除后,查看当前已经注册的watchers
print("Watchers 2:", d.watchers)
对于上面这份代码(),直接运行后的结果为:
而如果在进行电话呼叫时,运行脚本的结果如下。另外,在脚本运行的时刻,成功拒接电话
================================================================
Watcher官方文档内容如下:(源自:https://github.com/openatx/uiautomator2)
Watcher
You can register watchers to perform some actions when a selector does not find a match.
- Register Watcher
When a selector can not find a match, uiautomator2 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.
There is also a trick about click. You can use click without arguments.
d.watcher("ALERT").when(text="OK").click()
# Same as
d.watcher("ALERT").when(text="OK").click(text="OK")
- Press key when a condition becomes true
d.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.
- Check if the named watcher triggered
A 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 a named watcher
# remove the watcher
d.watcher("watcher_name").remove()
- List all watchers
d.watchers
# a list of all registered watchers
- Check for any triggered watcher
d.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()
- Remove watchers
# remove all registered watchers
d.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 watchers
d.watchers.run()
- Run all watchers when page update.
通常可以用来自动点击权限确认框,或者自动安装
d.watcher("OK").when(text="OK").click(text="OK")
# enable auto trigger watchers
d.watchers.watched = True
# disable auto trigger watchers
d.watchers.watched = False
# get current trigger watchers status
assert d.watchers.watched == False