Time will tell.
在前面的章节里,分享了通过获取控件坐标点来获取点击事件所需要的点击位置,那么还有其他获取控件点击事件所需要点击位置的方法吗?当然有。
在不同大小屏幕的手机上获取控件的坐标点,不是一样的。因此在不同的机型上需要重新获取坐标点。如果操作控件特别多,那么获取控件的坐标点就会特别繁琐。因此可以通过获取控件 ID 来避免获取控件坐标点的这种弊端。
控件 ID 的获取主要通过HierarchyViewer
,下面从打开和使用两方面进行讲解。
1、HierarchyViewer 打开方式
HierarchyViewer
的打开方式有两种:
一种是eclipse中打开HierarchyView视图;
第二种是命令行中执行sdk/tools/hierarchyviewer.bat。
HierarchyViewer
默认只能在非加密设备使用,例如工程机,工程平板或者模拟器。如果要在手机上使用HierarchyViewer
,你需要在你的应用中添加一个开源库View Server
。链接地址:https://github.com/romainguy/ViewServer ,里面有讲解如何启动真机View Server
。
方式一:
连接你的真机设备或打开模拟器,在 eclipse 中, 依次选择 Window - Open Perspective - Other,在 Other 中,选择HierarchyView
视图,即可打开。
方式二:
连接您的真机设备或打开模拟器,运行 cmd 窗口,进入到 sdk/tools 目录下,输入命令hierarchyviewer.bat
,运行hierarchyviewer
。
或直接在 sdk/tools 目录下,找到hierarchyviewer.bat
,双击运行。
未开启夜神模拟器的HierarchyViewer
:
开启夜神模拟器后的HierarchyViewer
:
2、HierarchyViewer 获取控件 ID
HierarchyViewer
启动后,首先会看到的第一个窗口显示了设备和模拟器的列表。点击左边的箭头,就会展开当前设备或模拟器的Activity
对象列表。列表中显示了设备或模拟器上, UI 当前可视的所有Activity
对象。
这些对象按照它们的 Android 组件名称列出来。列表中的内容包含应用的Activity
对象和系统的Activity
对象。
当模拟器Activity
画面变更后,点击refresh
可以加载新的页面布局信息。
从列表中选择你的 activity 名称,双击,或点击菜单栏的 Load View Hierarchy
按钮,进入View Hierarchy
窗口,查看它的view
层次结构;或者点击 Inspect Screenshot
按钮,进入Pixel Perfect
窗口,从而查看 UI 的一个放大图像。我们这里点击进入View Hierarchy
窗口。
从下图中看到模拟器此 activity 的画面布局信息,左边部分是hierarchy
通过树形结构展示的布局形式,右下角是模拟器上当前页面的 UI 布局信息。
通过滚动鼠标,可以放大每个树节点。拖拽鼠标,移动树形结构布局。双击树节点可以展示单独的 UI 部分。从下图中,可以看到,id/btn_login
即为登录按钮的 ID 。依次类推,可以查看其它控件 ID 。
对于列表、或者弹出框则无法直接通过点击 ID 操作成功,需要计算 ID 的坐标。
3、控件 ID 之 Monkeyrunner 脚本演示
同样,我们将下面一段 Monkeyrunner 脚本写到一个test.py
文件中,然后运行test.py
文件,查看模拟器上是不是做相应的操作。
# coding=utf-8
# 1.先设置编码,utf-8可支持中英文,如上,一般放在第一行
# 2.注释:包括记录创建时间,创建人,项目名称。
# 3.导入模块
from com.android.monkeyrunner import MonkeyRunner,MonkeyDevice
from com.android.monkeyrunner.easy import EasyMonkeyDevice #提供了根据ID进行访问
from com.android.monkeyrunner.easy import By #根据ID返回PyObject的方法
device=MonkeyRunner.waitForConnection()
#启动activity(这里启动qq)
device.startActivity(component="com.tencent.mobileqq/.activity.SplashActivity")
easy_device=EasyMonkeyDevice(device) #必须在activity启动之后
#登录界面,点击账号输入框
easy_device.touch(By.id('id/0x20e'),MonkeyDevice.DOWN_AND_UP)
device.type('721471592') #输入qq账号
至此,获取控件ID的方式已经介绍完,由于没有深入研究,肯定有不少功能点没有介绍到,有时间的话再做完善。
4、控件 ID 不存在或重复
在用 monkeyrunner 进行 Android 自动化时,通过获取坐标点或控件 ID 进行一系列操作。由于使用坐标点时,屏幕分辨率一旦更改,则代码中用到坐标的地方都要修改,这样导致代码的复用率较低。因此,我们多采用控件 ID 操作,注意控件 ID 需要在模拟器中使用,对于绝大多数真机不适用。但是,某些控件的 ID 是不存在的或重复存在,那么,遇到这种情况,我们怎样继续使用控件 ID 进行自动化测呢?
例如,下图中,我想要获取最右侧红框中的 id/tv ,但是,大家会发现,和它并列的也有重复的控件 id 值。现在我们就讲述一下这种情况(控件 ID 不存在同样处理)。
我们从这个控件树的节点角度来思考如何获得控件的引用。我们可以看到在上图hierarchy viewer
中的每个控件所对应的框形中,右下角都有一个数字。其实这个数字就是该控件在同级兄弟节点中的索引值,我们知道这个索引值后,就可以根据parentView.children[index]
属性来获取任意父节点所对应的子节点的对象引用。其中的parentView
可以是树形图中有效 ID 的任意父节点(父节点要保证唯一有效),然后利用python
函数的可变参数列表特性来传入所需控件的索引列表即可构造出得到任意节点引用的字符串,从而得到其引用。
核心代码如下,把如下代码加入自己的 python 脚本中,直接调用该函数即可。
#定义获取重复或不存在控件id,寻找子节点函数
def getChildView(parentId, *childSeq):
hierarchyViewer = device.getHierarchyViewer()
childView="hierarchyViewer.findViewById('" + parentId +"')"
for index in childSeq:
childView += ('.children[' + str(index) + ']')
print childView
return eval(childView)
#获取id的文本
def getText(view):
if view != None:
return (view.namedProperties.get('text:mText').value)
有了以上代码之后,我们可以获取上图中的 id/tv ,方法如下:
getChildView('id/province_list',5,0,0)
其中结合上图可知,getChildView
的第一个参数即:有效且唯一的父节点
参数二、三依次为要获取的控件 ID 的父节点的父节点
注:用到的父节点即图中的id/province_list
,有效且唯一的值。当前的父节点右下角的角标,不需要在getChildView
函数中显示。
这样,通过以上函数,再结合Hierarchyviewer
图形,我们获取到了重复的控件ID。
由于Hierarchyviewer
看起来不是特别方便,这里再推荐一款和Hierarchyviewer
类似功能的工具:uiautomatorviewer(存储在sdk\tools
中,双击打开即可)。
由上图中,uiautomatorviewer
每个控件前面的数字即相当于Hierarchyviewer
的角标,我们同样可以获取到目标 ID 的最终有效且唯一的父节点,从而调用函数getChildView('id/province_list',5,0,0)
获取到了不存在或重复的控件 ID 后,我们可以通过其坐标,进行点击操作。
首先,定义一个 “获取指定按钮坐标” 的函数
def getBtnPoint(btn):
print btn
point = device.getHierarchyViewer().getAbsoluteCenterOfView(btn);
return point
然后我们可以通过坐标,实现点击操作,例如:
askView = getChildView('id/tabs',1)
askPpoint = getBtnPoint(askView)
device.touch(askPpoint.x,askPpoint.y,'DOWN_AND_UP')
至此,我们介绍完了处理控件 ID 不存在或重复时的方法,有兴趣的小伙伴或者童鞋们可以自己动手实践一把,就会更能体会Hierarchyviewer/uiautomatorviewer
+ getChildView()
获取不存在或重复控件 ID 的用法、乐趣及其奥秘。
大概意思是说,单独版本的hieararchyviewer
已经被弃用了。请使用 Android Device Monitor 来代替。Android Device Monitor 在 tools 目录下面找到monitor.bat
即可。
为了紧跟时代潮流,就决定用 Android Device Monitor 启动即可。
具体操作启动步骤:
1、运行命令monitor.bat
,如下:
2、运行命令后出现,如下:
3、点击 “Window->Open Perspective” 。如图:
4、按第三步操作完以后,出现如下:
5、选择“hieararchyviewer ”,点击“OK” 即可,如下:
如何在真机上正常使用Hierarchy View
Hierarchy Viewer
如果不进行 “特殊” 配置的话是无法连接真机,会报以下错误:
[hierarchyviewer]Unable to get view server version from device XXXXX
[hierarchyviewer]Unable to get view server protocol version from device XXXXXX
[ViewServerDevice]Unable to debug device: XXXXX
[hierarchyviewer]Missing forwarded port for XXXXX
[hierarchyviewer]Unable to get the focused window from device XXXXX
无法连接真机的原因是:To preserve security, Hierarchy Viewer can only connect to devices running a developer version of the Android system.
出于安全性考虑, Hierarchy Viewe
只能连接开发版手机或模拟器。
Android 源码实现这一限制的地方在 /frameworks/base/services/core/java/com/android/server/wm/WindowManageService.java :
检验一台手机/模拟器是否开启了View Server
的办法是:
adb shell service call window 3
若返回值是:Result: Parcel(00000000 00000000 '........')" 说明View Server处于关闭状态
若返回值是:Result: Parcel(00000000 00000001 '........')" 说明View Server处于开启状态
有时碰到模拟器或开发发版手机,view Hierarchy
还是无法连接,可以先使用以上方法检查一下View Server
状态。如果没有开启,则使用以下命令打开View Server
:
adb shell service call window 1 i32 4939
也可以使用使用以下命令关闭View Server:
adb shell service call window 2 i32 4939
那么如何在真机能够正常使用Hierarchy Viewer
呢?这里总结了以下几个方法:
方法一:
配置设备,打开手机的开发者选项。
如果你的手机是 android 4.0 或者以下,请根据开源项目 View Server(https://github.com/romainguy/ViewServer) 进行安装和配置。
如果你的手机是4.1或以上,则必须进行以下环境变量配置:
点击 计算机属性-》高级系统设置-》环境变量
新建环境变量
ANDROID_HVPROTO
, 并设置其值为ddm
,保存重启
该方法参考 android 官方文档《Device Setup for Hierachy Viewer》https://developer.android.com/studio/profile/hierarchy-viewer-setup.html
然而在亲自试用真机(魅族MX4pro android 5.1 和 android 4.4的机顶盒)测试过程中,配置环境变量的方法似乎并没有起到作用,还是连不上。
不过直接在调试 app 中集成 View Server 开源项目是没有任何问题的。
方法二:
话说前面Hierarchy Viewer
只能连接 Android 开发版手机或是模拟器,只有ro.secure==0 && ro.debuggable==1
的 Android 系统。ro.xxxx
这种句式是不是觉得有点熟悉?不就是 android 系统的/system/build.prop
文件中的配置样式么。推测如果将ro.secure==0 && ro.debuggable==1
这个两个配置添加进来应该能够起作用吧,于是进行以下尝试:
先把手机
root
在进到在
/system/build.prop
中添加ro.secure==0
和ro.debuggable==1
, 保存配置并重启手机,Hierarchy Viewer
连接正常,终于可以正常调试了。
好了,关于控件ID的获取就分享到这里。希望大家都能熟练掌握。如果你对Python自动化软件测试感兴趣可以加入我们扣裙一起学习175317069。有各项测试学习资源,也有行业深潜多年的技术人分析讲解。
欢迎【点赞】、【评论】、【关注】~
Time will tell.(时间会证明一切)