Android自动化之AccessibilityService

简介
demo示例说明
Manifest声明
AccessibilityService的XML配置文件
创建继承自AccessibilityService的服务类
MainActivity检测服务是否开启
UiAutomatorViewer
参考

简介

由于许多Android用户由于某些原因(视力,身体,年龄)要求他们以不同的方式与手机设备交互。

安卓提供了辅助功能特性和服务来帮助这些用户更容易的操作他们的设备,包括文字转语音(原生不支持中文,国内ROM可能会有,我的测试OPPO自带中文哟!),触觉反馈,手势操作,轨迹球和手柄操作。开发者可以利用这些服务使得程序更好用,也可以创建自己的辅助服务。

随着Android版本的不断升级,Android Accessibility功能也越来越强大,Android 4.0版本以前,系统辅助服务功能比较单一,仅仅能过单向获取窗口元素信息,比如获取输入框用户输入内容。到Android 4.1版本以后(现在主流厂商的版本都在KITKAT4.4),系统辅助服务增加了与窗口元素的双向交互,此时可以通过辅助功能服务操作窗口元素,比如点击按钮等。
由于系统辅助服务能够实时获取您当前操作应用的窗口元素信息,这有可能给你带来隐私信息的泄露风险,比如获取非密码输入框的输入内容等。同时通过辅助功能也可以模拟用户自动化点击应用内元素,也会带来一定的安全风险。

已经有其他同学使用AccessibilityService实现了抢红包~以及自动安装等,大家可以自行百度。

demo示例说明

接下来我们将通过AccessibilityService实现点击元素之后语言反馈所点击的内容。
测试辅助抓包应用为【微信】

下载地址
链接:http://pan.baidu.com/s/1pJVyo0z 密码:00i6

Manifest声明

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <manifestxmlns:android="http://schemas.android.com/apk/res/android"
  3. package="com.leestar.example.accessibilityservice"
  4. android:versionCode="1"
  5. android:versionName="1.0">
  6. <uses-sdk
  7. android:minSdkVersion="19"
  8. android:targetSdkVersion="21"/>
  9. <application
  10. android:allowBackup="true"
  11. android:icon="@drawable/ic_launcher"
  12. android:label="@string/app_name"
  13. android:theme="@style/AppTheme">
  14. <activity
  15. android:name=".MainActivity"
  16. android:label="@string/app_name">
  17. <intent-filter>
  18. <actionandroid:name="android.intent.action.MAIN"/>
  19. <categoryandroid:name="android.intent.category.LAUNCHER"/>
  20. </intent-filter>
  21. </activity>
  22. <service
  23. android:name=".AccessibilityServiceExample"
  24. android:label="@string/accessibility_service_label"
  25. android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
  26. <intent-filter>
  27. <actionandroid:name="android.accessibilityservice.AccessibilityService"/>
  28. </intent-filter>
  29. <meta-data
  30. android:name="android.accessibilityservice"
  31. android:resource="@xml/accessibility_service_config"/>
  32. </service>
  33. </application>
  34. </manifest>

AccessibilityService的XML配置文件

保存路径为<project_dir>/res/xml/accessibility_service_config.xml

  1. <accessibility-servicexmlns:android="http://schemas.android.com/apk/res/android"
  2. android:description="@string/accessibility_service_description"
  3. android:packageNames="com.tencent.mm"
  4. android:accessibilityEventTypes="typeAllMask"
  5. android:accessibilityFlags="flagDefault"
  6. android:accessibilityFeedbackType="feedbackSpoken"
  7. android:notificationTimeout="100"
  8. android:canRetrieveWindowContent="true"
  9. android:settingsActivity="com.example.android.accessibility.ServiceSettingsActivity"
  10. />

其中
android:packageNames为需要捕获的包名
android:accessibilityEventTypes为需要回调的事件
android:notificationTimeout为事件回调的延迟事件
其他具体含义请查询官方文档~

创建继承自AccessibilityService的服务类

