Android輔助功能

 


 

1、前言

Android的輔助功能是個比較老的API(since API 4),但是該API真正的開始發展還是在API 16~19(很多常用的方法參數都是在這幾個版本逐漸加入以及完善的)版本中。輔助功能我們最常見的是在類似深度休眠,搶紅包中使用,模擬點擊屏幕view。此次寫關於輔助功能的分享是因爲在API 24、 API 26中,又增添了幾個類以及幾個接口。

本文首先介紹關於輔助功能的常見使用方法,然後開始介紹輔助功能新增接口以及類的使用。

2、輔助功能的使用

2.1 輔助功能常規使用方法:

本小結介紹一般情況下輔助功能的使用(基礎用法和方法釋義較多,如果需要閱覽API > 20 新增方法使用請從2.2開始閱讀),API level在20及以下的使用方式。不涉及新增的方法以及類的使用介紹。

2.1.1 使用流程:

1、Service: 配置自己的輔助功服務(註冊、配置)

2、Class: 自己的輔助功能類(對事件的攔截、處理)

2.1.2 Service配置:

1、在實例化的輔助功能類中:onServiceConnected()中初始化,如下所示。


 
  1. @Override

  2. protected void onServiceConnected() {

  3. super.onServiceConnected();

  4. AccessibilityServiceInfo info = new AccessibilityServiceInfo();

  5. info.eventTypes = AccessibilityEvent.TYPES_ALL_MASK;

  6. info.feedbackType = AccessibilityServiceInfo.FEEDBACK_GENERIC;

  7. info.notificationTimeout = 100;

  8. info.packageNames = new String[]{"...", "..."};

  9. info.flags = AccessibilityServiceInfo.FLAG_REPORT_VIEW_IDS;

  10. setServiceInfo(info);

  11. }

2、使用manifest中添加meta-data的方式(該方式從API 14開始使用)


 
  1. <?xml version="1.0" encoding="utf-8"?>

  2. <accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"

  3. android:accessibilityEventTypes=""

  4. android:accessibilityFeedbackType=""

  5. android:accessibilityFlags=""

  6. android:canRequestEnhancedWebAccessibility=""

  7. android:canRequestFilterKeyEvents=""

  8. android:canRequestTouchExplorationMode=""

  9. android:canRetrieveWindowContent=""

  10. android:description=""

  11. android:notificationTimeout=""

  12. android:packageNames=""

  13. android:settingsActivity=""

  14. android:summary="" />

由上邊兩組代碼可以看到,前一個配置中單個代碼塊中,配置屬性有限,但靈活的在服務裏邊初始化,使我們可以隨時的改變需要的flag和type及一些其他參數。而後一個(Android 4.0+ / API 14+)的meta-data配置方式,可配置的屬性更多。在系統條件符合時(同時不需要更改我們輔助功能的一些參數時),還是推薦使用後一個配置方式進行輔助功能的配置。

2.1.3 AccessibilityServiceInfo 配置參數:

這裏只是對所有的XML attributes進行說明。

XML attributes:

constant value 描述
typeAllMask ffffffff 所有類型的事件
typeAnnouncement 4000 一個應用產生一個通知事件
typeAssistReadingContext 1000000 輔助用戶讀取當前屏幕事件
typeContextClicked 800000 view中上下文點擊事件
typeGestureDetectionEnd 80000 監測到的手勢事件完成
typeGestureDetectionStart 40000 開始手勢監測事件
typeNotificationStateChanged 40 收到notification彈出消息事件
typeTouchExplorationGestureEnd 400 觸摸瀏覽事件完成
typeTouchExplorationGestureStart 200 觸摸瀏覽事件開始
typeTouchInteractionEnd 200000 用戶觸屏事件結束
typeTouchInteractionStart 100000 觸摸屏幕事件開始
typeViewAccessibilityFocusCleared 10000 無障礙焦點事件清除
typeViewAccessibilityFocused 8000 獲得無障礙的焦點事件
typeViewClicked 1 點擊事件
typeViewFocused 8 view獲取到焦點事件
typeViewHoverEnter 80 一個view的懸停事件
typeViewHoverExit 100 一個view的懸停事件結束,懸停離開該view
typeViewLongClicked 2 view的長按事件
typeViewScrolled 1000 view的滾動事件,adapterview、scrollview
typeViewSelected 4 view選中,一般是具有選中屬性的view,例如adapter
typeViewTextChanged 10 edittext中文字發生改變的事件
typeViewTextSelectionChanged 2000 edittext文字選中發生改變事件
typeViewTextTraversedAtMovementGranularity 20000 UIanimator中在一個視圖文本中進行遍歷會產生這個事件,多個粒度遍歷文本。一般用於語音閱讀context
typeWindowContentChanged 800 窗口的內容發生變化,或者更具體的子樹根佈局變化事件
typeWindowStateChanged 20 新的彈出層導致的窗口變化(dialog、menu、popupwindow)
typeWindowsChanged 400000 屏幕上的窗口變化事件,需要API 21+
constant value 描述
feedbackAllMask ffffffff 取消所有的可用反饋方式
feedbackAudible 4 可聽見的(非語音反饋)
feedbackGeneric 10 通用反饋
feedbackHaptic 2 觸覺反饋(震動)
feedbackSpoken 1 語音反饋
feedbackVisual 8 視覺反饋
  • accessibilityFlags 輔助功能附加的標誌,多個使用 ' | '分隔
