UiAutomator 与 Shell 结合的力量

转载地址:https://testerhome.com/topics/2806


我的想法就是通过UiAutomator本身的dump命令,来抓取手机当前页面的xml档,这个xml档里面有存储手机当前页面的属性及坐标等.接着通过shell脚本命令来解析或过滤出我们想要点击的属性的坐标值来,最后通过sendevent的方式来实现:点击/长按/滑动(Swipe)/双击/拖拽(Drag)/多点点击等操作.

阅读前提:
1. 读者需要掌握uiautomator的基本用法
2. 读者需要掌握shell脚本的基本用法,以及grep与sed的常用方法

首先,我们需要借助UiAutomator抓取手机当前页面的配置信息,我们在DOS命令行中,执行adb shell uiautomator dump时,会自动生成一份文件,并存储在手机的SD 卡根目录中,名为:window_dump.xml.读者可以将它复制到电脑上来查看,其实这个文件和我们在电脑上借助Android SDK中,uiautomatorviewer.bat来察看手机当前页面的属性等值的方法是一样的.

<code style="font-family: Monaco, Menlo, 'Courier New', monospace; margin: 2px; word-break: break-all; line-height: 18px; display: block; padding: 0px !important; border: none !important;"><span style="font-size: 18px;">REM 这里是DOS命令行,REM为DOS命令行注释,请知悉
REM 这里使用的是小米手机,Android Version: 4.4.4
C:\Users\Administrator>adb shell uiautomator dump
UI hierchary dumped to: /storage/emulated/legacy/window_dump.xml</span></code>

那抓出来的档案是可以在电脑上来查看的,形如:

<code style="font-family: Monaco, Menlo, 'Courier New', monospace; margin: 2px; word-break: break-all; line-height: 18px; display: block; padding: 0px !important; border: none !important;"><span style="font-size: 18px;"><span class="cp" style="color: rgb(176, 178, 176);"><?xml version="1.0" encoding="UTF-8" standalone="true"?></span>
<span class="nt" style="color: rgb(0, 128, 0); font-weight: bold;"><hierarchy</span> <span class="na" style="color: rgb(187, 68, 68);">rotation=</span><span class="s" style="color: rgb(187, 68, 68);">"0"</span><span class="nt" style="color: rgb(0, 128, 0); font-weight: bold;">></span>
<span class="nt" style="color: rgb(0, 128, 0); font-weight: bold;"><node</span> <span class="na" style="color: rgb(187, 68, 68);">index=</span><span class="s" style="color: rgb(187, 68, 68);">"0"</span> <span class="na" style="color: rgb(187, 68, 68);">text=</span><span class="s" style="color: rgb(187, 68, 68);">""</span> <span class="na" style="color: rgb(187, 68, 68);">resource-id=</span><span class="s" style="color: rgb(187, 68, 68);">""</span> <span class="na" style="color: rgb(187, 68, 68);">class=</span><span class="s" style="color: rgb(187, 68, 68);">"android.widget.FrameLayout"</span> <span class="na" style="color: rgb(187, 68, 68);">package=</span><span class="s" style="color: rgb(187, 68, 68);">"com.miui.notes"</span> <span class="na" style="color: rgb(187, 68, 68);">content-desc=</span><span class="s" style="color: rgb(187, 68, 68);">""</span> <span class="na" style="color: rgb(187, 68, 68);">checkable=</span><span class="s" style="color: rgb(187, 68, 68);">"false"</span> <span class="na" style="color: rgb(187, 68, 68);">checked=</span><span class="s" style="color: rgb(187, 68, 68);">"false"</span> <span class="na" style="color: rgb(187, 68, 68);">clickable=</span><span class="s" style="color: rgb(187, 68, 68);">"false"</span> <span class="na" style="color: rgb(187, 68, 68);">enabled=</span><span class="s" style="color: rgb(187, 68, 68);">"true"</span> <span class="na" style="color: rgb(187, 68, 68);">focusable=</span><span class="s" style="color: rgb(187, 68, 68);">"false"</span> <span class="na" style="color: rgb(187, 68, 68);">focused=</span><span class="s" style="color: rgb(187, 68, 68);">"false"</span> <span class="na" style="color: rgb(187, 68, 68);">scrollable=</span><span class="s" style="color: rgb(187, 68, 68);">"false"</span> <span class="na" style="color: rgb(187, 68, 68);">long-clickable=</span><span class="s" style="color: rgb(187, 68, 68);">"false"</span> <span class="na" style="color: rgb(187, 68, 68);">password=</span><span class="s" style="color: rgb(187, 68, 68);">"false"</span> <span class="na" style="color: rgb(187, 68, 68);">selected=</span><span class="s" style="color: rgb(187, 68, 68);">"false"</span> <span class="na" style="color: rgb(187, 68, 68);">bounds=</span><span class="s" style="color: rgb(187, 68, 68);">"[0,0][720,1280]"</span><span class="nt" style="color: rgb(0, 128, 0); font-weight: bold;">></span>
<span class="c" style="color: rgb(176, 178, 176); font-style: italic;"><!--这里提注释,内容太多,抱歉,不便全列,省略若干字哈 --></span>
<span class="nt" style="color: rgb(0, 128, 0); font-weight: bold;"></hierarchy></span></span></code>

接着,这里我们介绍如何借助强大的Shell脚本,来抓取/过滤出我们想要的东东,

<code style="font-family: Monaco, Menlo, 'Courier New', monospace; margin: 2px; word-break: break-all; line-height: 18px; display: block; padding: 0px !important; border: none !important;"><span style="font-size: 18px;">getCoordinateByAttribution<span class="o" style="color: rgb(102, 102, 102);">()</span>
<span class="o" style="color: rgb(102, 102, 102);">{</span>

<span class="c" style="color: rgb(176, 178, 176); font-style: italic;">#这里我们定义了一个instance,它的灵感是来自UiAutomator中的同名操作.意思是在当前页面下,有n个一模一样的属性,我们不好区分时,使用instance来指出我们需要点击的是第一个还是第n个属性.默认点击第一个.</span>
<span class="nv" style="color: rgb(184, 134, 11);">instance</span><span class="o" style="color: rgb(102, 102, 102);">=</span><span class="s2" style="color: rgb(187, 68, 68);">""</span>
<span class="nv" style="color: rgb(184, 134, 11);">instance</span><span class="o" style="color: rgb(102, 102, 102);">=</span><span class="k" style="color: rgb(170, 34, 255); font-weight: bold;">${</span><span class="nv" style="color: rgb(184, 134, 11);">instance</span>:<span class="p">=</span><span class="nv" style="color: rgb(184, 134, 11);">$2</span><span class="k" style="color: rgb(170, 34, 255); font-weight: bold;">}</span>
<span class="nv" style="color: rgb(184, 134, 11);">instance</span><span class="o" style="color: rgb(102, 102, 102);">=</span><span class="k" style="color: rgb(170, 34, 255); font-weight: bold;">${</span><span class="nv" style="color: rgb(184, 134, 11);">instance</span>:<span class="p">=1</span><span class="k" style="color: rgb(170, 34, 255); font-weight: bold;">}</span>

uiautomator dump
<span class="c" style="color: rgb(176, 178, 176); font-style: italic;">#这里借助了busybox工具,至于什么是busybox工具以及如何安装,此处暂不讲,读者可以先行百度,若有困难,再说.</span>
<span class="c" style="color: rgb(176, 178, 176); font-style: italic;">#这里借助grep命令,来过滤出我们需要点击的属性,个人认为此方法比UiAutomator这个工具本身要方便一些.UiAutomator本身做了很多的区别,比如text,descrption,resourceId等等.</span>
<span class="nv" style="color: rgb(184, 134, 11);">temp</span><span class="o" style="color: rgb(102, 102, 102);">=</span><span class="sb" style="color: rgb(187, 68, 68);">`</span>cat /mnt/sdcard/window_dump.xml|busybox sed <span class="s1" style="color: rgb(187, 68, 68);">'s/>/\n/g'</span>|busybox grep <span class="s2" style="color: rgb(187, 68, 68);">"</span><span class="nv" style="color: rgb(184, 134, 11);">$1</span><span class="s2" style="color: rgb(187, 68, 68);">"</span>|busybox sed -n <span class="o" style="color: rgb(102, 102, 102);">{</span><span class="nv" style="color: rgb(184, 134, 11);">$2</span><span class="o" style="color: rgb(102, 102, 102);">}</span>p<span class="sb" style="color: rgb(187, 68, 68);">`</span>
<span class="nv" style="color: rgb(184, 134, 11);">temp</span><span class="o" style="color: rgb(102, 102, 102);">=</span><span class="sb" style="color: rgb(187, 68, 68);">`</span><span class="nb" style="color: rgb(170, 34, 255);">echo</span> <span class="k" style="color: rgb(170, 34, 255); font-weight: bold;">${</span><span class="nv" style="color: rgb(184, 134, 11);">temp</span><span class="p">%]\</span><span class="s2" style="color: rgb(187, 68, 68);">"*}</span><span class="sb" style="color: rgb(187, 68, 68);">`</span>
<span class="nv" style="color: rgb(184, 134, 11);">temp</span><span class="o" style="color: rgb(102, 102, 102);">=</span><span class="sb" style="color: rgb(187, 68, 68);">`</span><span class="s2" style="color: rgb(187, 68, 68);">echo </span><span class="nv" style="color: rgb(184, 134, 11);">$temp</span><span class="s2" style="color: rgb(187, 68, 68);">|busybox awk '{print </span><span class="nv" style="color: rgb(184, 134, 11);">$NF</span><span class="s2" style="color: rgb(187, 68, 68);">}'</span><span class="sb" style="color: rgb(187, 68, 68);">`</span>

<span class="c" style="color: rgb(176, 178, 176); font-style: italic;">#此处我们作一个判断,如果temp的值不等空串的话,我们认为找到了我们需要查找的属性,并作进一步的处理</span>
<span class="k" style="color: rgb(170, 34, 255); font-weight: bold;">if </span>busybox <span class="nb" style="color: rgb(170, 34, 255);">test</span> ! <span class="s2" style="color: rgb(187, 68, 68);">"</span><span class="nv" style="color: rgb(184, 134, 11);">$temp</span><span class="s2" style="color: rgb(187, 68, 68);">"</span> <span class="o" style="color: rgb(102, 102, 102);">==</span> <span class="s2" style="color: rgb(187, 68, 68);">""</span>
<span class="k" style="color: rgb(170, 34, 255); font-weight: bold;">then
</span><span class="nv" style="color: rgb(184, 134, 11);">temp</span><span class="o" style="color: rgb(102, 102, 102);">=</span><span class="sb" style="color: rgb(187, 68, 68);">`</span><span class="s2" style="color: rgb(187, 68, 68);">echo </span><span class="k" style="color: rgb(170, 34, 255); font-weight: bold;">${</span><span class="nv" style="color: rgb(184, 134, 11);">temp</span><span class="p">/bounds=/</span><span class="k" style="color: rgb(170, 34, 255); font-weight: bold;">}</span><span class="sb" style="color: rgb(187, 68, 68);">`</span>
<span class="nv" style="color: rgb(184, 134, 11);">temp</span><span class="o" style="color: rgb(102, 102, 102);">=</span><span class="sb" style="color: rgb(187, 68, 68);">`</span><span class="s2" style="color: rgb(187, 68, 68);">echo </span><span class="nv" style="color: rgb(184, 134, 11);">$temp</span><span class="s2" style="color: rgb(187, 68, 68);">| busybox sed 's/"</span><span class="p">//g</span><span class="s1" style="color: rgb(187, 68, 68);">'| busybox sed '</span><span class="nv" style="color: rgb(184, 134, 11);">s</span><span class="p">/\[//g</span><span class="s1" style="color: rgb(187, 68, 68);">'| busybox sed '</span><span class="nv" style="color: rgb(184, 134, 11);">s</span><span class="p">/\]/\n/g</span><span class="s1" style="color: rgb(187, 68, 68);">'`
p1=`echo $temp|busybox awk '</span><span class="p">{print </span><span class="nv" style="color: rgb(184, 134, 11);">$1</span><span class="k" style="color: rgb(170, 34, 255); font-weight: bold;">}</span><span class="s1" style="color: rgb(187, 68, 68);">'`
p2=`echo $temp|busybox awk '</span><span class="o" style="color: rgb(102, 102, 102);">{</span>print <span class="nv" style="color: rgb(184, 134, 11);">$2</span><span class="o" style="color: rgb(102, 102, 102);">}</span><span class="s1" style="color: rgb(187, 68, 68);">'`
#定义四个变量,用例存储找到的属性的四个坐标值
p1x=`echo ${p1%,*}`
p1y=`echo ${p1#*,}`
p2x=`echo ${p2%,*}`
p2y=`echo ${p2#*,}`

let centerX=$p1x/2+$p2x/2
let centerY=$p1y/2+$p2y/2
else
#这里是查找属性失败时的动作
echo `date +%m-%d-%H-%M-%S` getCoordinateByAttribution $1 failed >> /mnt/sdcard/log.txt
#screencap是android自带的可以抓图的命令,这里加上了时间而已
screencap -p /mnt/sdcard/"`date +%m-%d-%H-%M-%S`".png
fi
}

