简介
在前边的第二十二篇文章里, 已经分享了通过获取控件的坐标点来获取点击事件的所需要的点击位置, 那么还有没有其他方法来获取控件点击事件所需要的点击位置呢? 答案是: Yes! 因为在不同的大小屏幕的手机上获取控件的坐标点, 不是一样的, 而是有变化的, 因此在不同的手机机型上, 我们可能都需要重新获取坐标点, 这么操作起来, 如果操作控件特别的多, 那么获取控件的坐标点就会显得特别的繁琐. 因此我们可以通过获取控件的 ID 来避免获取控件坐标点的这种弊端.
通过控件 ID 实现自动化脚本的运行, 就性能而言, 会比控件坐标的实现差一些; 但是对于不同分辨率的设备都通用, 不需要动态变换坐标. 控件 ID 的获取主要是通过 HierarchyViewer. 下面就 HierarchyViewer 从打开方式和使用两方面进行讲解.
HierarchyViewer 的打开方式
HierarchyViewer 的打开方式有两种: 一种是 eclipse 中打开 HierarchyView 视图, 另外一种是命令行中执行 sdk/tools/hierarchyviewer.bat.
HierarchyViewer 默认只能在非加密设备使用, 例如工程机, 工程平板或者模拟器. 如果要在手机上使用 HierarchyViewer, 你需要在你的应用中添加一个开源库 View Server. 链接地址: https://github.com/romainguy/ViewServer. 该篇文章中有讲解如何启动真机 View Server, 大家如果有兴趣, 可参考: https://dup2.org/node/1538.
方式一:
连接您的真机设备, 或打开模拟器, 在 eclipse 中, 依次选择 Windows-Open Perspective-Other, 在 Other 中, 选择 HierarchyView 视图, 即可打开.
方式二:
连接您的真机设备或打开模拟器, 运行 cmd 窗口, 进入到 sdk/tools 目录下, 输入命令 hierarchyviewer.bat, 运行 hierarchyviewer.
或者直接在 sdk/tools 目录下, 找到 hierarchyviewer.bat, 双击运行.
未开启夜神模拟器的 HierarchyViewer, 如下图:
开启夜神模拟器后的 HierarchyViewer, 如下图:
那么接下来看一下今天的重头戏: 讲解利用 HierarchyViewer 获取控件 ID 的方法.
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 的坐标.
控件 ID 之 Monkeyrunner 脚本演示
同样的, 我们将下面一段 Monkeyrunner 脚本写到一个 test.py 文件中, 然后运行 test.py 文件, 查看模拟器上是不是做相应的操作.
- # coding=utf-8
- # 1. 先设置编码, utf-8 可支持中英文, 如上, 一般放在第一行
- # 2. 注释: 包括记录创建时间, 创建人, 项目名称.
- '''
- Created on 2019-7-30
- @author: 北京 - 宏哥 QQ 交流群: 707699217
- Project: 学习和使用 appium 自动化测试 - 获取控件的 ID
- '''
- # 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('1918991791') #输入 qq 账号
至此, 获取控件 ID 的方式已经介绍完, 由于没有深入研究, 肯定有不少功能点没有介绍到, 有时间的话再做完善.
控件 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, 方法如下:
1 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 的用法, 乐趣及其奥秘.
小结
一, 直接在 sdk>tools 下面找到 hierarchyviewer.bat 双击运行, 然后运行成功了.
但是出现这个提示:
The standalone version of hieararchyviewer is deprecated.
Please use Android Device Monitor (tools/monitor.bat) instead.
大概意思是说, 单独版本的 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 Windows 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 Windows 3
若返回值是: Result: Parcel(00000000 00000000 '........')" 说明 View Server 处于关闭状态
若返回值是: Result: Parcel(00000000 00000001 '........')" 说明 View Server 处于开启状态
有时碰到模拟器或开发发版手机, view Hierarchy 还是无法连接, 可以先使用以上方法检查一下 View Server 状态. 如果没有开启, 则使用以下命令打开 View Server:
adb shell service call Windows 1 i32 4939
也可以使用使用以下命令关闭 View Server:
adb shell service call Windows 2 i32 4939
那么如何在真机能够正常使用 Hierarchy Viewer 了? 通过实践目前总结了以下三种方法:
方法一.
1, 配置设备, 打开手机的开发者选项
如果你的手机是 Android 4.0 或者以下, 请根据开源项目 View Server( https://github.com/romainguy/ViewServer ) 进行安装和配置
如果你的手机是 4.1 或以上, 则必须进行以下环境变量配置:
1. 点击 计算机属性 -》高级系统设置 -》环境变量
2. 新建环境变量 ANDROID_HVPROTO, 并设置其值为 ddm, 保存重启
PS: 该方法参考 Android 官方文档《Device Setup for Hierachy Viewer》
然而在本人亲自试用真机 (魅族 MX4pro Android 5.1 和 Android 4.4 的机顶盒) 测试过程中, 配置环境变量的方法似乎并没有起到作用, 还是连不上.
不过直接在调试 App 中集成 View Server 开源项目是没有任何问题的.
方法二:
话说前面 Hierarchy Viewer 只能连接 Android 开发版手机或是模拟器, 只有 ro.secure==0 && ro.debuggable==1 的 Android 系统(这一句是其他网友的文章看到的, 没有在 Android 官方查证到 ).ro.xxxx 这种句式大家是不是觉得有点熟悉? 不就是 Android 系统的 /system/build.prop 文件中的配置样式么. 推测如果将 ro.secure==0 && ro.debuggable==1 这个两个配置添加进来应该能够起作用吧, 于是进行以下尝试:
1. 先把手机 root
2. 在进到在 / system/build.prop 中添加 ro.secure==0 和 ro.debuggable==1, 保存配置并重启手机, Hierarchy Viewer 连接正常, 终于可以正常调试了.
方法三:
参照《如何在 Root 的手机上开启 ViewServer, 使得 HierachyViewer 能够连接》 http://maider.blog.sohu.com/255448342.html . 该方法本人没有实践过, 一看有 18 个步骤,
还涉及到 Android 逆向, smail, 瞬间脑仁发紧, 有兴趣的同学可以自行尝试一下.
三, 好了, 关于控件 ID 的获取, 就分享到这里.
您的肯定就是我进步的动力. 如果你感觉还不错, 就请鼓励一下吧! 记得点波 推荐 哦!!!(点击右边的小球即可, 胆子大的可以尝试一下哦! :))
个人公众号
微信群
来源: https://www.cnblogs.com/du-hong/p/11243612.html