目录html
Accessibility:无障碍,又称辅助性功能.
AccessibilityService:无障碍服务,继承于 Serveice. 它能够监听操做、检索窗口内容、启用触摸浏览等android
在原生android设备中 Settings 应用程序菜单中有一项 Accessibility(无障碍). 该项菜单下有项 TalkBack功能:它能读取屏幕上的内容,对于盲人和视力低弱人士而言,这项功能很是实用. 还有不知道你们是否会注意,使用三方app store批量自动安装app时,此时Accessibility中会出现 "xx自动安装"功能. 那么这些功能是怎实现的呢?是如何实现的呢?—— AccessibilityService
git
在《UiAutomator2.0 - 控件实现点击操做原理》中已经分析了UiAutomator自动测试点击操做的具体实现过程,最终的操做是由 UiAutomation 这个类实现的.从这个类注释能够看出:能够将UiAutomation看做特殊AccessibilityService 类型,它不为服务生命周期提供挂钩,而且公开了对UI测试自动化有用的其余API.也就是说UiAutomator2.0是经过 AccessibilityService来实现的.
github
a.为了验证上面的猜测是否正确,在Android studio中新建app工程->建一个服务类MyAccessibility继承 AccessibilityServiceshell
package com.zzw.barrierfree; import android.accessibilityservice.AccessibilityService; import android.accessibilityservice.AccessibilityServiceInfo; import android.util.Log; import android.view.accessibility.AccessibilityEvent; public class MyAccessibility extends AccessibilityService { private static final String TAG = MyAccessibility.class.getSimpleName(); // 初始化服务操做 @Override protected void onServiceConnected() { Log.d(TAG, "onServiceConnected: ------- config accessibility "); AccessibilityServiceInfo accessibilityServiceInfo = new AccessibilityServiceInfo(); // 响应某个应用的事件,包名为应用的包名。设置为null等同于全部包名 accessibilityServiceInfo.packageNames = new String[]{ "com.android.settings"}; // 响应时间的类型,事件分不少种:单击、长按、滑动。 这里设置为全部事件 accessibilityServiceInfo.eventTypes = AccessibilityEvent.TYPES_ALL_MASK; // 设置回馈给用户的方式,语音播出仍是振动 accessibilityServiceInfo.feedbackType = AccessibilityServiceInfo.FEEDBACK_SPOKEN; // 响应时间的设置 accessibilityServiceInfo.notificationTimeout = 1000; setServiceInfo(accessibilityServiceInfo); } // 响应AccessibilityEvent的事件 @Override public void onAccessibilityEvent(AccessibilityEvent event) { int eventTypeId = event.getEventType(); String eventText = ""; Log.d(TAG, "onAccessibilityEvent: ----------------Start--------------"); switch (eventTypeId) { 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 + ":" + eventTypeId; Log.e(TAG, "onAccessibilityEvent:"+ eventText); Log.d(TAG, "onAccessibilityEvent: -------------------End----------------"); } // 打断获取事件的过程 @Override public void onInterrupt() { } }
b.在AndroidManifest.xml中配置服务app
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.zzw.barrierfree"> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:theme="@style/AppTheme.NoActionBar"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <!--服务配置--> <service android:name=".MyAccessibility" android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE" > <intent-filter> <action android:name="android.accessibilityservice.AccessibilityService" /> </intent-filter> </service> </application> </manifest>
c.运行该app,此时在设置->无障碍中会出现配置的服务, 可是该服务处于关闭状态
d.手动开启该服务,打开android studio中的logcat. 操做(点击/滑动等)设置应用程序,会出现相应的响应事件.如下是命令开启方式:
adb shell settings put secure enabled_accessibility_services com.zzw.barrierfree/com.zzw.barrierfree.MyAccessibility
adb shell settings put secure accessibility_enabled 1
e.结合上篇的点击时监听的相应事件,与log中打印的事件是一致的. 那就说明:点击/滑动等操做是经过 AccessibilityService 监听对应的视图或窗口状态来判断操做是否成功执行.ide