</span></span></code>

这个函数如何调用呢?容我举例说明,我们可在shell脚本中执行以下命令来调用它.

<code style="font-family: Monaco, Menlo, 'Courier New', monospace; margin: 2px; word-break: break-all; line-height: 18px; display: block; padding: 0px !important; border: none !important;"><span style="font-size: 18px;"><span class="c" style="color: rgb(176, 178, 176); font-style: italic;">#这是一个查找点击text属性的例子,这里加上双引号是因为,即使字串中有空格时,也不会被当成两个参数来处理</span>
getCoordinateByAttribution <span class="s2" style="color: rgb(187, 68, 68);">"text"</span> 1
<span class="c" style="color: rgb(176, 178, 176); font-style: italic;">#这是一个查找点击description属性的例子</span>
getCoordinateByAttribution <span class="s2" style="color: rgb(187, 68, 68);">"description"</span> 1
<span class="c" style="color: rgb(176, 178, 176); font-style: italic;">#这是一个查找点击resourceId属性的例子</span>
getCoordinateByAttribution <span class="s2" style="color: rgb(187, 68, 68);">"resourceId"</span> 1
<span class="c" style="color: rgb(176, 178, 176); font-style: italic;">#如果有三个一模一样的resourceId属性,而我们需要点击第三个属性的话</span>
getCoordinateByAttribution <span class="s2" style="color: rgb(187, 68, 68);">"resourceId"</span> 3</span></code>