具体见代码以及注释,里面也实现了语言反馈功能。

  1. package com.leestar.example.accessibilityservice;
  2. import android.accessibilityservice.AccessibilityService;
  3. import android.annotation.TargetApi;
  4. import android.content.Intent;
  5. import android.os.Build;
  6. import android.speech.tts.TextToSpeech;
  7. import android.util.Log;
  8. import android.view.accessibility.AccessibilityEvent;
  9. import android.view.accessibility.AccessibilityNodeInfo;
  10. publicclassAccessibilityServiceExampleextendsAccessibilityService{
  11. privateAccessibilityNodeInfo rootNodeInfo;
  12. privateTextToSpeech tts =null;
  13. privateboolean ttsIsInit =false;
  14. /**
  15. * 可选。系统会在成功连接上你的服务的时候调用这个方法,在这个方法里你可以做一下初始化工作,例如设备的声音震动管理,
  16. * 也可以调用setServiceInfo()进行配置工作。
  17. */
  18. @Override
  19. protectedvoid onServiceConnected(){
  20. // TODO Auto-generated method stub
  21. super.onServiceConnected();
  22. tts =newTextToSpeech(getApplicationContext(),new android.speech.tts.TextToSpeech.OnInitListener(){
  23. @Override
  24. publicvoid onInit(int status){
  25. if(status ==TextToSpeech.SUCCESS){
  26. ttsIsInit =true;
  27. }
  28. }
  29. });
  30. }
  31. /**
  32. * 可选。在系统将要关闭这个AccessibilityService会被调用。在这个方法中进行一些释放资源的工作。
  33. */
  34. @Override
  35. publicboolean onUnbind(Intent intent){
  36. // TODO Auto-generated method stub
  37. returnsuper.onUnbind(intent);
  38. }
  39. /**
  40. * 根据XML的android:accessibilityEventTypes来进行事件回调,所有的业务逻辑都要在回调中完成
  41. */
  42. @TargetApi(Build.VERSION_CODES.KITKAT)
  43. @Override
  44. publicvoid onAccessibilityEvent(AccessibilityEvent event){
  45. rootNodeInfo = event.getSource();
  46. if(rootNodeInfo ==null)
  47. return;
  48. switch(event.getEventType()){
  49. caseAccessibilityEvent.TYPE_VIEW_CLICKED:
  50. // 语音反馈
  51. if(ttsIsInit){
  52. // event.getContentDescription根据触发事件节点来自动查找子树的ContentDescription
  53. //所以你会发现UIAutomatorViewer上的相关节点信息为空,但是event里赋值了。
  54. // event.getText同上
  55. if(event.getContentDescription()!=null){
  56. tts.speak(event.getContentDescription().toString(),TextToSpeech.QUEUE_ADD,null);
  57. }elseif(event.getText()!=null){
  58. tts.speak(event.getText().toString(),TextToSpeech.QUEUE_ADD,null);
  59. }
  60. }
  61. // 获取精确节点信息,可以通过UIAutomatorViewer检索,实现相关模拟操作
  62. //AccessibilityNodeInfo提供了2种自动查找字节点的函数
  63. //rootNodeInfo.findAccessibilityNodeInfosByText
  64. //rootNodeInfo.findAccessibilityNodeInfosByViewId(viewId)
  65. if(rootNodeInfo.getChild(0)!=null
  66. && rootNodeInfo.getChild(0).getClassName().equals("android.widget.TextView")
  67. && rootNodeInfo.getChild(0).getText()!=null
  68. && rootNodeInfo.getChild(0).getText().toString().equals("我")){
  69. // 如果发现按的是【我】,模拟全局返回按钮,即退出微信
  70. performGlobalAction(GLOBAL_ACTION_BACK);
  71. // 模拟点击元素
  72. // if (rootNodeInfo.isClickable()) {
  73. // rootNodeInfo.performAction(AccessibilityNodeInfo.ACTION_CLICK);
  74. // }
  75. }
  76. break;
  77. default:
  78. break;
  79. }
  80. Log.i("leestar",AccessibilityEvent.eventTypeToString(event.getEventType()));
  81. Log.i("leestar", rootNodeInfo.getClassName().toString());
  82. }
  83. /**
  84. * 这个在系统想要中断AccessibilityService返给的响应时会调用。在整个生命周期里会被调用多次。
  85. */
  86. @Override
  87. publicvoid onInterrupt(){
  88. Log.i("leestar","onInterrupt");
  89. }
  90. }

