Accessibility:無障礙,又稱輔助性功能.
AccessibilityService:無障礙服務,繼承於 Serveice. 它可以監聽操作、檢索窗口內容、啟用觸摸瀏覽等
一、Android中的 Accessibility
在原生android設備中 Settings 應用程序菜單中有一項 Accessibility(無障礙). 該項菜單下有項 TalkBack功能:它能讀取屏幕上的內容,對於盲人和視力低弱人士而言,這項功能非常實用. 還有不知道大家是否會注意,使用三方app store批量自動安裝app時,此時Accessibility中會出現 "xx自動安裝"功能. 那么這些功能是怎實現的呢?是如何實現的呢?—— AccessibilityService
二、UiAutomator2.0 與 AccessibilityService
在《UiAutomator2.0 - 控件實現點擊操作原理》中已經分析了UiAutomator自動測試點擊操作的具體實現過程,最終的操作是由 UiAutomation 這個類實現的.從這個類注釋可以看出:可以將UiAutomation看作特殊AccessibilityService 類型,它不為服務生命周期提供掛鈎,並且公開了對UI測試自動化有用的其他API.也就是說UiAutomator2.0是通過 AccessibilityService來實現的.
三、驗證與 AccessibilityService的關聯
a.為了驗證上面的猜想是否正確,在Android studio中新建app工程->建一個服務類MyAccessibility繼承 AccessibilityService
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中配置服務
<?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 監聽對應的視圖或窗口狀態來判斷操作是否成功執行.