Android自动化测试中AccessibilityService获取控件信息(1)

您所在的位置:网站首页 安卓获取控件信息的脚本 Android自动化测试中AccessibilityService获取控件信息(1)

Android自动化测试中AccessibilityService获取控件信息(1)

2024-07-18 06:54:56| 来源: 网络整理| 查看: 265

        AccessibilityService为一个响应用户发送AccessibilityEvent事件的服务类,主要用作对于一些辅助功能的实现中。对于某些方面有缺陷的人群,可以通过辅助功能反馈给用户。

        AccessibilityService的介绍,网络上有很多,我就不多做介绍了。我把怎么实现它跟大家分享一下,以及怎么把它跟Android自动化测试扯上关系的学习过程给大家介绍一下。

 

  第一步  编写辅助程序 

 

        创建一个Android项目,创建一个服务类,继承AccessibilityService。

 

import android.accessibilityservice.AccessibilityService; import android.accessibilityservice.AccessibilityServiceInfo; import android.annotation.SuppressLint; import android.util.Log; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; @SuppressLint("NewApi") public class MyAccessibility extends AccessibilityService { private static final String TAG = "MyAccessibility"; String[] PACKAGES = { "com.android.settings" }; @Override protected void onServiceConnected() { Log.i(TAG, "config success!"); AccessibilityServiceInfo accessibilityServiceInfo = new AccessibilityServiceInfo(); // accessibilityServiceInfo.packageNames = PACKAGES; accessibilityServiceInfo.eventTypes = AccessibilityEvent.TYPES_ALL_MASK; accessibilityServiceInfo.feedbackType = AccessibilityServiceInfo.FEEDBACK_SPOKEN; accessibilityServiceInfo.notificationTimeout = 1000; setServiceInfo(accessibilityServiceInfo); } @SuppressLint("NewApi") @Override public void onAccessibilityEvent(AccessibilityEvent event) { // TODO Auto-generated method stub int eventType = event.getEventType(); String eventText = ""; Log.i(TAG, "==============Start===================="); switch (eventType) { case AccessibilityEvent.TYPE_VIEW_CLICKED: eventText = "TYPE_VIEW_CLICKED"; break; case AccessibilityEvent.TYPE_VIEW_FOCUSED: eventText = "TYPE_VIEW_FOCUSED"; break; case AccessibilityEvent.TYPE_VIEW_LONG_CLICKED: eventText = "TYPE_VIEW_LONG_CLICKED"; break; case AccessibilityEvent.TYPE_VIEW_SELECTED: eventText = "TYPE_VIEW_SELECTED"; break; case AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED: eventText = "TYPE_VIEW_TEXT_CHANGED"; break; case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED: eventText = "TYPE_WINDOW_STATE_CHANGED"; break; case AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED: eventText = "TYPE_NOTIFICATION_STATE_CHANGED"; break; case AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_END: eventText = "TYPE_TOUCH_EXPLORATION_GESTURE_END"; break; case AccessibilityEvent.TYPE_ANNOUNCEMENT: eventText = "TYPE_ANNOUNCEMENT"; break; case AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START: eventText = "TYPE_TOUCH_EXPLORATION_GESTURE_START"; break; case AccessibilityEvent.TYPE_VIEW_HOVER_ENTER: eventText = "TYPE_VIEW_HOVER_ENTER"; break; case AccessibilityEvent.TYPE_VIEW_HOVER_EXIT: eventText = "TYPE_VIEW_HOVER_EXIT"; break; case AccessibilityEvent.TYPE_VIEW_SCROLLED: eventText = "TYPE_VIEW_SCROLLED"; break; case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: eventText = "TYPE_VIEW_TEXT_SELECTION_CHANGED"; break; case AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED: eventText = "TYPE_WINDOW_CONTENT_CHANGED"; break; } eventText = eventText + ":" + eventType; Log.i(TAG, eventText); Log.i(TAG, "=============END====================="); } @Override public void onInterrupt() { // TODO Auto-generated method stub } }

      

         该服务类继承了3个方法:

        1.onServiceConnected():绑定服务所用方法,一些初始化的操作放在这里面。

        2.onAccessibilityEvent(AccessibilityEvent event):响应AccessibilityEvent的事件,在用户操作的过程中,系统不断的发送sendAccessibiltyEvent(AccessibilityEvent event);然后通过onAccessibilityEvent()可以捕捉到该事件,然后分析。

        3.public void onInterrupt():打断获取事件的过程,本例中暂不适用。

        在onServiceConnected()我们做了一些初始化的工作,通过AccessibilityServiceInfo设置了AccessibilityService的一些参数

       //ccessibilityServiceInfo.packageNames = PACKAGES:响应某个应用的时间,包名为应用的包名;可以用String[]对象传入多包。如果不设置,默认响应所有应用的事件。

        ssibilityServiceInfo.eventTypes = AccessibilityEvent.TYPES_ALL_MASK:响应时间的类型,事件分很多种:单击、长按、滑动等,需要指定,我设置了所有事件都响应:TYPES_ALL_MASK。

        cessibilityServiceInfo.feedbackType = AccessibilityServiceInfo.FEEDBACK_SPOKEN:设置回馈给用户的方式,是语音播出还是振动。这个我们稍后尝试配置一些TTS引擎,让它发音。

        cessibilityServiceInfo.notificationTimeout = 1000:看意思就能明白,响应时间的设置。

        接下来我们要在配置文件AndroidManifest.xml配置该服务:

 

        这些设置很重要,因为AccessibilityService服务不是用户去开启的。我们无法用startService()方法启动它,所以我连activity都没写。因为它是通过该配置让系统自动识别的,识别成功后,就会在我们手机里面看到该服务,然后需要手动开启该服务(所以千万别粗心写错,我就是因为少写了一个单词,然后安装上app,一直没反应,它也不报错,害我找错找了半天,后来发现是自己的低级错误。)。

        现在我们就可以将应用部署到手机上,部署成功后我们点:设置->辅助功能。找到我们的服务,如图:

 

 

       

        看到我们的应用会显示在其中,默认是关闭的;如果你在此没看见你的服务,那么你应该核对一下你的配置文件,确保配置正确;点进去,打开该服务。

然后我们就可以随意在你的手机设备上操作,看看log输出:

 

       

        我们就会看到我们点击的事件,被服务在后台捕捉到了。接下来,我们尝试着从我们捕捉到的时间中获得我们有用的时间,AccessibilityEvent API 中有一个getSource()方法。得到的是AccessibilityNodeInfo,试着获得这个对象。我们看看是什么东西。

 

   第二步 获得控件信息

 

        在调用这个getSource()方法时,需要事先配置一下,也就是需要android:canRetrieveWindowContent="true",这个属性是API14(android4.0)给出的,它的配置方法受限于需要采用XML初始化的方式配置AccessibilityService,也就是我们现在不在onServiceConnected()里配置初始化信息,改在xml里实现。那么我们现在就要将上面的程序修改一下。首先,删除onServiceConnected()的配置(因为getSource()不是所有的操作都有该方法,所以得在特定的方法中实现该方法,我们选择在TYPE_VIEW_CLICKED里实现),修改后的服务类如下:

 

package com.spreadtrum.accessibilityservice; import android.accessibilityservice.AccessibilityService; import android.accessibilityservice.AccessibilityServiceInfo; import android.annotation.SuppressLint; import android.util.Log; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; @SuppressLint("NewApi") public class MyAccessibility extends AccessibilityService { private static final String TAG = "MyAccessibility"; String[] PACKAGES = { "com.android.settings" }; @Override protected void onServiceConnected() { Log.i(TAG, "config success!"); } @SuppressLint("NewApi") @Override public void onAccessibilityEvent(AccessibilityEvent event) { // TODO Auto-generated method stub int eventType = event.getEventType(); String eventText = ""; switch (eventType) { case AccessibilityEvent.TYPE_VIEW_CLICKED: Log.i(TAG, "==============Start===================="); eventText = "TYPE_VIEW_CLICKED"; AccessibilityNodeInfo noteInfo = event.getSource(); Log.i(TAG, noteInfo.toString()); Log.i(TAG, "=============END====================="); break; case AccessibilityEvent.TYPE_VIEW_FOCUSED: eventText = "TYPE_VIEW_FOCUSED"; break; case AccessibilityEvent.TYPE_VIEW_LONG_CLICKED: eventText = "TYPE_VIEW_LONG_CLICKED"; break; case AccessibilityEvent.TYPE_VIEW_SELECTED: eventText = "TYPE_VIEW_SELECTED"; break; case AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED: eventText = "TYPE_VIEW_TEXT_CHANGED"; break; case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED: eventText = "TYPE_WINDOW_STATE_CHANGED"; break; case AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED: eventText = "TYPE_NOTIFICATION_STATE_CHANGED"; break; case AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_END: eventText = "TYPE_TOUCH_EXPLORATION_GESTURE_END"; break; case AccessibilityEvent.TYPE_ANNOUNCEMENT: eventText = "TYPE_ANNOUNCEMENT"; break; case AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START: eventText = "TYPE_TOUCH_EXPLORATION_GESTURE_START"; break; case AccessibilityEvent.TYPE_VIEW_HOVER_ENTER: eventText = "TYPE_VIEW_HOVER_ENTER"; break; case AccessibilityEvent.TYPE_VIEW_HOVER_EXIT: eventText = "TYPE_VIEW_HOVER_EXIT"; break; case AccessibilityEvent.TYPE_VIEW_SCROLLED: eventText = "TYPE_VIEW_SCROLLED"; break; case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: eventText = "TYPE_VIEW_TEXT_SELECTION_CHANGED"; break; case AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED: eventText = "TYPE_WINDOW_CONTENT_CHANGED"; break; } } @Override public void onInterrupt() { // TODO Auto-generated method stub } }

      

        然后我们要在res文件写创建一个XML文件夹,里面新建accessibility.xml配置文件。

 

      

        在accessibility.xml配置一些属性:

 

       

        重点就是标红的这一句,这样我们就能在程序中得到AccessibilityNodeInfo对象。然后在AndroidManifest.xml配置文件里引用该XML文件:

 

       

         然后我们部署应用到手机设备,看输出情况:

 

 

        注意:

        在你配置成功后,有可能会报空指针错误,但有可能你已经配置正确,只是你点的对象有问题。因为在API文档中有一句话:如果发起的窗口事件仍然是活动的窗口,该调用将会返回一个对象,否则,会返回null!所以首先确保你刚开始点击的那个控件所在的窗口要是活动的状态,不然也会报null。例如:我刚开始点击HOME界面的所有应用按钮进入到应用的列表,这时候就会报错,如果你是点击通讯录触发服务的,就没问题;原理我也不太清楚,所以不敢大放厥词,反正在一个应用中来回点是没问题的;这个随着深入的了解后,相信会有答案的。



【本文地址】

公司简介

联系我们

今日新闻


点击排行

实验室常用的仪器、试剂和
说到实验室常用到的东西,主要就分为仪器、试剂和耗
不用再找了,全球10大实验
01、赛默飞世尔科技(热电)Thermo Fisher Scientif
三代水柜的量产巅峰T-72坦
作者:寞寒最近,西边闹腾挺大,本来小寞以为忙完这
通风柜跟实验室通风系统有
说到通风柜跟实验室通风,不少人都纠结二者到底是不
集消毒杀菌、烘干收纳为一
厨房是家里细菌较多的地方,潮湿的环境、没有完全密
实验室设备之全钢实验台如
全钢实验台是实验室家具中较为重要的家具之一,很多

推荐新闻


    图片新闻

    实验室药品柜的特性有哪些
    实验室药品柜是实验室家具的重要组成部分之一,主要
    小学科学实验中有哪些教学
    计算机 计算器 一般 打孔器 打气筒 仪器车 显微镜
    实验室各种仪器原理动图讲
    1.紫外分光光谱UV分析原理:吸收紫外光能量,引起分
    高中化学常见仪器及实验装
    1、可加热仪器:2、计量仪器:(1)仪器A的名称:量
    微生物操作主要设备和器具
    今天盘点一下微生物操作主要设备和器具,别嫌我啰嗦
    浅谈通风柜使用基本常识
     众所周知,通风柜功能中最主要的就是排气功能。在

    专题文章

      CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