MainActivity检测服务是否开启

  1. package com.leestar.example.accessibilityservice;
  2. import java.util.List;
  3. import android.accessibilityservice.AccessibilityServiceInfo;
  4. import android.app.Activity;
  5. import android.content.Context;
  6. import android.content.Intent;
  7. import android.os.Bundle;
  8. import android.provider.Settings;
  9. import android.view.View;
  10. import android.view.WindowManager;
  11. import android.view.accessibility.AccessibilityManager;
  12. import android.widget.Button;
  13. publicclassMainActivityextendsActivity{
  14. privateButton button_switch;
  15. @Override
  16. protectedvoid onCreate(Bundle savedInstanceState){
  17. // TODO Auto-generated method stub
  18. super.onCreate(savedInstanceState);
  19. setContentView(R.layout.activity_main);
  20. button_switch =(Button) findViewById(R.id.button_switch);
  21. }
  22. @Override
  23. protectedvoid onResume(){
  24. super.onResume();
  25. updateServiceStatus();
  26. }
  27. @Override
  28. protectedvoid onDestroy(){
  29. getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
  30. super.onDestroy();
  31. }
  32. publicvoid onButtonClick(View view){
  33. startActivity(newIntent(Settings.ACTION_ACCESSIBILITY_SETTINGS));
  34. }
  35. privatevoid updateServiceStatus(){
  36. booleanServiceEnabled=false;
  37. // 循环遍历所有服务,查看是否开启
  38. AccessibilityManager accessibilityManager =(AccessibilityManager) getSystemService(Context.ACCESSIBILITY_SERVICE);
  39. List<AccessibilityServiceInfo> accessibilityServices = accessibilityManager
  40. .getEnabledAccessibilityServiceList(AccessibilityServiceInfo.FEEDBACK_SPOKEN);
  41. for(AccessibilityServiceInfo info : accessibilityServices){
  42. if(info.getId().equals(getPackageName()+"/.AccessibilityServiceExample")){
  43. ServiceEnabled=true;
  44. break;
  45. }
  46. }
  47. if(ServiceEnabled){
  48. button_switch.setText("关闭测试服务");
  49. // Prevent screen from dimming
  50. getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
  51. }else{
  52. button_switch.setText("开启测试服务");
  53. getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
  54. }
  55. }
  56. }

UiAutomatorViewer

在需要精确元素节点操作检索的时候,就需要用到UiAutomatorViewer工具,一般情况下,Android SDK下会自带这个工具

找到uiautomatorviewer.bat即可,打开之后,点击看起来是这个样子的

我想你应该知道怎么做了,树形结构UI,AccessibilityNodeInfo通过getChild、getParent尽情的识别吧~!

参考

http://www.android-doc.com/guide/topics/ui/accessibility/services.html

来自为知笔记(Wiz)

时间: 2024-10-09 17:03:29

Android自动化之AccessibilityService的相关文章

Android自动化框架 模拟操作 模拟测试

转自:http://bbs2.c114.net/home.php?mod=space&uid=1025779&do=blog&id=5322 几种常见的Android自动化测试框架及其应用 随着Android应用得越来越广,越来越多的公司推出了自己移动应用测试平台.例如,百度的MTC.东软易测云.Testin云测试平台…….由于自己所在项目组就是做终端测试工具的,故抽空了解了下几种常见的基于UI层面的自动化测试工具.趁晚上有空总结下,好记心不如烂笔头呀! 一 常见Android自动

Android自动化框架

Android自动化框架 已有 2085 次阅读2014-8-26 12:19 | Android 几种常见的Android自动化测试框架及其应用 随着Android应用得越来越广,越来越多的公司推出了自己移动应用测试平台.例如,百度的MTC.东软易测云.Testin云测试平台…….由于自己所在项目组就是做终端测试工具的,故抽空了解了下几种常见的基于UI层面的自动化测试工具.趁晚上有空总结下,好记心不如烂笔头呀! 一 常见Android自动化测试框架及其应用 目前,Android基于UI层面的自