constant value 描述
flagDefault 1 默認的配置
flagEnableAccessibilityVolume 80 這個標誌要求系統內所有的音頻通道,使用由STREAM_ACCESSIBILTY音量控制USAGE_ASSISTANCE_ACCESSIBILITY
flagIncludeNotImportantViews 2 表示可獲取到一些被表示爲輔助功能無權獲取到的view
flagReportViewIds 10 使用該flag表示可獲取到view的ID
flagRequestAccessibilityButton 100 如果輔助功能可用,提供一個輔助功能按鈕在系統的導航欄 API 26+
flagRequestEnhancedWebAccessibility 8 此類擴展的目的是爲WebView中呈現的內容提供更好的輔助功能支持。這種擴展的一個例子是從一個安全的來源注入JavaScript。如果至少有一個具有此標誌的輔助功能服務, 則系統將使能增強的web輔助功能。因此, 清除此標誌並不保證該設備不會使能增強的web輔助功能, 因爲可能有另一個使能的服務在使用它。
flagRequestFilterKeyEvents 20 能夠監聽到系統的物理按鍵
flagRequestFingerprintGestures 200 監聽系統的指紋手勢 API 26+
flagRequestTouchExplorationMode 4 系統進入觸控探索模式。出現一個鼠標在用戶的界面
flagRetrieveInteractiveWindows 40 該標誌知識的輔助服務要訪問所有交互式窗口內容的系統,這個標誌沒有被設置時,服務不會收到TYPE_WINDOWS_CHANGE事件。
  • canRequestEnhancedWebAccessibility (boolean)
    輔助功能服務是否能夠請求WEB輔助增強的屬性。例如: 安裝腳本以使應用程序內容更易於訪問。

  • canRequestFilterKeyEvents (boolean)
    輔助功能服務是否能夠請求過濾KeyEvent的屬性,是否可以請求KeyEvent事件流。,flagRequestFilterKeyEvents搭配使用

  • canRequestTouchExplorationMode (boolean)
    此屬性用於,能夠讓輔助功能服務通過手勢,來請求觸摸瀏覽模式,其被觸摸的項,將被朗讀出來,flagRequestTouchExplorationMode搭配使用

  • canRetrieveWindowContent (boolean)
    輔助功能服務是否能夠取回活動窗口內容的屬性。 與上邊的flagRetrieveInteractiveWindows搭配使用,無法在運行時更改此設置。

  • description
    輔助功能服務目的或行爲的簡短描述。

  • notificationTimeout
    同一類型的兩個輔助功能事件發送到服務的最短間隔(毫秒,兩個輔助功能事件之間的最小週期)

  • packageNames
    從此服務能接收到事件的軟件包名稱 (不適合所有軟件包)(多個軟件包用逗號分隔)。

  • settingsActivity
    允許用戶修改輔助功能的activity組件名稱

  • summary
    同description


2.1.4 實現自己的輔助功能類:

首先需要了解的是AccessibilityService這個類。

Public方法有:

Method 描述
API 20  
getRootInActiveWindow() 獲取窗體中的節點信息。 返回 AccessibilityNodeInfo
getServiceInfo() 獲取本服務的配置信息。 返回 AccessibilityServiceInfo
getSystemService(String name) 通過服務名獲取對應的系統服務。 返回 Object
onAccessibilityEvent(AccessibilityEvent event) 輔助功能事件(s)回調方法
onBind(Intent intent) service的bind接口
onInterrupt() 輔助功能中斷的回調
performGlobalAction(int action) 全局的點擊方法
setServiceInfo(AccessibilityServiceInfo info) 設置該輔助功能服務的描述,修改輔助功能的配置。可通過搭配使用getServiceInfo()動態修改我們輔助功能的配置
API 21新增:  
getWindows() 返回窗口最上層的一個用戶可交互的窗口信息節點 List<AccessibilityWindowInfo>
API 24新增:  
disableSelf() 關閉自己service的方法,在設置界面可以看到輔助功能狀態被關閉
getSoftKeyboardController() 返回軟鍵盤控制器,可用於查詢和修改軟鍵盤顯示模式。
findFocus(int focus) 找到具有指定焦點類型的視圖。搜索在所有窗口中執行。注意:爲了訪問Windows,您的服務必須通過在其元數據中設置AccessibilityService_canRetrieveWindowContent屬性來聲明檢索窗口內容的功能。有關詳細信息,請參閱SERVICE_META_DATA。此外,服務必須選擇通過設置FLAG_RETRIEVE_INTERACTIVE_WINDOWS標誌來檢索交互式窗口。否則,搜索將僅在活動窗口中執行。
getMagnificationController() 返回放大控制器,可用於查詢和修改顯示放大的狀態。注意:爲了控制放大倍數,您的服務必須通過在其元數據中設置AccessibilityService_canControlMagnification屬性來聲明該功能
dispatchGesture(GestureDescription ge, GestureResultCallback cb, Handler handler) 將手勢發送到觸摸屏。目前正在進行的任何手勢(無論是從用戶,本服務還是其他服務)將被取消。 手勢將被調度,就像在用戶直接在屏幕上執行的一樣,因此事件可能會受到諸如放大和觸摸探索之類的功能的影響。
API 26新增:  
getAccessibilityButtonController() 返回系統導航區域中可訪問性按鈕的控制器。當設置FLAG_REQUEST_ACCESSIBILITY_BUTTON時,此實例可用於查詢輔助功能按鈕的狀態並註冊監聽器以進行交互和輔助功能按鈕的狀態更改。返回 AccessibilityButtonController
getFingerprintGestureController() 獲取控制器的指紋手勢。此功能需要 AccessibilityServiceInfo#CAPABILITY_CAN_CAPTURE_FINGERPRINT_GESTURES。注意:在調用此方法之前,必須先啓動該服務。返回 FingerprintGestureController

這部分我們只針對API <= 20部分的代碼,其中我們常用的方法有:

Method 描述
getRootInActiveWindow() 獲取窗體中的節點信息 AccessibilityNodeInfo,如果需要使用該方法,我們需要在配置中申明 canRetrieveWindowContent,否則可能獲取不到窗體的節點信息。AccessibilityNodeInfo
onAccessibilityEvent(AccessibilityEvent event) 輔助功能事件(s)回調方法,處理輔助功能內所有事件的回調方法
performGlobalAction(int action) 全局的點擊方法

在使用這些方法時,有三個需要我們瞭解的地方:

  • AccessibilityEvent 在輔助功能event回調方法中,返回的參數。(官方API En)

  • AccessibilityNodeInfo 輔助功能中的節點對象(nodeInfo)。(官方API En)

  • performGlobalAction(action) 全局事件發送方法(物理按鍵的點擊)

AccessibilityEvent

當用戶界面發生某些明顯的事件時,AccessibilityEvent代表的無障礙事件會被系統發送,每一種事件類型是由該類暴露出的屬性子集表示其特徵的。在此類中爲每一種事件類型定義了相應的常量。詳細的事件類型請參照AccessibilityEvent文檔 Zh

Public Methods 公有方法:

Method 描述
appendRecord(AccessibilityRecord record) AccessibilityRecord(AccessibilityRecord使用pdf文檔 Zh)追加到事件記錄的結尾。
getRecord(int index) 獲取給定索引下的記錄。
getRecordCount() 獲取被包含在事件中的記錄數。
describeContents() 描述被包含在 Parcelable 實例的編組表示中的特殊對象種類。例如,如果對象在 writeToParcel(Parcel, int)的輸出裏包括一個文件描述符,該方法的返回值必須包括 CONTENTS_FILE_DESCRIPTOR 位。
getEventType() 獲取事件類型。
setEventType(int eventType) 設置事件類型。
eventTypeToString(int eventType) 返回一個事件類型的字符串表示。例如,TYPE_VIEW_CLICKED 的字符串表示爲“TYPE_VIEW_CLICKED”。
getAction() 獲取觸發該事件的執行操作。
getContentChangeTypes() 獲取由 TYPE_WINDOW_CONTENT_CHANGED 事件標識的改變類型的位掩碼。一個單一事件可能代表多種變化類型。
getEventTime() 獲取該事件的發送時間。
setEventTime(long eventTime) 設置事件被髮送的時間。
getMovementGranularity() 獲取遍歷的移動粒度。
setMovementGranularity(int granularity) 設置遍歷的移動粒度。
getPackageName() 獲取源的包名。
setPackageName(CharSequence packageName) 設置源的包名。
initFromParcel(Parcel parcel) 從 Parcel 創建一個新實例。
obtain(AccessibilityEvent event) 如果可獲得,返回一個緩存實例或創建一個新實例。返回實例從給定事件初始化。
obtain() 如果可獲得,返回一個緩存實例或實例化一個新的。
obtain(int eventType) 如果可獲得,返回一個緩存實例或實例化一個新的並設置它的類型屬性。
recycle() 回收一個實例重複使用。
setAction(int action) 設置觸發此事件的執行操作。
setContentChangeTypes(int changeTypes) 設置由一個 TYPE_WINDOW_CONTENT_CHANGED 事件標識的節點樹改變的位掩碼。
toString() 返回對象的字符串表示。一般情況下,toString 方法返回一個“文本表示”該對象的字符串。結果應該是一個簡潔但容易閱讀的信息表示。建議所有子類重寫該方法。
writeToParcel(Parcel parcel, int flags) 整組該對象到一個 Parcel。

AccessibilityNodeInfo

該類代表一個窗口內容節點和可以從源請求的操作。從 AccessibilityService的角度看,一個窗口內容被呈現爲一個無障礙節點信息樹,該樹可能與視圖層次一一映射,也可能不與視圖層次一一映射。換句話說,一個自定義視圖可靈活地將自己報告爲一個無障礙節點信息樹。一旦無障礙節點信息被髮送給無障礙服務,該信息將會是不可改變的,且調用狀態改變方法將會產生錯誤。AccessibilityNodeInfo文檔 Zh

嵌套類:

常量:
使用nodeInfo.performAction(Int Action)performAction(Int Action, Bundle bundle)方法

Action 釋義
ACTION_ACCESSIBILITY_FOCUS 給節點添加無障礙焦點的操作。
ACTION_ARGUMENT_COLUMN_INT 讓指定集合列在屏幕上可見的參數。
ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN 當以一定粒度移動時,是否擴大選擇範圍或反之移除的參數。
ACTION_ARGUMENT_HTML_ELEMENT_STRING 要移動到的下一個/上一個 HTML 元素的參數。
ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT 當遍歷節點文本的時,使用哪種移動粒度的參數。。
ACTION_ARGUMENT_PROGRESS_VALUE 指定要設置的進度值的參數。
ACTION_ARGUMENT_ROW_INT 讓指定集合行在屏幕上可見的參數。
ACTION_ARGUMENT_SELECTION_END_INT 指定選擇結束的參數。
ACTION_ARGUMENT_SELECTION_START_INT 指定選擇起始的參數。
ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE 指定要設置的文本內容的參數。
ACTION_CLEAR_ACCESSIBILITY_FOCUS 清除節點無障礙焦點的操作。
ACTION_CLEAR_FOCUS 清除節點輸入焦點的操作。
ACTION_CLEAR_SELECTION 取消選擇節點的操作。
ACTION_NEXT_AT_MOVEMENT_GRANULARITY 以給定移動粒度,請求去到該節點文本的下一個文本實體的操作。
ACTION_CLICK 在節點信息上點擊的操作.
ACTION_COLLAPSE 摺疊一個可展開節點的操作。
ACTION_COPY 將當前選擇拷貝到剪貼板的操作。
ACTION_CUT 剪貼當前選項並放置到剪貼板的操作。
ACTION_DISMISS 關閉一個可關閉節點的操作。
ACTION_EXPAND 展開一個可展開節點的操作。
ACTION_FOCUS 給節點添加輸入焦點的操作。
ACTION_LONG_CLICK 在節點上點擊長按的操作。
ACTION_NEXT_HTML_ELEMENT 移動到給定類型的下一個 HTML 元素的操作。例如,移動到 BUTTON、INPUT、TABLE 等。
ACTION_PASTE 粘貼當前剪貼板內容的操作。
ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY 以給定移動粒度,請求去到該節點文本的上一個文本實體的操作。例如,移動到下一個字、詞等。
ACTION_PREVIOUS_HTML_ELEMENT 移動到給定類型的上一個 HTML 元素的操作。例如,移動到BUTTON、INPUT、TABLE 等。
ACTION_SCROLL_BACKWARD 向後滾動節點內容的操作。
ACTION_SCROLL_FORWARD 向前滾動節點內容的操作
ACTION_SELECT 選擇節點的操作。
ACTION_SET_SELECTION 設置選擇項的操作。執行該操作,並且無參數清除選項
ACTION_SET_TEXT 設置節點文本的操作。在沒有參數的情況下執行該操作,使用 null 或者空CharSequence 將會清除文本。該操作也將會把光標放置到文本末尾
FOCUS_ACCESSIBILITY 無障礙焦點。
FOCUS_INPUT 輸入焦點。
MOVEMENT_GRANULARITY_CHARACTER 以字符爲移動粒度位,遍歷節點文本
MOVEMENT_GRANULARITY_LINE 以行爲移動粒度位,遍歷節點文本。
MOVEMENT_GRANULARITY_PAGE 以頁爲移動粒度位,遍歷節點文本。
MOVEMENT_GRANULARITY_PARAGRAPH 以段爲移動粒度位,遍歷節點文本。
MOVEMENT_GRANULARITY_WORD 以字詞爲移動粒度位,遍歷節點文本。

方法:

Public Method 釋義
addAction(int action) 爲一個nodeInfo添加一個操作,在API 21時被棄用
addAction(AccessibilityNodeInfo.AccessibilityAction action) 爲一個nodeInfo添加一個操作,API 21
addChild(View root, int virtualDescendantId) 添加一個虛擬子元素,作爲給定根節點的子view
addChild(View child) 添加一個子view節點。
canOpenPopup() 獲取該節點是否可以打開一個彈窗或對話框。
describeContents() 描述被包含在可打包實例的封裝代表中的特殊對象的種類。
equals(Object object) 標識是否有某些其他對象“等同於”該對象。
findAccessibilityNodeInfosByText(String text) 使用文本找到 AccessibilityNodeInfo。
findAccessibilityNodeInfosByViewId(String viewId) 使用完全合格視圖id的源名稱找到AccessibilityNodeInfo,完全合格 id 的樣式 如下“package:id/id_resource_name”。
findFocus(int focus) 找到具有指定焦點類型的視圖。
focusSearch(int direction) 在指定方向搜索具有輸入焦點的最近的視圖。
getActionList() 獲取可以在該節點上執行的操作。
getActions() 該方法在 API 級別 21 被棄用。使用getActionList()代替。
getBoundsInParent(Rect outBounds) 獲取父級座標中的節點邊界。
getBoundsInScreen(Rect outBounds) 獲取屏幕座標中的節點邊界。
getChild(int index) 獲取給定索引下的子元素。
getChildCount() 獲取子元素的數目。
getClassName() 獲取該節點來自的類。
getCollectionInfo() 如果節點是個集合,獲取集合信息。一個集合子集總是一個集合項目。
getCollectionItemInfo() 如果節點是個集合項目,獲取集合項目信息。一個集合項目總是一個集合的子集。
getContentDescription() 獲取該節點的內容描述。
getExtras() 獲取具有附加數據的可選 bundle。該包是閒時創建的且永不爲 null。注意:爲了避免衝突,推薦使用應用的包名作爲關鍵字字首,如果從不同應用發出的相同關鍵詞有不同的含義,可能會導致無障礙服務困擾。
getInputType() 獲取定義爲 InputType 的源中的輸入類型。
getLabelFor() 爲無障礙目的,獲取作爲標籤代表該視圖的節點信息。 返回AccessibilityNodeInfo
getLabeledBy() 爲無障礙目的,獲取作爲標籤代表該視圖的節點信息。返回AccessibilityNodeInfo
getLiveRegion() 獲取該節點的實時區域模式。一個實時區域是一個包含對用戶來說重要信息的節點,且當其改變時應該告知用戶。例如,在一個登錄界面,有一個呈現“密碼錯誤”通知的 TextView,該視圖應該使用ACCESSIBILITY_LIVE_REGION_POLITE模式被標記爲一個實時區域。這是無障礙服務的責任,控制TYPE_WINDOW_CONTENT_CHANGED 事件標識實時區域節點和其子元素的變化。實時區域模式,或如果視圖不是個實時區域,返回ACCESSIBILITY_LIVE_REGION_NONE。
getMaxTextLength() 返回該節點的最大文本長度。
getMovementGranularities() 獲取遍歷該節點文本的移動粒度。
getPackageName() 獲取該節點來自的包名。
getParent() 獲取父級NodeInfo。
getRangeInfo() 如果節點是個範圍,獲取範圍信息AccessibilityNodeInfo.RangeInfo
getText() 獲取該節點的文本。
getTextSelectionEnd() 選擇文本的末尾,如果沒有選擇文本,返回光標位置,或如果不存在選擇文本和光標,返回-1。
getTextSelectionStart() 選擇文本的起始,如果沒有選擇文本,返回光標位置,或如果不存在選擇文本和光標,返回-1。
getViewIdResourceName() 獲取源視圖 id 的完全合格源名稱。
getWindowId() 獲取該信息來自的窗口的id。
hashCode() 返回該對象的哈希編碼值。多用於判斷node是否相同
isAccessibilityFocused() 獲取該節點是否可被無障礙聚焦。
isCheckable() 獲取該節點是否可選中。
isChecked() 獲取該節點是否已選中。
isClickable() 獲取該節點是否可點擊。
isContentInvalid() 獲取該節點的內容是否已失效。例如,一個日期數據格式不正確。
isDismissable() 獲取該節點是否可被關閉。
isEditable() 獲取該節點是否可編輯。
isEnabled() 獲取該節點是否可用。
isFocusable() 獲取該節點是否可獲取焦點。
isFocused() 獲取該節點是否已被聚焦。
isLongClickable() 獲取該節點是否可長按點擊。
isMultiLine() 獲取該節點是否是個多行可編輯文本。
isPassword() 獲取該節點是否是個密碼。
isScrollable() 獲取該節點是否可滾動。
isSelected() 獲取該節點是否已被選擇。
isVisibleToUser() 該節點是否對用戶可見。
obtain(View root, int virtualDescendantId) 如果可獲得,返回一個緩存實例,否則創建一個新的並設置源。 View:虛擬子樹的根。 int:虛擬後代的id。返回一個實例化的AccessibilityNodeInfo
obtain(AccessibilityNodeInfo info) 如果可獲得,返回一個緩存實例,或創建一個新的。返回的實例初始化自一個給定 root。
obtain() 如果可獲得,返回一個緩存實例,否則,返回一個新的。
obtain(View source) 如果可獲得,返回一個緩存實例,否則,返回一個新的並設置源。View:源視圖。
performAction(int action, Bundle arguments) 在該節點上執行一個操作。int: 要執行的操作。Bundle:具有額外參數的包。返回一個布爾值,表示是否成功執行操作。
performAction(int action) 在該節點上執行一個操作。
recycle() 返回一個實例重複使用,回收掉當前的實例。
refresh() 刷新視圖呈現的最新狀態信息。返回一個布爾值,表示是否刷新成功。
removeAction(int action) 該方法在 API 級別 21 被棄用。
setAccessibilityFocused(boolean focused) 設置該節點可無障礙聚焦。
setBoundsInParent(Rect bounds) 在父級座標中設置節點邊界。
setBoundsInScreen(Rect bounds) 在屏幕座標中設置節點邊界。
setCanOpenPopup(boolean opensPopup) 設置該節點可打開一個彈窗或對話框。
setCheckable(boolean checkable) 設置該節點可選中。
setChecked(boolean checked) 設置該節點已選中。
setClassName(CharSequence className) 設置該節點來自的類。
setClickable(boolean clickable) 設置該節點可點擊。
setCollectionInfo(AccessibilityNodeInfo.CollectionInfo collectionInfo) 如果該節點是個集合,設置集合信息。一個集合子集通常也是個集合項目。
setContentDescription(CharSequence contentDescription) 設置該節點的內容描述。
setContentInvalid(boolean contentInvalid) 設置節點內容無效。例如,一個日期數據格式不正確。
setContextClickable(boolean contextClickable) 設置該節點文本可點擊。
setDismissable(boolean dismissable) 設置該節點可以被關閉。
setEditable(boolean editable) 設置該節點可編輯。
setEnabled(boolean enabled) 設置該節點可用。
setFocusable(boolean focusable) 設置該節點可聚焦。
setFocused(boolean focused) 設置該節點已聚焦。
setInputType(int inputType) 設置源中的輸入類型爲inputType
setLabelFor(View root, int virtualDescendantId) 爲無障礙目的,設置可作爲標籤代表視圖的信息。如果 virtualDescendantId 爲NO_ID,根被設置爲標籤。一個虛擬後代是一個虛構視圖,爲無障礙目的,將自己報告爲視圖層次的一部分。該操作可以使繪製複雜內容的自定義視圖,將自己報告爲虛擬視圖樹,然後傳遞其邏輯結構。
setLabelFor(View labeled) 爲無障礙目的,設置可作爲標籤代表視圖的信息。
setLabeledBy(View label) 爲無障礙目的,設置可作爲標籤代表視圖的信息。
setLabeledBy(View root, int virtualDescendantId) 爲無障礙目的,設置可作爲標籤代表視圖的信息。如果 virtualDescendantId 爲NO_ID,根被設置爲標籤。一個虛擬後代是一個虛構視圖,爲無障礙目的,將自己報告爲視圖層次的一部分。該操作可以使繪製複雜內容的自定義視圖,將自己報告爲虛擬視圖樹,然後傳遞其邏輯結構。
setLiveRegion(int mode) 設置該節點的實時區域模式。int:實時區域模式,或如果視圖不是個實時區域時,爲ACCESSIBILITY_LIVE_REGION_NONE。
setLongClickable(boolean longClickable) 設置該節點可長按點擊。
setMaxTextLength(int max) 設置最大文本長度,或無限制時爲-1。一般情況下,用來標識一個可編輯文本框有輸入字符數目限制。
getMovementGranularities() 設置遍歷節點文本的移動粒度。
setMultiLine(boolean multiLine) 設置該節點爲一個多行可編輯文本。
setPackageName(CharSequence packageName) 設置該節點來自的包。
setParent(View root, int virtualDescendantId) 設置給定 root 虛擬後代的父元素。如果 virtualDescendantId 等於 NO_ID,該root 被設置爲父級。一個虛擬後代是一個虛構視圖,爲無障礙目的,將自己報告爲視圖層次的一部分。該操作可以使繪製複雜內容的自定義視圖,將自己報告爲虛擬視圖樹,然後傳遞其邏輯結構。
setParent(View parent) 設置父元素。
setPassword(boolean password) 設置該節點爲密碼。
setRangeInfo(AccessibilityNodeInfo.RangeInfo rangeInfo) 如果該節點是個範圍,設置範圍信息。
setScrollable(boolean scrollable) 設置該節點可滾動。
setSelected(boolean selected) 設置該節點是否已選擇。
setSource(View source) 設置信息源。
setSource(View root, int virtualDescendantId) 爲給定 root 虛擬後代設置源。如果 virtualDescendantId 等於 NO_ID,該 root被設置爲源。一個虛擬後代是一個虛構視圖,爲無障礙目的,將自己報告爲視圖層次的一部分。該操作可以使繪製複雜內容的自定義視圖,將自己報告爲虛擬視圖樹,然後傳遞其邏輯結構。
setText(CharSequence text) 設置該節點的文本。
setTextSelection(int start, int end) 設置文本選擇的起始和結尾。
setViewIdResourceName(String viewIdResName) 設置源視圖id的資源名稱
setVisibleToUser(boolean visibleToUser) 設置該節點對用戶可見。
toString() 返回一個代表對象的字符串。 getClass().getName() + '@' + Integer.toHexString(hashCode())
writeToParcel(Parcel parcel, int flags) 封裝該對象到一個包中。
API 21 ADD
getError() API Level 21 獲取該節點的錯誤文本。
setError(CharSequence error) API Level 21 設置該節點的錯誤文本。
getWindow() API Level 21 獲取該節點所屬的窗口。AccessibilityWindowInfo
removeAction(AccessibilityNodeInfo.AccessibilityAction action) API Level 21 移除一個可以在該節點上執行的操作。如果該操作未被添加到該節點,調用該方法沒有任何效果。返回一個布爾值表示是否成功移除操作。
removeChild(View root, int virtualDescendantId) API Level 21 移除給定根節點的一個虛擬子元素。如果子元素不是之前被添加到該節點的,調用該方法無效果。 返回一個布爾值表示是否存在子元素。
removeChild(View child) API Level 21 移除一個子元素。如果子元素先前未被添加到該節點,調用該方法無效果。
API 22 ADD
getTraversalAfter() API Level 22 當前節點被訪問後,獲取無障礙遍歷中的下一個節點。一個屏幕閱讀器必須在訪問該節點內容之前,訪問其他節點的內容。如果存在,返回後續節點,否則,返回 null。
getTraversalBefore() API Level 22 當前節點被訪問後,獲取無障礙遍歷中的上一個節點。屏幕閱讀器必須訪問該節點的信息,在訪問先前節點內容之前。
setTraversalAfter(View view) API Level 22 設置無障礙遍歷中下一個被訪問的視圖。一個屏幕閱讀器在訪問該節點內容之前,必須訪問另一個節點的內容。
setTraversalAfter(View root, int virtualDescendantId) API Level 22設置無障礙遍歷中下一個被訪問的視圖。一個屏幕閱讀器在訪問該節點內容之前,必須訪問另一個節點的內容。如果 virtualDescendantId 等於 NO_ID,root被設置爲前任。一個虛擬後代是一個虛構視圖,爲無障礙目的,將自己報告爲視圖層次的一部分。該操作可以使繪製複雜內容的自定義視圖,將自己報告爲虛擬視圖樹,然後傳遞其邏輯結構。
setTraversalBefore(View view) API Level 22 設置無障礙遍歷中當前訪問節點的上一個視圖。一個屏幕閱讀器在訪問上一個節點之前,必須訪問該節點的內容。
setTraversalBefore(View root, int virtualDescendantId) API Level 22 設置無障礙遍歷中當前訪問節點的上一個視圖。一個屏幕閱讀器在訪問上一個節點之前,必須訪問該節點的內容。如果virtualDescendantId 等於 NO_ID,root被設置爲後任。一個虛擬後代是一個虛構視圖,爲無障礙目的,將自己報告爲視圖層次的一部分。該操作可以使繪製複雜內容的自定義視圖,將自己報告爲虛擬視圖樹,然後傳遞其邏輯結構。
API 23 ADD
isContextClickable() API Level 23 獲取該節點是否上下文可點擊。
API 24 ADD
setImportantForAccessibility(boolean important) API Level 24 設置該節點對無障礙很重要。
setDrawingOrder(int drawingOrderInParent) API Level 24 設置該節點相關視圖的繪製順序。
getDrawingOrder() API Level 24。獲取該節點中視圖的相對繪製順序。繪製順序只決定於節點的父級,所以該索引只與其兄弟姐妹相關。在一些情景下,繪製順序是基本同步的,所以兩個兄弟姐妹的返回值相同是可能的。返回值會被跳過也是可能的。
isImportantForAccessibility() API Level 24 返回該節點是否來源於一個對無障礙相當重要的視圖。

performGlobalAction

Action 釋義
GLOBAL_ACTION_BACK 相當於點擊物理按鍵返回
GLOBAL_ACTION_HOME 相當於點擊物理按鍵Home鍵
GLOBAL_ACTION_NOTIFICATIONS 相當於下滑打開通知
GLOBAL_ACTION_RECENTS 相當於點擊物理按鍵最近任務鍵
GLOBAL_ACTION_QUICK_SETTINGS 打開快速設置
GLOBAL_ACTION_POWER_DIALOG 打開長按電源鍵的彈框

2.1.5 自定義AccessibilityService類的常規使用


 
  1. public class MyAccessibilityService extends AccessibilityService {

  2.  
  3. @Override

  4. protected void onServiceConnected() {

  5. super.onServiceConnected();

  6. }

  7.  
  8. @Override

  9. public void onAccessibilityEvent(AccessibilityEvent event) {

  10. // 1.AccessibilityEvent中一些常用的使用方法

  11. // 這裏我們獲取到該輔助功能的事件類型

  12. // 事件類型請參照 2.1.3中AccessibilityEventTypes表

  13. int eventType = event.getEventType();

  14. // 輸出事件的字符串type

  15. String typeStr = event.eventTypeToString(eventType);

  16. // 根據事件類型來分發我們的需要的操作,這裏以窗口變化爲例

  17. if(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED == eventType){

  18. // 判斷我們的輔助功能是否在約定好的應用界面執行,以設置界面爲例

  19. if("com.android.settings".equals(event.getPackageName()){

  20. // doSomeThing

  21. }

  22. } else if(AccessibilityEvent.TYPE_GESTURE_DETECTION_START == eventType) {

  23. // 在監測到手勢的時候

  24. } else {

  25. // 在完成操作時,可以關閉自己的服務,下次使用再次開啓。

  26. // API > = 24

  27. disableSelf();

  28. }

  29.  
  30. // 2.通過event來遍歷我們的nodeInfo

  31. if (VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2)

  32. // 這裏使用getResource()方法其實是從AccessibilityEvent繼承的

  33. // AccessibilityRecord中抽取AccessibilityNodeInfo

  34. // 實際調用的是AccessibilityRecord中的方法,返回的是AccessibilityNodeInfo mSourceNode

  35. AccessibilityNodeInfo info = event.getSource();

  36. else

  37. info = getRootInActiveWindow();

  38.  
  39. // 3.遍歷info中的子節點

  40. if (info.getChildCount() != 0){

  41. // 通過一個循環將info的子節點遍歷

  42. for (int i = 0; i < info.getChildCount(); i++) {

  43. // 獲取子節點中某個特定的node,這裏通過以下方法通過ID查找

  44. List<AccessibilityNodeInfo> list = info.findAccessibilityNodeInfosByViewId("com.android" +".settings:id/xxxx");

  45. // 通過text查找

  46. List<AccessibilityNodeInfo> list = info.findAccessibilityNodeInfosByText("xxxx");

  47. // 打印nodeinfo的信息

  48. Log.e("InfoType: " + info.getClassName());

  49. Log.e("InfoText: " + info.getText());

  50. Log.e("InfoPkgName: " + info.getPackageName());

  51. Log.e("InfoViewId: " + info.getViewIdResourceName());

  52. }

  53. }

  54.  
  55. // 4.爲節點添加操作

  56. // 1) 首先獲取到我們的節點

  57. AccessibilityNodeInfo info = event.getSource();

  58. // 2) 通過查找指定的ID、text來查找一個系列的節點,返回一個list,需要判斷list.size()是否爲空

  59. List<AccessibilityNodeInfo> list = info.findAccessibilityNodeInfosByViewId("pkgName." + "id");

  60. AccessibilityNodeInfo info = list.get(0);

  61. // 3) 爲節點添加操作,點擊事件(事件可參照AccessibilityNodeInfo表)

  62. info.performAction(AccessibilityNodeInfo.ACTION_CLICK);

  63. // 4) 添加node可用的action,給node添加一個可清除焦點的操作

  64. // 通過addAction(AccessibilityNodeInfo.AccessibilityAction action)

  65. info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_CLEAR_FOCUS);

  66. // 獲取該node上可用的action屬性list,可以用來查看該node的屬性

  67. List<AccessibilityNodeInfo.AccessibilityAction> listAction = info.getActionList();

  68.  
  69. // 5.獲取該節點上子節點個數

  70. int childCount = info.getChildCount();

  71.  
  72. // 6.操作完成後,回收實例,返回一個下次可用的實例

  73. info.recycle();

  74.  
  75. // 需要注意的是,在node.performAction之後,調用本地廣播的話,之後的globeAction不會起作用,例:

  76. sureStopNode.performAction(AccessibilityNodeInfo.ACTION_CLICK);

  77. sureStopNode.recycle();

  78. SystemMessage.getInstance().send(SystemMessage.ACTION_POWER_BOOSTER_NEXT);

  79. performGlobalAction();// 這句話是不起作用的

  80.  
  81. // 7.輔助功能的一些適用場景:

  82. // 1)部分應用中獲取短信驗證碼(通過開啓輔助功能的方式獲取)

  83. // - 監聽通知欄的消息(typeNotificationStateChanged)

  84. // - 彈出通知欄的時候獲取該通知的節點信息(event.getSource())

  85. // - 遍歷root節點,取得顯示信息的文本Node(info.findAccessibilityNodeInfosByViewId("pkgName." + "id"))

  86. // - 通過NodeInfo.getText()方法獲取到相應的文本信息,並取出驗證碼

  87. // - 取消掉通知欄彈出框

  88. // - 獲取到要輸入的EditText獲取直接在本應用給需要填寫驗證碼的區域設置文本。

  89.  
  90. // 2)部分應用中恢復APP的初始設置(清除APP的數據)

  91. // - 跳轉到應用詳情,通過findAccessibilityNodeInfosByViewId查找節點

  92. // - 通過節點info.performAction(AccessibilityNodeInfo.ACTION_CLICK)點擊清除

  93. // - 彈出確定對話框,同上方式找到確定節點,點擊後返回

  94.  
  95. // 3)監測應用是否在前臺,APP的啓動(通過windowstatechange事件獲取到當前的event的pkgName)

  96. // - 通過接收typeWindowStateChanged事件,獲取event的pkgName確定哪個應用啓動或者在最上層顯示(懸浮窗不適用)

  97.  
  98. // 4)自動安裝與卸載軟件

  99. // - 同3,尋找相應的節點,點擊事件

  100.  
  101. // 5)自動化UI測試

  102.  
  103. // 6)最常見的搶紅包

  104.  
  105. // 7)通過輔助功能開啓一些權限(不需要用戶手動點擊開啓了)

  106. // - 在用戶確定需要開啓權限時,自動跳轉,尋找相應的開關按鈕

  107. // - 需要注意的是,部分開關(switch button, checkbox)可能沒有ID,需要通過info.getClassName()來判斷,屬於那種類型的view。

  108. }

  109.  
  110. @Override

  111. public void onInterrupt() {

  112. }

  113.  
  114. }

需要重寫的一些方法:

  • onServiceConnected() 該方法在初始化輔助功能服務時調用,可以在這時做相應的初始化工作。
  • onAccessibilityEvent() 在獲取到指定的監聽事件時,通過回調這個方法來進行對應的操作
  • onInterrupt() 系統想要中斷輔助功能時會調用該方法

當然service中的onUnbind()方法也同樣適用,在onUnbind()中釋放一些資源也是可以的。

Note: 這裏需要了解的是輔助功能最重要的就是手機機型的適配。由於各個廠商的系統不一樣,導致了我們在獲取一些節點時,需要的節點ID不同(通過ID獲取節點時一種比較高效的方式)。而我們一般通過Device Monitor中的Hierarchy View獲取節點信息。同時在此方式下,很多手機沒法獲取到節點信息,我們就需要使用添加flagReportViewIds進行手動遍歷界面節點的方式獲取nodeInfo。

以上是輔助功能常規使用以及使用場景的介紹。下面爲輔助功能的註冊。


 
  1. <service

  2. android:name=".我們自己繼承自AccessibilityService的類"

  3. android:label="@string/app_name"

  4. android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">

  5. <intent-filter>

  6. <action android:name="android.accessibilityservice.AccessibilityService"/>

  7. </intent-filter>

  8.  
  9. <meta-data

  10. android:name="android.accessibilityservice"

  11. android:resource="@xml/第二個輔助功能配置方式的文件,存放在xml下"/>

  12. </service>


2.2 API > 20 新增方法,接口(預覽版)使用探究:

2.2.1 AccessibilityService新增方法一覽:

API 21:

Method 描述
getWindows() 返回窗口最上層的一個用戶可交互的窗口信息節點 List<AccessibilityWindowInfo>

獲取屏幕上的窗口。
返回一個有目標的用戶可以與之進行交互的窗口,而不是所有的窗口。

爲了訪問Windows,服務必須通過在其元數據中設置AccessibilityService_canRetrieveWindowContent屬性來聲明檢索窗口內容的功能。此外,服務必須選擇通過設置FLAG_RETRIEVE_INTERACTIVE_WINDOWS標誌來檢索交互式窗口。

使用此方法來獲取我們屏幕上最上層的一個窗口根節點。

API 24:

Method 描述
getSoftKeyboardController() 返回軟鍵盤控制器,可用於查詢和修改軟鍵盤顯示模式。

返回AccessibilityService.SoftKeyboardController其中可以使用添加addOnShowModeChangedListener()的方式來進行對鍵盤的顯示隱藏狀態監聽,通過getShowMode()獲取到軟鍵盤的顯示隱藏狀態,setShowMode(int showMode)設置軟鍵盤的顯示隱藏狀態。

Method 描述
disableSelf() 關閉自己service的方法,在設置界面可以看到輔助功能狀態被關閉

通過在服務中調用該方法可以將自己的服務停止,同時在輔助功能開啓界面上的開關也會隨之關閉。

Method 描述
dispatchGesture(GestureDescription gesture, AccessibilityService.GestureResultCallback callback, Handler handler) 將手勢發送到觸摸屏。

可以通過設定GestureDescription將手勢的軌跡顯示在觸摸屏上,同時可以通過GestureResultCallback回調獲得事件的完成情況。

Method 描述
findFocus(int focus) 找到具有指定焦點類型的視圖。

這裏的焦點類型有FOCUS_INPUTFOCUS_ACCESSIBILITY分別代表了輸入焦點和無障礙重點。
FOCUS_ACCESSIBILITY這個焦點,是需要使用setAccessibilityFocused(boolean isFocus)方法進行設置過得焦點。

需要注意的是:如果要使用該方法的話,需要先設置AccessibilityService_canRetrieveWindowContent同時添加一個flag:FLAG_RETRIEVE_INTERACTIVE_WINDOWS

Method 描述
getMagnificationController() 返回放大控制器,可用於查詢和修改顯示放大的狀態。

返回:AccessibilityService.MagnificationController。爲了控制放大倍數,輔助功能服務必須通過在其元數據中設置AccessibilityService_canControlMagnification屬性來聲明該功能。

API 26:

Method 描述
getAccessibilityButtonController() 系統導航區域內的輔助功能按鈕控制器

返回:AccessibilityButtonController

當設置FLAG_REQUEST_ACCESSIBILITY_BUTTON時,此類可用於查詢輔助功能按鈕的狀態並註冊回調以進行交互,並對可訪問性按鈕進行狀態更改。

注意:此類和FLAG_REQUEST_ACCESSIBILITY_BUTTON不應該被用作通過AccessibilityService爲用戶提供功能的唯一手段。 一些設備實現可以選擇不提供軟件呈現的系統導航區域,使得該功能永久不可用。

注意:在支持輔助功能按鈕的設備實現中,它可能始終不可用,例如前臺應用程序使用SYSTEM_UI_FLAG_HIDE_NAVIGATION時。 用戶還可以選擇將該按鈕分配給另一個可訪問性服務或功能。 在每種情況下,將調用註冊的AccessibilityButtonController.AccessibilityButtonCallback的onAvailabilityChanged(AccessibilityButtonController,boolean)方法來提供對可訪問性按鈕對註冊服務的可用性的更改的通知。

注意底部導航欄的小人:

 

image

下面是一個簡單的用例:


 
  1. public class MyAccessibilityService extends AccessibilityService {

  2.  
  3. @Override

  4. protected void onServiceConnected() {

  5. super.onServiceConnected();

  6. AccessibilityServiceInfo info = new AccessibilityServiceInfo();

  7. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {

  8. info.flags = AccessibilityServiceInfo.FLAG_REQUEST_ACCESSIBILITY_BUTTON;

  9. } else {

  10. info.flags = AccessibilityServiceInfo.FLAG_REPORT_VIEW_IDS;

  11. }

  12. info.eventTypes = AccessibilityEvent.TYPES_ALL_MASK;

  13. info.feedbackType = AccessibilityServiceInfo.FEEDBACK_GENERIC;

  14. info.notificationTimeout = 100;

  15. setServiceInfo(info);

  16. }

  17.  
  18. @Override

  19. public void onAccessibilityEvent(AccessibilityEvent event) {

  20. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {

  21. AccessibilityButtonController mAccessibilityButtonController = getAccessibilityButtonController();

  22. mAccessibilityButtonController.registerAccessibilityButtonCallback(new AccessibilityButtonController.AccessibilityButtonCallback() {

  23. @Override

  24. public void onClicked(AccessibilityButtonController controller) {

  25. super.onClicked(controller);

  26. // 底部導航欄中輔助功能按鈕點擊事件回調

  27. Toast.makeText(MyAccessibilityService.this, "on Click", Toast.LENGTH_SHORT).show();

  28. }

  29.  
  30. @Override

  31. public void onAvailabilityChanged(AccessibilityButtonController controller, boolean available) {

  32. super.onAvailabilityChanged(controller, available);

  33. // 輔助功能可用性改變的回調。返回了輔助功能底部按鈕是否可用的布爾值,和按鈕控制器

  34. // available = true 表示該按鈕對本服務可用

  35. // available = false 是由於設備顯示了按鈕,或按鈕被分配到另一個服務或其他原因。

  36. }

  37. });

  38. }

  39. }

  40.  
  41. @Override

  42. public void onInterrupt() {

  43. }

  44. }

在開啓輔助功能之後,如果是O系統的話,在底部導航欄會出現一個輔助功能的小人。同時這個小人可以接收到點擊事件,和輔助功能可用狀態變化。

Method 描述
getFingerprintGestureController() 返回指紋手勢控制器

指紋手勢控制器:FingerprintGestureController

只要設備具有能夠檢測手勢的傳感器,AccessibilityService可以捕獲在設備的指紋傳感器上執行的手勢。
使用時需要聲明CAPABILITY_CAN_CAPTURE_FINGERPRINT_GESTURES同時需要權限USE_FINGERPRINT,由於沒有真機調試該方法,待Google發佈正式版API後繼續研究

支持的四個事件:

常量 描述
FINGERPRINT_GESTURE_SWIPE_DOWN 指紋手勢下滑。
FINGERPRINT_GESTURE_SWIPE_LEFT 指紋手勢左滑。
FINGERPRINT_GESTURE_SWIPE_RIGHT 指紋手勢右滑。
FINGERPRINT_GESTURE_SWIPE_DOWN 指紋手勢上滑。

公有方法

方法 描述
isGestureDetectionAvailable() 判斷手勢監測是否可用。
registerFingerprintGestureCallback(FingerprintGestureController.FingerprintGestureCallback callback, Handler handler) 通過該方法註冊一個指紋手勢的回調。
unregisterFingerprintGestureCallback(FingerprintGestureController.FingerprintGestureCallback callback) 取消註冊。
registerFingerprintGestureCallback(FingerprintGestureController.FingerprintGestureCallback, Handler) 取消註冊。

其中的FingerprintGestureController.FingerprintGestureCallback與之前的輔助功能按鈕回調基本相同,都只有兩個方法。

方法 描述
onGestureDetected(int gesture) 這裏獲取到相應的手勢。
onGestureDetectionAvailabilityChanged(boolean available) 這裏返回了手勢監測是否可用。

2.2.1 AccessibilityNodeInfo新增方法一覽:

API 21

Method 描述
getError() 獲取該節點的錯誤文本。
setError(CharSequence error) 設置該節點的錯誤文本。

以上兩個方法需要搭配使用。

Method 描述
getWindow() 獲取該節點所屬的窗口(根節點)

通過該方法,我們可以使用一個子節點來重新獲取到我們的根節點。在需要多次操作界面元素的情況下(同時沒有產生windowstatechange事件),我們可以不通過監聽事件來進行下一個節點的操作。

Method 描述
addAction(AccessibilityNodeInfo.AccessibilityAction action) 爲一個nodeInfo添加一個操作,API 21
removeAction(AccessibilityNodeInfo.AccessibilityAction action) 移除一個可以在該節點上執行的操作。
removeChild(View root, int virtualDescendantId) 移除給定根節點的一個虛擬子元素。
removeChild(View child) 移除一個子元素。

第一個addAction(AccessibilityNodeInfo.AccessibilityAction action)方法是API 21時替代API 20中的addAction(int action)方法。
提供了一個在輔助功能外操作節點的方法,該方法不能在輔助功能服務中調用,不然會報錯java.lang.IllegalStateException: Cannot perform this action on a sealed instance.

後三個方法使用的前提都是需要事先在節點中添加了操作,或者視圖,不然都不會起作用。要說明的是removeAction方法也需要在服務外調用,不然也要報錯

API 22

Method 描述
getTraversalAfter() 當前節點被訪問後,獲取無障礙遍歷中的下一個節點。
getTraversalBefore() 當前節點被訪問後,獲取無障礙遍歷中的上一個節點。
setTraversalAfter(View view) 設置無障礙遍歷中下一個被訪問的視圖。一個屏幕閱讀器在訪問該節點內容之前,必須訪問另一個節點的內容。如果 virtualDescendantId 等於 NO_ID,root被設置爲前任。
setTraversalAfter(View root, int virtualDescendantId) 設置無障礙遍歷中下一個被訪問的視圖。
setTraversalBefore(View view) 設置無障礙遍歷中當前訪問節點的上一個視圖。

通過在view的xml屬性中添加android:accessibilityTraversalAfter="+id"方式來進行輔助功能遍歷時的順序後,通過本方法獲取下一個節點。

通過在view的xml屬性中添加android:accessibilityTraversalBefore="+id"方式來進行輔助功能遍歷時的順序,同上。

通過View.setAccessibilityTraversalBefore(+id)方式設置順序。

API 23

Method 描述
isContextClickable() 獲取該節點是否上下文可點擊。

通過View的setContextClickable(Boolean isClickable)方法設置一個View是否可以點擊。然後通過該方法,我們可以獲取到節點上下文的可否點擊狀態。

API 24

Method 描述
setImportantForAccessibility(boolean important) 設置該節點對無障礙很重要。
isImportantForAccessibility() 返回該節點是否來源於一個對無障礙相當重要的視圖。

通過View的XML屬性設置android:importantForAccessibility=""狀態後,我們可以通過本方法獲取到該狀態的boolean值。

Method 描述
setDrawingOrder(int drawingOrderInParent) 設置與此節點對應的視圖的繪圖順序。
getDrawingOrder() 獲取該節點中視圖的相對繪製順序。

同樣的不能在輔助功能服務中調用該方法。
參考ViewGroup.setChildrenDrawingOrderEnabled()中children的繪製順序理解。

返回與該節點對應的視圖相對於其兄弟姐妹的繪圖位置。
返回的數值從1開始,表示相對於父節點中,並列view的繪製順序。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章