OK,既然已查找到属性,如何点击它呢?这里我们借用android自带的sendevent方法,当然你也可以使用input命令来点击,因为坐标值我们已经获取到了.
这里还是用小米2移动定制手机为例,

<code style="font-family: Monaco, Menlo, 'Courier New', monospace; margin: 2px; word-break: break-all; line-height: 18px; display: block; padding: 0px !important; border: none !important;"><span style="font-size: 18px;"><span class="c" style="color: rgb(176, 178, 176); font-style: italic;">#这里定义了点击的shell函数</span>
Tap<span class="o" style="color: rgb(102, 102, 102);">()</span>
<span class="o" style="color: rgb(102, 102, 102);">{</span>
sendevent /dev/input/event0 3 57 1
sendevent /dev/input/event0 3 53 <span class="nv" style="color: rgb(184, 134, 11);">$1</span>
sendevent /dev/input/event0 3 54 <span class="nv" style="color: rgb(184, 134, 11);">$2</span>
sendevent /dev/input/event0 1 330 1
sendevent /dev/input/event0 0 0 0
sendevent /dev/input/event0 3 53 <span class="nv" style="color: rgb(184, 134, 11);">$1</span>
sendevent /dev/input/event0 3 54 <span class="nv" style="color: rgb(184, 134, 11);">$2</span>
sendevent /dev/input/event0 0 0 0
<span class="o" style="color: rgb(102, 102, 102);">}</span>
<span class="c" style="color: rgb(176, 178, 176); font-style: italic;">#结合前面所述,我们只需点击对应坐标便可</span>
Tap <span class="nv" style="color: rgb(184, 134, 11);">$centerX</span> <span class="nv" style="color: rgb(184, 134, 11);">$centerY</span></span></code>

以上便是小可今天花了一个小时,写出来的一点东东了,可能有些地方不恰当,敬请批评指正,感谢!
本来还有一些感言什么的,感觉写出来,也是无甚趣味,呵呵,不写也罢.第一次发贴,诚惶诚恐.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值