使用Monkeyrunner进行Android自动化的总结

使用Android自动化的方式,不仅可以用来对Android APP进行自动化测试,同样可以用来进行一些其他非常有意思的自动化任务.常用的自动化工具有Monkeyrunner, Robotium, Appium等.Monkeyrunner是Android自带的自动化测试工具,允许用户对Android设备的UI界面进行元素提取,执行touch和drag等操作,配合HierarchyViewer等模块可以非常方便地进行自动化操作. 首先,用户需要安装好Android开发环境,同时运行Monkeyru

Android自动化测试之Monkeyrunner学习笔记(一)【转】

因项目需要,开始研究Android自动化测试方法,对其中的一些工具.方法和框架做了一些简单的整理,其中包括Monkey.Monkeyrunner.Athrun.appium,目前仍在了解学习android测试框架.CTS等.本文主要为前段时间学习总结,由于刚接触不久,故本文难免会有些肤浅,大神请绕走~ [目录] 1.Monkeyrunner简介 2.Monkeyrunner工具特性 3.Monkeyrunner工具同Monkey工具的差别 4.运行Monkeyrunner 5.实例 6.学习笔记

【金阳光测试】Android自动化 -- 学习历程:MonkeyRunner原理初步

章节:自动化基础篇——MonkeyRunner原理初步 网易云课堂: http://study.163.com/course/courseLearn.htm?courseId=712011#/learn/video?lessonId=877115&courseId=712011 主要讲解内容及笔记: 一.理论知识和脚本演示 最佳方式是上官网文档去查看monkeyrunner的介绍,官网上不去,就找了一个本地的android 4.2 的查看,基本内容没啥变化 First,什么是MonkeyRunn

[转] android自动化之MonkeyRunner测试环境配置(一)

Android自动化测试之MonkeyRunner 一.Android自动化测试之环境搭建 1.1  Android-sdk介绍 ¢ SDK(Software development kit)软件开发工具包.被软件开发工程师用于为特定的软件包.软件框架.硬件平台.操作系统等建立应用软件的开发工具的集合.Android是google公司推出的手机开发平台.Android-sdk就是指Android专属的软件开发工具包. Android-sdk中我们最常用的就是tools和Platformtools

[转] Android自动化测试之使用java调用monkeyrunner(五)

Android自动化测试之使用java调用monkeyrunner 众所周知,一般情况下我们使用android中的monkeyrunner进行自动化测试时,使用的是python语言来写测试脚本.不过,最近发现可以用java调用monkeyrunner Api,用java语言写测试脚本. 于是,就简单研究了一下.这里做一些总结.希望有对在研究的午饭可以有所用处. 开始时,搜素到一些零碎的教程,说使用java调用monkeyrunner时,需要导入android sdk  tools路径下的lib里

美团Android自动化之旅—适配渠道包

概述 前一篇文章(美团Android自动化之旅-生成渠道包)介绍了Android中几种生成渠道包的方式,基本解决了打包慢的问题. 但是,随着渠道越来越多,不同渠道对应用的要求也不尽相同.例如,有的渠道要求美团客户端的应用名为美团,有的渠道要求应用名为美团团购.又比如,有些渠道要求应用不能使用第三方统计工具(如flurry).总之,每次打包都需要对这些渠道进行适配. 之前的做法是为每个需要适配的渠道创建一个Git分支,发版时再切换到相应的分支,并合并主分支的代码.适配的渠道比较少的话这种方式还可以

Android自动化问题小结

Android 自动化case小结: 1.jenkins  job  运行   Android 自动化case     出现 com.meilishuo.testcase.profile.AlbumShare:INSTRUMENTATION_RESULT: shortMsg=keyDispatchingTimedOutINSTRUMENTATION_RESULT: longMsg=Timed out while dispatching key eventINSTRUMENTATION_CODE: