UiAutomator2.0 - 與AccessibilityService的關聯
目錄
Accessibility:無障礙,又稱輔助性功能.
AccessibilityService:無障礙服務,繼承於 Serveice. 它可以監聽操作、檢索視窗內容、啟用觸控瀏覽等
一、Android中的 Accessibility
在原生android裝置中 Settings 應用程式選單中有一項 Accessibility(無障礙). 該項選單下有項 TallBack功能:它能讀取螢幕上的內容,對於盲人和視力低弱人士而言,這項功能非常實用. 還有不知道大家是否會注意,使用三方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. 操作(點選/滑動等)設定應用程式,會出現相應的響應事件
e.結合上篇的點選時監聽的相應事件,與log中列印的事件是一致的. 那就說明:點選/滑動等操作是通過 AccessibilityService 監聽對應的檢視或視窗狀態來判斷操作是否成功執行.