?Android輔助功能 轉(zhuǎn)載 2017年10月19日 13:19:40 閱讀 1012 1、前言 Android的輔助功能是個(gè)比較老的API(since API 4),但是該API真正的開始發(fā)展還是在API 16~19(很多常用的方法參數(shù)都是在這幾個(gè)版本逐漸加入以及完善的)版本中。輔助功能我們最常見的是在類似深度休眠,搶紅包中使用,模擬點(diǎn)擊屏幕view。此次寫關(guān)于輔助功能的分享是因?yàn)樵贏PI 24、 API 26中,又增添了幾個(gè)類以及幾個(gè)接口。 本文首先介紹關(guān)于輔助功能的常見使用方法,然后開始介紹輔助功能新增接口以及類的使用。 2、輔助功能的使用 2.1 輔助功能常規(guī)使用方法: 本小結(jié)介紹一般情況下輔助功能的使用(基礎(chǔ)用法和方法釋義較多,如果需要閱覽API > 20 新增方法使用請(qǐng)從2.2開始閱讀),API level在20及以下的使用方式。不涉及新增的方法以及類的使用介紹。 2.1.1 使用流程: 1、Service: 配置自己的輔助功服務(wù)(注冊(cè)、配置) 2、Class: 自己的輔助功能類(對(duì)事件的攔截、處理) 2.1.2 Service配置: 1、在實(shí)例化的輔助功能類中:onServiceConnected()中初始化,如下所示。 @Override protected void onServiceConnected() { super.onServiceConnected(); AccessibilityServiceInfo info = new AccessibilityServiceInfo(); info.eventTypes = AccessibilityEvent.TYPES_ALL_MASK; info.feedbackType = AccessibilityServiceInfo.FEEDBACK_GENERIC; info.notificationTimeout = 100; info.packageNames = new String[]{"...", "..."}; info.flags = AccessibilityServiceInfo.FLAG_REPORT_VIEW_IDS; setServiceInfo(info); } 2、使用manifest中添加meta-data的方式(該方式從API 14開始使用) <?xml version="1.0" encoding="utf-8"?> <accessibility-service xmlns:android="http://schemas./apk/res/android" android:accessibilityEventTypes="" android:accessibilityFeedbackType="" android:accessibilityFlags="" android:canRequestEnhancedWebAccessibility="" android:canRequestFilterKeyEvents="" android:canRequestTouchExplorationMode="" android:canRetrieveWindowContent="" android:description="" android:notificationTimeout="" android:packageNames="" android:settingsActivity="" android:summary="" /> 由上邊兩組代碼可以看到,前一個(gè)配置中單個(gè)代碼塊中,配置屬性有限,但靈活的在服務(wù)里邊初始化,使我們可以隨時(shí)的改變需要的flag和type及一些其他參數(shù)。而后一個(gè)(Android 4.0+ / API 14+)的meta-data配置方式,可配置的屬性更多。在系統(tǒng)條件符合時(shí)(同時(shí)不需要更改我們輔助功能的一些參數(shù)時(shí)),還是推薦使用后一個(gè)配置方式進(jìn)行輔助功能的配置。 2.1.3 AccessibilityServiceInfo 配置參數(shù): 這里只是對(duì)所有的XML attributes進(jìn)行說(shuō)明。 XML attributes: AccessibilityEventTypes 此服務(wù)希望接收的事件類型 constant value 描述 typeAllMask ffffffff 所有類型的事件 typeAnnouncement 4000 一個(gè)應(yīng)用產(chǎn)生一個(gè)通知事件 typeAssistReadingContext 1000000 輔助用戶讀取當(dāng)前屏幕事件 typeContextClicked 800000 view中上下文點(diǎn)擊事件 typeGestureDetectionEnd 80000 監(jiān)測(cè)到的手勢(shì)事件完成 typeGestureDetectionStart 40000 開始手勢(shì)監(jiān)測(cè)事件 typeNotificationStateChanged 40 收到notification彈出消息事件 typeTouchExplorationGestureEnd 400 觸摸瀏覽事件完成 typeTouchExplorationGestureStart 200 觸摸瀏覽事件開始 typeTouchInteractionEnd 200000 用戶觸屏事件結(jié)束 typeTouchInteractionStart 100000 觸摸屏幕事件開始 typeViewAccessibilityFocusCleared 10000 無(wú)障礙焦點(diǎn)事件清除 typeViewAccessibilityFocused 8000 獲得無(wú)障礙的焦點(diǎn)事件 typeViewClicked 1 點(diǎn)擊事件 typeViewFocused 8 view獲取到焦點(diǎn)事件 typeViewHoverEnter 80 一個(gè)view的懸停事件 typeViewHoverExit 100 一個(gè)view的懸停事件結(jié)束,懸停離開該view typeViewLongClicked 2 view的長(zhǎng)按事件 typeViewScrolled 1000 view的滾動(dòng)事件,adapterview、scrollview typeViewSelected 4 view選中,一般是具有選中屬性的view,例如adapter typeViewTextChanged 10 edittext中文字發(fā)生改變的事件 typeViewTextSelectionChanged 2000 edittext文字選中發(fā)生改變事件 typeViewTextTraversedAtMovementGranularity 20000 UIanimator中在一個(gè)視圖文本中進(jìn)行遍歷會(huì)產(chǎn)生這個(gè)事件,多個(gè)粒度遍歷文本。一般用于語(yǔ)音閱讀context typeWindowContentChanged 800 窗口的內(nèi)容發(fā)生變化,或者更具體的子樹根布局變化事件 typeWindowStateChanged 20 新的彈出層導(dǎo)致的窗口變化(dialog、menu、popupwindow) typeWindowsChanged 400000 屏幕上的窗口變化事件,需要API 21+ accessibilityFeedbackType 此服務(wù)提供的反饋類型 constant value 描述 feedbackAllMask ffffffff 取消所有的可用反饋方式 feedbackAudible 4 可聽見的(非語(yǔ)音反饋) feedbackGeneric 10 通用反饋 feedbackHaptic 2 觸覺反饋(震動(dòng)) feedbackSpoken 1 語(yǔ)音反饋 feedbackVisual 8 視覺反饋 accessibilityFlags 輔助功能附加的標(biāo)志,多個(gè)使用 ' | '分隔 constant value 描述 flagDefault 1 默認(rèn)的配置 flagEnableAccessibilityVolume 80 這個(gè)標(biāo)志要求系統(tǒng)內(nèi)所有的音頻通道,使用由STREAM_ACCESSIBILTY音量控制USAGE_ASSISTANCE_ACCESSIBILITY flagIncludeNotImportantViews 2 表示可獲取到一些被表示為輔助功能無(wú)權(quán)獲取到的view flagReportViewIds 10 使用該flag表示可獲取到view的ID flagRequestAccessibilityButton 100 如果輔助功能可用,提供一個(gè)輔助功能按鈕在系統(tǒng)的導(dǎo)航欄 API 26+ flagRequestEnhancedWebAccessibility 8 此類擴(kuò)展的目的是為WebView中呈現(xiàn)的內(nèi)容提供更好的輔助功能支持。這種擴(kuò)展的一個(gè)例子是從一個(gè)安全的來(lái)源注入JavaScript。如果至少有一個(gè)具有此標(biāo)志的輔助功能服務(wù), 則系統(tǒng)將使能增強(qiáng)的web輔助功能。因此, 清除此標(biāo)志并不保證該設(shè)備不會(huì)使能增強(qiáng)的web輔助功能, 因?yàn)榭赡苡辛硪粋€(gè)使能的服務(wù)在使用它。 flagRequestFilterKeyEvents 20 能夠監(jiān)聽到系統(tǒng)的物理按鍵 flagRequestFingerprintGestures 200 監(jiān)聽系統(tǒng)的指紋手勢(shì) API 26+ flagRequestTouchExplorationMode 4 系統(tǒng)進(jìn)入觸控探索模式。出現(xiàn)一個(gè)鼠標(biāo)在用戶的界面 flagRetrieveInteractiveWindows 40 該標(biāo)志知識(shí)的輔助服務(wù)要訪問(wèn)所有交互式窗口內(nèi)容的系統(tǒng),這個(gè)標(biāo)志沒有被設(shè)置時(shí),服務(wù)不會(huì)收到TYPE_WINDOWS_CHANGE事件。 canRequestEnhancedWebAccessibility (boolean) 輔助功能服務(wù)是否能夠請(qǐng)求WEB輔助增強(qiáng)的屬性。例如: 安裝腳本以使應(yīng)用程序內(nèi)容更易于訪問(wèn)。 canRequestFilterKeyEvents (boolean) 輔助功能服務(wù)是否能夠請(qǐng)求過(guò)濾KeyEvent的屬性,是否可以請(qǐng)求KeyEvent事件流。,flagRequestFilterKeyEvents搭配使用 canRequestTouchExplorationMode (boolean) 此屬性用于,能夠讓輔助功能服務(wù)通過(guò)手勢(shì),來(lái)請(qǐng)求觸摸瀏覽模式,其被觸摸的項(xiàng),將被朗讀出來(lái),flagRequestTouchExplorationMode搭配使用 canRetrieveWindowContent (boolean) 輔助功能服務(wù)是否能夠取回活動(dòng)窗口內(nèi)容的屬性。 與上邊的flagRetrieveInteractiveWindows搭配使用,無(wú)法在運(yùn)行時(shí)更改此設(shè)置。 description 輔助功能服務(wù)目的或行為的簡(jiǎn)短描述。 notificationTimeout 同一類型的兩個(gè)輔助功能事件發(fā)送到服務(wù)的最短間隔(毫秒,兩個(gè)輔助功能事件之間的最小周期) packageNames 從此服務(wù)能接收到事件的軟件包名稱 (不適合所有軟件包)(多個(gè)軟件包用逗號(hào)分隔)。 settingsActivity 允許用戶修改輔助功能的activity組件名稱 summary 同description 2.1.4 實(shí)現(xiàn)自己的輔助功能類: 首先需要了解的是AccessibilityService這個(gè)類。 Public方法有: Method 描述 API 20 getRootInActiveWindow() 獲取窗體中的節(jié)點(diǎn)信息。 返回 AccessibilityNodeInfo getServiceInfo() 獲取本服務(wù)的配置信息。 返回 AccessibilityServiceInfo getSystemService(String name) 通過(guò)服務(wù)名獲取對(duì)應(yīng)的系統(tǒng)服務(wù)。 返回 Object onAccessibilityEvent(AccessibilityEvent event) 輔助功能事件(s)回調(diào)方法 onBind(Intent intent) service的bind接口 onInterrupt() 輔助功能中斷的回調(diào) performGlobalAction(int action) 全局的點(diǎn)擊方法 setServiceInfo(AccessibilityServiceInfo info) 設(shè)置該輔助功能服務(wù)的描述,修改輔助功能的配置??赏ㄟ^(guò)搭配使用getServiceInfo()動(dòng)態(tài)修改我們輔助功能的配置 API 21新增: getWindows() 返回窗口最上層的一個(gè)用戶可交互的窗口信息節(jié)點(diǎn) List<AccessibilityWindowInfo> API 24新增: disableSelf() 關(guān)閉自己service的方法,在設(shè)置界面可以看到輔助功能狀態(tài)被關(guān)閉 getSoftKeyboardController() 返回軟鍵盤控制器,可用于查詢和修改軟鍵盤顯示模式。 findFocus(int focus) 找到具有指定焦點(diǎn)類型的視圖。搜索在所有窗口中執(zhí)行。注意:為了訪問(wèn)Windows,您的服務(wù)必須通過(guò)在其元數(shù)據(jù)中設(shè)置AccessibilityService_canRetrieveWindowContent屬性來(lái)聲明檢索窗口內(nèi)容的功能。有關(guān)詳細(xì)信息,請(qǐng)參閱SERVICE_META_DATA。此外,服務(wù)必須選擇通過(guò)設(shè)置FLAG_RETRIEVE_INTERACTIVE_WINDOWS標(biāo)志來(lái)檢索交互式窗口。否則,搜索將僅在活動(dòng)窗口中執(zhí)行。 getMagnificationController() 返回放大控制器,可用于查詢和修改顯示放大的狀態(tài)。注意:為了控制放大倍數(shù),您的服務(wù)必須通過(guò)在其元數(shù)據(jù)中設(shè)置AccessibilityService_canControlMagnification屬性來(lái)聲明該功能 dispatchGesture(GestureDescription ge, GestureResultCallback cb, Handler handler) 將手勢(shì)發(fā)送到觸摸屏。目前正在進(jìn)行的任何手勢(shì)(無(wú)論是從用戶,本服務(wù)還是其他服務(wù))將被取消。 手勢(shì)將被調(diào)度,就像在用戶直接在屏幕上執(zhí)行的一樣,因此事件可能會(huì)受到諸如放大和觸摸探索之類的功能的影響。 API 26新增: getAccessibilityButtonController() 返回系統(tǒng)導(dǎo)航區(qū)域中可訪問(wèn)性按鈕的控制器。當(dāng)設(shè)置FLAG_REQUEST_ACCESSIBILITY_BUTTON時(shí),此實(shí)例可用于查詢輔助功能按鈕的狀態(tài)并注冊(cè)監(jiān)聽器以進(jìn)行交互和輔助功能按鈕的狀態(tài)更改。返回 AccessibilityButtonController getFingerprintGestureController() 獲取控制器的指紋手勢(shì)。此功能需要 AccessibilityServiceInfo#CAPABILITY_CAN_CAPTURE_FINGERPRINT_GESTURES。注意:在調(diào)用此方法之前,必須先啟動(dòng)該服務(wù)。返回 FingerprintGestureController 這部分我們只針對(duì)API <= 20部分的代碼,其中我們常用的方法有: Method 描述 getRootInActiveWindow() 獲取窗體中的節(jié)點(diǎn)信息 AccessibilityNodeInfo,如果需要使用該方法,我們需要在配置中申明 canRetrieveWindowContent,否則可能獲取不到窗體的節(jié)點(diǎn)信息。AccessibilityNodeInfo onAccessibilityEvent(AccessibilityEvent event) 輔助功能事件(s)回調(diào)方法,處理輔助功能內(nèi)所有事件的回調(diào)方法 performGlobalAction(int action) 全局的點(diǎn)擊方法 在使用這些方法時(shí),有三個(gè)需要我們了解的地方: AccessibilityEvent 在輔助功能event回調(diào)方法中,返回的參數(shù)。(官方API En) AccessibilityNodeInfo 輔助功能中的節(jié)點(diǎn)對(duì)象(nodeInfo)。(官方API En) performGlobalAction(action) 全局事件發(fā)送方法(物理按鍵的點(diǎn)擊) AccessibilityEvent 當(dāng)用戶界面發(fā)生某些明顯的事件時(shí),AccessibilityEvent代表的無(wú)障礙事件會(huì)被系統(tǒng)發(fā)送,每一種事件類型是由該類暴露出的屬性子集表示其特征的。在此類中為每一種事件類型定義了相應(yīng)的常量。詳細(xì)的事件類型請(qǐng)參照AccessibilityEvent文檔 Zh。 Public Methods 公有方法: Method 描述 appendRecord(AccessibilityRecord record) 將AccessibilityRecord(AccessibilityRecord使用pdf文檔 Zh)追加到事件記錄的結(jié)尾。 getRecord(int index) 獲取給定索引下的記錄。 getRecordCount() 獲取被包含在事件中的記錄數(shù)。 describeContents() 描述被包含在 Parcelable 實(shí)例的編組表示中的特殊對(duì)象種類。例如,如果對(duì)象在 writeToParcel(Parcel, int)的輸出里包括一個(gè)文件描述符,該方法的返回值必須包括 CONTENTS_FILE_DESCRIPTOR 位。 getEventType() 獲取事件類型。 setEventType(int eventType) 設(shè)置事件類型。 eventTypeToString(int eventType) 返回一個(gè)事件類型的字符串表示。例如,TYPE_VIEW_CLICKED 的字符串表示為“TYPE_VIEW_CLICKED”。 getAction() 獲取觸發(fā)該事件的執(zhí)行操作。 getContentChangeTypes() 獲取由 TYPE_WINDOW_CONTENT_CHANGED 事件標(biāo)識(shí)的改變類型的位掩碼。一個(gè)單一事件可能代表多種變化類型。 getEventTime() 獲取該事件的發(fā)送時(shí)間。 setEventTime(long eventTime) 設(shè)置事件被發(fā)送的時(shí)間。 getMovementGranularity() 獲取遍歷的移動(dòng)粒度。 setMovementGranularity(int granularity) 設(shè)置遍歷的移動(dòng)粒度。 getPackageName() 獲取源的包名。 setPackageName(CharSequence packageName) 設(shè)置源的包名。 initFromParcel(Parcel parcel) 從 Parcel 創(chuàng)建一個(gè)新實(shí)例。 obtain(AccessibilityEvent event) 如果可獲得,返回一個(gè)緩存實(shí)例或創(chuàng)建一個(gè)新實(shí)例。返回實(shí)例從給定事件初始化。 obtain() 如果可獲得,返回一個(gè)緩存實(shí)例或?qū)嵗粋€(gè)新的。 obtain(int eventType) 如果可獲得,返回一個(gè)緩存實(shí)例或?qū)嵗粋€(gè)新的并設(shè)置它的類型屬性。 recycle() 回收一個(gè)實(shí)例重復(fù)使用。 setAction(int action) 設(shè)置觸發(fā)此事件的執(zhí)行操作。 setContentChangeTypes(int changeTypes) 設(shè)置由一個(gè) TYPE_WINDOW_CONTENT_CHANGED 事件標(biāo)識(shí)的節(jié)點(diǎn)樹改變的位掩碼。 toString() 返回對(duì)象的字符串表示。一般情況下,toString 方法返回一個(gè)“文本表示”該對(duì)象的字符串。結(jié)果應(yīng)該是一個(gè)簡(jiǎn)潔但容易閱讀的信息表示。建議所有子類重寫該方法。 writeToParcel(Parcel parcel, int flags) 整組該對(duì)象到一個(gè) Parcel。 AccessibilityNodeInfo 該類代表一個(gè)窗口內(nèi)容節(jié)點(diǎn)和可以從源請(qǐng)求的操作。從 AccessibilityService的角度看,一個(gè)窗口內(nèi)容被呈現(xiàn)為一個(gè)無(wú)障礙節(jié)點(diǎn)信息樹,該樹可能與視圖層次一一映射,也可能不與視圖層次一一映射。換句話說(shuō),一個(gè)自定義視圖可靈活地將自己報(bào)告為一個(gè)無(wú)障礙節(jié)點(diǎn)信息樹。一旦無(wú)障礙節(jié)點(diǎn)信息被發(fā)送給無(wú)障礙服務(wù),該信息將會(huì)是不可改變的,且調(diào)用狀態(tài)改變方法將會(huì)產(chǎn)生錯(cuò)誤。AccessibilityNodeInfo文檔 Zh 嵌套類: AccessibilityNodeInfo.AccessibilityAction API 21+ 定義了一個(gè)可以在 AccessibilityNodeInfo 上執(zhí)行的操作的類。 AccessibilityNodeInfo.CollectionInfo 具有一個(gè)節(jié)點(diǎn)是否是個(gè)集合的信息的類。 AccessibilityNodeInfo.CollectionItemInfo 具有一個(gè)節(jié)點(diǎn)是否是個(gè)集合項(xiàng)目的信息的類。 AccessibilityNodeInfo.RangeInfo 具有一個(gè)節(jié)點(diǎn)是否是個(gè)范圍的信息的類。 常量: 使用nodeInfo.performAction(Int Action)、performAction(Int Action, Bundle bundle)方法 Action 釋義 ACTION_ACCESSIBILITY_FOCUS 給節(jié)點(diǎn)添加無(wú)障礙焦點(diǎn)的操作。 ACTION_ARGUMENT_COLUMN_INT 讓指定集合列在屏幕上可見的參數(shù)。 ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN 當(dāng)以一定粒度移動(dòng)時(shí),是否擴(kuò)大選擇范圍或反之移除的參數(shù)。 ACTION_ARGUMENT_HTML_ELEMENT_STRING 要移動(dòng)到的下一個(gè)/上一個(gè) HTML 元素的參數(shù)。 ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT 當(dāng)遍歷節(jié)點(diǎn)文本的時(shí),使用哪種移動(dòng)粒度的參數(shù)。。 ACTION_ARGUMENT_PROGRESS_VALUE 指定要設(shè)置的進(jìn)度值的參數(shù)。 ACTION_ARGUMENT_ROW_INT 讓指定集合行在屏幕上可見的參數(shù)。 ACTION_ARGUMENT_SELECTION_END_INT 指定選擇結(jié)束的參數(shù)。 ACTION_ARGUMENT_SELECTION_START_INT 指定選擇起始的參數(shù)。 ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE 指定要設(shè)置的文本內(nèi)容的參數(shù)。 ACTION_CLEAR_ACCESSIBILITY_FOCUS 清除節(jié)點(diǎn)無(wú)障礙焦點(diǎn)的操作。 ACTION_CLEAR_FOCUS 清除節(jié)點(diǎn)輸入焦點(diǎn)的操作。 ACTION_CLEAR_SELECTION 取消選擇節(jié)點(diǎn)的操作。 ACTION_NEXT_AT_MOVEMENT_GRANULARITY 以給定移動(dòng)粒度,請(qǐng)求去到該節(jié)點(diǎn)文本的下一個(gè)文本實(shí)體的操作。 ACTION_CLICK 在節(jié)點(diǎn)信息上點(diǎn)擊的操作. ACTION_COLLAPSE 折疊一個(gè)可展開節(jié)點(diǎn)的操作。 ACTION_COPY 將當(dāng)前選擇拷貝到剪貼板的操作。 ACTION_CUT 剪貼當(dāng)前選項(xiàng)并放置到剪貼板的操作。 ACTION_DISMISS 關(guān)閉一個(gè)可關(guān)閉節(jié)點(diǎn)的操作。 ACTION_EXPAND 展開一個(gè)可展開節(jié)點(diǎn)的操作。 ACTION_FOCUS 給節(jié)點(diǎn)添加輸入焦點(diǎn)的操作。 ACTION_LONG_CLICK 在節(jié)點(diǎn)上點(diǎn)擊長(zhǎng)按的操作。 ACTION_NEXT_HTML_ELEMENT 移動(dòng)到給定類型的下一個(gè) HTML 元素的操作。例如,移動(dòng)到 BUTTON、INPUT、TABLE 等。 ACTION_PASTE 粘貼當(dāng)前剪貼板內(nèi)容的操作。 ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY 以給定移動(dòng)粒度,請(qǐng)求去到該節(jié)點(diǎn)文本的上一個(gè)文本實(shí)體的操作。例如,移動(dòng)到下一個(gè)字、詞等。 ACTION_PREVIOUS_HTML_ELEMENT 移動(dòng)到給定類型的上一個(gè) HTML 元素的操作。例如,移動(dòng)到BUTTON、INPUT、TABLE 等。 ACTION_SCROLL_BACKWARD 向后滾動(dòng)節(jié)點(diǎn)內(nèi)容的操作。 ACTION_SCROLL_FORWARD 向前滾動(dòng)節(jié)點(diǎn)內(nèi)容的操作 ACTION_SELECT 選擇節(jié)點(diǎn)的操作。 ACTION_SET_SELECTION 設(shè)置選擇項(xiàng)的操作。執(zhí)行該操作,并且無(wú)參數(shù)清除選項(xiàng) ACTION_SET_TEXT 設(shè)置節(jié)點(diǎn)文本的操作。在沒有參數(shù)的情況下執(zhí)行該操作,使用 null 或者空CharSequence 將會(huì)清除文本。該操作也將會(huì)把光標(biāo)放置到文本末尾 FOCUS_ACCESSIBILITY 無(wú)障礙焦點(diǎn)。 FOCUS_INPUT 輸入焦點(diǎn)。 MOVEMENT_GRANULARITY_CHARACTER 以字符為移動(dòng)粒度位,遍歷節(jié)點(diǎn)文本 MOVEMENT_GRANULARITY_LINE 以行為移動(dòng)粒度位,遍歷節(jié)點(diǎn)文本。 MOVEMENT_GRANULARITY_PAGE 以頁(yè)為移動(dòng)粒度位,遍歷節(jié)點(diǎn)文本。 MOVEMENT_GRANULARITY_PARAGRAPH 以段為移動(dòng)粒度位,遍歷節(jié)點(diǎn)文本。 MOVEMENT_GRANULARITY_WORD 以字詞為移動(dòng)粒度位,遍歷節(jié)點(diǎn)文本。 方法: Public Method 釋義 addAction(int action) 為一個(gè)nodeInfo添加一個(gè)操作,在API 21時(shí)被棄用 addAction(AccessibilityNodeInfo.AccessibilityAction action) 為一個(gè)nodeInfo添加一個(gè)操作,API 21 addChild(View root, int virtualDescendantId) 添加一個(gè)虛擬子元素,作為給定根節(jié)點(diǎn)的子view addChild(View child) 添加一個(gè)子view節(jié)點(diǎn)。 canOpenPopup() 獲取該節(jié)點(diǎn)是否可以打開一個(gè)彈窗或?qū)υ捒颉?/div> describeContents() 描述被包含在可打包實(shí)例的封裝代表中的特殊對(duì)象的種類。 equals(Object object) 標(biāo)識(shí)是否有某些其他對(duì)象“等同于”該對(duì)象。 findAccessibilityNodeInfosByText(String text) 使用文本找到 AccessibilityNodeInfo。 findAccessibilityNodeInfosByViewId(String viewId) 使用完全合格視圖id的源名稱找到AccessibilityNodeInfo,完全合格 id 的樣式 如下“package:id/id_resource_name”。 findFocus(int focus) 找到具有指定焦點(diǎn)類型的視圖。 focusSearch(int direction) 在指定方向搜索具有輸入焦點(diǎn)的最近的視圖。 getActionList() 獲取可以在該節(jié)點(diǎn)上執(zhí)行的操作。 getActions() 該方法在 API 級(jí)別 21 被棄用。使用getActionList()代替。 getBoundsInParent(Rect outBounds) 獲取父級(jí)坐標(biāo)中的節(jié)點(diǎn)邊界。 getBoundsInScreen(Rect outBounds) 獲取屏幕坐標(biāo)中的節(jié)點(diǎn)邊界。 getChild(int index) 獲取給定索引下的子元素。 getChildCount() 獲取子元素的數(shù)目。 getClassName() 獲取該節(jié)點(diǎn)來(lái)自的類。 getCollectionInfo() 如果節(jié)點(diǎn)是個(gè)集合,獲取集合信息。一個(gè)集合子集總是一個(gè)集合項(xiàng)目。 getCollectionItemInfo() 如果節(jié)點(diǎn)是個(gè)集合項(xiàng)目,獲取集合項(xiàng)目信息。一個(gè)集合項(xiàng)目總是一個(gè)集合的子集。 getContentDescription() 獲取該節(jié)點(diǎn)的內(nèi)容描述。 getExtras() 獲取具有附加數(shù)據(jù)的可選 bundle。該包是閑時(shí)創(chuàng)建的且永不為 null。注意:為了避免沖突,推薦使用應(yīng)用的包名作為關(guān)鍵字字首,如果從不同應(yīng)用發(fā)出的相同關(guān)鍵詞有不同的含義,可能會(huì)導(dǎo)致無(wú)障礙服務(wù)困擾。 getInputType() 獲取定義為 InputType 的源中的輸入類型。 getLabelFor() 為無(wú)障礙目的,獲取作為標(biāo)簽代表該視圖的節(jié)點(diǎn)信息。 返回AccessibilityNodeInfo getLabeledBy() 為無(wú)障礙目的,獲取作為標(biāo)簽代表該視圖的節(jié)點(diǎn)信息。返回AccessibilityNodeInfo getLiveRegion() 獲取該節(jié)點(diǎn)的實(shí)時(shí)區(qū)域模式。一個(gè)實(shí)時(shí)區(qū)域是一個(gè)包含對(duì)用戶來(lái)說(shuō)重要信息的節(jié)點(diǎn),且當(dāng)其改變時(shí)應(yīng)該告知用戶。例如,在一個(gè)登錄界面,有一個(gè)呈現(xiàn)“密碼錯(cuò)誤”通知的 TextView,該視圖應(yīng)該使用ACCESSIBILITY_LIVE_REGION_POLITE模式被標(biāo)記為一個(gè)實(shí)時(shí)區(qū)域。這是無(wú)障礙服務(wù)的責(zé)任,控制TYPE_WINDOW_CONTENT_CHANGED 事件標(biāo)識(shí)實(shí)時(shí)區(qū)域節(jié)點(diǎn)和其子元素的變化。實(shí)時(shí)區(qū)域模式,或如果視圖不是個(gè)實(shí)時(shí)區(qū)域,返回ACCESSIBILITY_LIVE_REGION_NONE。 getMaxTextLength() 返回該節(jié)點(diǎn)的最大文本長(zhǎng)度。 getMovementGranularities() 獲取遍歷該節(jié)點(diǎn)文本的移動(dòng)粒度。 getPackageName() 獲取該節(jié)點(diǎn)來(lái)自的包名。 getParent() 獲取父級(jí)NodeInfo。 getRangeInfo() 如果節(jié)點(diǎn)是個(gè)范圍,獲取范圍信息AccessibilityNodeInfo.RangeInfo getText() 獲取該節(jié)點(diǎn)的文本。 getTextSelectionEnd() 選擇文本的末尾,如果沒有選擇文本,返回光標(biāo)位置,或如果不存在選擇文本和光標(biāo),返回-1。 getTextSelectionStart() 選擇文本的起始,如果沒有選擇文本,返回光標(biāo)位置,或如果不存在選擇文本和光標(biāo),返回-1。 getViewIdResourceName() 獲取源視圖 id 的完全合格源名稱。 getWindowId() 獲取該信息來(lái)自的窗口的id。 hashCode() 返回該對(duì)象的哈希編碼值。多用于判斷node是否相同 isAccessibilityFocused() 獲取該節(jié)點(diǎn)是否可被無(wú)障礙聚焦。 isCheckable() 獲取該節(jié)點(diǎn)是否可選中。 isChecked() 獲取該節(jié)點(diǎn)是否已選中。 isClickable() 獲取該節(jié)點(diǎn)是否可點(diǎn)擊。 isContentInvalid() 獲取該節(jié)點(diǎn)的內(nèi)容是否已失效。例如,一個(gè)日期數(shù)據(jù)格式不正確。 isDismissable() 獲取該節(jié)點(diǎn)是否可被關(guān)閉。 isEditable() 獲取該節(jié)點(diǎn)是否可編輯。 isEnabled() 獲取該節(jié)點(diǎn)是否可用。 isFocusable() 獲取該節(jié)點(diǎn)是否可獲取焦點(diǎn)。 isFocused() 獲取該節(jié)點(diǎn)是否已被聚焦。 isLongClickable() 獲取該節(jié)點(diǎn)是否可長(zhǎng)按點(diǎn)擊。 isMultiLine() 獲取該節(jié)點(diǎn)是否是個(gè)多行可編輯文本。 isPassword() 獲取該節(jié)點(diǎn)是否是個(gè)密碼。 isScrollable() 獲取該節(jié)點(diǎn)是否可滾動(dòng)。 isSelected() 獲取該節(jié)點(diǎn)是否已被選擇。 isVisibleToUser() 該節(jié)點(diǎn)是否對(duì)用戶可見。 obtain(View root, int virtualDescendantId) 如果可獲得,返回一個(gè)緩存實(shí)例,否則創(chuàng)建一個(gè)新的并設(shè)置源。 View:虛擬子樹的根。 int:虛擬后代的id。返回一個(gè)實(shí)例化的AccessibilityNodeInfo obtain(AccessibilityNodeInfo info) 如果可獲得,返回一個(gè)緩存實(shí)例,或創(chuàng)建一個(gè)新的。返回的實(shí)例初始化自一個(gè)給定 root。 obtain() 如果可獲得,返回一個(gè)緩存實(shí)例,否則,返回一個(gè)新的。 obtain(View source) 如果可獲得,返回一個(gè)緩存實(shí)例,否則,返回一個(gè)新的并設(shè)置源。View:源視圖。 performAction(int action, Bundle arguments) 在該節(jié)點(diǎn)上執(zhí)行一個(gè)操作。int: 要執(zhí)行的操作。Bundle:具有額外參數(shù)的包。返回一個(gè)布爾值,表示是否成功執(zhí)行操作。 performAction(int action) 在該節(jié)點(diǎn)上執(zhí)行一個(gè)操作。 recycle() 返回一個(gè)實(shí)例重復(fù)使用,回收掉當(dāng)前的實(shí)例。 refresh() 刷新視圖呈現(xiàn)的最新狀態(tài)信息。返回一個(gè)布爾值,表示是否刷新成功。 removeAction(int action) 該方法在 API 級(jí)別 21 被棄用。 setAccessibilityFocused(boolean focused) 設(shè)置該節(jié)點(diǎn)可無(wú)障礙聚焦。 setBoundsInParent(Rect bounds) 在父級(jí)坐標(biāo)中設(shè)置節(jié)點(diǎn)邊界。 setBoundsInScreen(Rect bounds) 在屏幕坐標(biāo)中設(shè)置節(jié)點(diǎn)邊界。 setCanOpenPopup(boolean opensPopup) 設(shè)置該節(jié)點(diǎn)可打開一個(gè)彈窗或?qū)υ捒颉?/div> setCheckable(boolean checkable) 設(shè)置該節(jié)點(diǎn)可選中。 setChecked(boolean checked) 設(shè)置該節(jié)點(diǎn)已選中。 setClassName(CharSequence className) 設(shè)置該節(jié)點(diǎn)來(lái)自的類。 setClickable(boolean clickable) 設(shè)置該節(jié)點(diǎn)可點(diǎn)擊。 setCollectionInfo(AccessibilityNodeInfo.CollectionInfo collectionInfo) 如果該節(jié)點(diǎn)是個(gè)集合,設(shè)置集合信息。一個(gè)集合子集通常也是個(gè)集合項(xiàng)目。 setContentDescription(CharSequence contentDescription) 設(shè)置該節(jié)點(diǎn)的內(nèi)容描述。 setContentInvalid(boolean contentInvalid) 設(shè)置節(jié)點(diǎn)內(nèi)容無(wú)效。例如,一個(gè)日期數(shù)據(jù)格式不正確。 setContextClickable(boolean contextClickable) 設(shè)置該節(jié)點(diǎn)文本可點(diǎn)擊。 setDismissable(boolean dismissable) 設(shè)置該節(jié)點(diǎn)可以被關(guān)閉。 setEditable(boolean editable) 設(shè)置該節(jié)點(diǎn)可編輯。 setEnabled(boolean enabled) 設(shè)置該節(jié)點(diǎn)可用。 setFocusable(boolean focusable) 設(shè)置該節(jié)點(diǎn)可聚焦。 setFocused(boolean focused) 設(shè)置該節(jié)點(diǎn)已聚焦。 setInputType(int inputType) 設(shè)置源中的輸入類型為inputType setLabelFor(View root, int virtualDescendantId) 為無(wú)障礙目的,設(shè)置可作為標(biāo)簽代表視圖的信息。如果 virtualDescendantId 為NO_ID,根被設(shè)置為標(biāo)簽。一個(gè)虛擬后代是一個(gè)虛構(gòu)視圖,為無(wú)障礙目的,將自己報(bào)告為視圖層次的一部分。該操作可以使繪制復(fù)雜內(nèi)容的自定義視圖,將自己報(bào)告為虛擬視圖樹,然后傳遞其邏輯結(jié)構(gòu)。 setLabelFor(View labeled) 為無(wú)障礙目的,設(shè)置可作為標(biāo)簽代表視圖的信息。 setLabeledBy(View label) 為無(wú)障礙目的,設(shè)置可作為標(biāo)簽代表視圖的信息。 setLabeledBy(View root, int virtualDescendantId) 為無(wú)障礙目的,設(shè)置可作為標(biāo)簽代表視圖的信息。如果 virtualDescendantId 為NO_ID,根被設(shè)置為標(biāo)簽。一個(gè)虛擬后代是一個(gè)虛構(gòu)視圖,為無(wú)障礙目的,將自己報(bào)告為視圖層次的一部分。該操作可以使繪制復(fù)雜內(nèi)容的自定義視圖,將自己報(bào)告為虛擬視圖樹,然后傳遞其邏輯結(jié)構(gòu)。 setLiveRegion(int mode) 設(shè)置該節(jié)點(diǎn)的實(shí)時(shí)區(qū)域模式。int:實(shí)時(shí)區(qū)域模式,或如果視圖不是個(gè)實(shí)時(shí)區(qū)域時(shí),為ACCESSIBILITY_LIVE_REGION_NONE。 setLongClickable(boolean longClickable) 設(shè)置該節(jié)點(diǎn)可長(zhǎng)按點(diǎn)擊。 setMaxTextLength(int max) 設(shè)置最大文本長(zhǎng)度,或無(wú)限制時(shí)為-1。一般情況下,用來(lái)標(biāo)識(shí)一個(gè)可編輯文本框有輸入字符數(shù)目限制。 getMovementGranularities() 設(shè)置遍歷節(jié)點(diǎn)文本的移動(dòng)粒度。 setMultiLine(boolean multiLine) 設(shè)置該節(jié)點(diǎn)為一個(gè)多行可編輯文本。 setPackageName(CharSequence packageName) 設(shè)置該節(jié)點(diǎn)來(lái)自的包。 setParent(View root, int virtualDescendantId) 設(shè)置給定 root 虛擬后代的父元素。如果 virtualDescendantId 等于 NO_ID,該root 被設(shè)置為父級(jí)。一個(gè)虛擬后代是一個(gè)虛構(gòu)視圖,為無(wú)障礙目的,將自己報(bào)告為視圖層次的一部分。該操作可以使繪制復(fù)雜內(nèi)容的自定義視圖,將自己報(bào)告為虛擬視圖樹,然后傳遞其邏輯結(jié)構(gòu)。 setParent(View parent) 設(shè)置父元素。 setPassword(boolean password) 設(shè)置該節(jié)點(diǎn)為密碼。 setRangeInfo(AccessibilityNodeInfo.RangeInfo rangeInfo) 如果該節(jié)點(diǎn)是個(gè)范圍,設(shè)置范圍信息。 setScrollable(boolean scrollable) 設(shè)置該節(jié)點(diǎn)可滾動(dòng)。 setSelected(boolean selected) 設(shè)置該節(jié)點(diǎn)是否已選擇。 setSource(View source) 設(shè)置信息源。 setSource(View root, int virtualDescendantId) 為給定 root 虛擬后代設(shè)置源。如果 virtualDescendantId 等于 NO_ID,該 root被設(shè)置為源。一個(gè)虛擬后代是一個(gè)虛構(gòu)視圖,為無(wú)障礙目的,將自己報(bào)告為視圖層次的一部分。該操作可以使繪制復(fù)雜內(nèi)容的自定義視圖,將自己報(bào)告為虛擬視圖樹,然后傳遞其邏輯結(jié)構(gòu)。 setText(CharSequence text) 設(shè)置該節(jié)點(diǎn)的文本。 setTextSelection(int start, int end) 設(shè)置文本選擇的起始和結(jié)尾。 setViewIdResourceName(String viewIdResName) 設(shè)置源視圖id的資源名稱 setVisibleToUser(boolean visibleToUser) 設(shè)置該節(jié)點(diǎn)對(duì)用戶可見。 toString() 返回一個(gè)代表對(duì)象的字符串。 getClass().getName() + '@' + Integer.toHexString(hashCode()) writeToParcel(Parcel parcel, int flags) 封裝該對(duì)象到一個(gè)包中。 API 21 ADD getError() API Level 21 獲取該節(jié)點(diǎn)的錯(cuò)誤文本。 setError(CharSequence error) API Level 21 設(shè)置該節(jié)點(diǎn)的錯(cuò)誤文本。 getWindow() API Level 21 獲取該節(jié)點(diǎn)所屬的窗口。AccessibilityWindowInfo removeAction(AccessibilityNodeInfo.AccessibilityAction action) API Level 21 移除一個(gè)可以在該節(jié)點(diǎn)上執(zhí)行的操作。如果該操作未被添加到該節(jié)點(diǎn),調(diào)用該方法沒有任何效果。返回一個(gè)布爾值表示是否成功移除操作。 removeChild(View root, int virtualDescendantId) API Level 21 移除給定根節(jié)點(diǎn)的一個(gè)虛擬子元素。如果子元素不是之前被添加到該節(jié)點(diǎn)的,調(diào)用該方法無(wú)效果。 返回一個(gè)布爾值表示是否存在子元素。 removeChild(View child) API Level 21 移除一個(gè)子元素。如果子元素先前未被添加到該節(jié)點(diǎn),調(diào)用該方法無(wú)效果。 API 22 ADD getTraversalAfter() API Level 22 當(dāng)前節(jié)點(diǎn)被訪問(wèn)后,獲取無(wú)障礙遍歷中的下一個(gè)節(jié)點(diǎn)。一個(gè)屏幕閱讀器必須在訪問(wèn)該節(jié)點(diǎn)內(nèi)容之前,訪問(wèn)其他節(jié)點(diǎn)的內(nèi)容。如果存在,返回后續(xù)節(jié)點(diǎn),否則,返回 null。 getTraversalBefore() API Level 22 當(dāng)前節(jié)點(diǎn)被訪問(wèn)后,獲取無(wú)障礙遍歷中的上一個(gè)節(jié)點(diǎn)。屏幕閱讀器必須訪問(wèn)該節(jié)點(diǎn)的信息,在訪問(wèn)先前節(jié)點(diǎn)內(nèi)容之前。 setTraversalAfter(View view) API Level 22 設(shè)置無(wú)障礙遍歷中下一個(gè)被訪問(wèn)的視圖。一個(gè)屏幕閱讀器在訪問(wèn)該節(jié)點(diǎn)內(nèi)容之前,必須訪問(wèn)另一個(gè)節(jié)點(diǎn)的內(nèi)容。 setTraversalAfter(View root, int virtualDescendantId) API Level 22設(shè)置無(wú)障礙遍歷中下一個(gè)被訪問(wèn)的視圖。一個(gè)屏幕閱讀器在訪問(wèn)該節(jié)點(diǎn)內(nèi)容之前,必須訪問(wèn)另一個(gè)節(jié)點(diǎn)的內(nèi)容。如果 virtualDescendantId 等于 NO_ID,root被設(shè)置為前任。一個(gè)虛擬后代是一個(gè)虛構(gòu)視圖,為無(wú)障礙目的,將自己報(bào)告為視圖層次的一部分。該操作可以使繪制復(fù)雜內(nèi)容的自定義視圖,將自己報(bào)告為虛擬視圖樹,然后傳遞其邏輯結(jié)構(gòu)。 setTraversalBefore(View view) API Level 22 設(shè)置無(wú)障礙遍歷中當(dāng)前訪問(wèn)節(jié)點(diǎn)的上一個(gè)視圖。一個(gè)屏幕閱讀器在訪問(wèn)上一個(gè)節(jié)點(diǎn)之前,必須訪問(wèn)該節(jié)點(diǎn)的內(nèi)容。 setTraversalBefore(View root, int virtualDescendantId) API Level 22 設(shè)置無(wú)障礙遍歷中當(dāng)前訪問(wèn)節(jié)點(diǎn)的上一個(gè)視圖。一個(gè)屏幕閱讀器在訪問(wèn)上一個(gè)節(jié)點(diǎn)之前,必須訪問(wèn)該節(jié)點(diǎn)的內(nèi)容。如果virtualDescendantId 等于 NO_ID,root被設(shè)置為后任。一個(gè)虛擬后代是一個(gè)虛構(gòu)視圖,為無(wú)障礙目的,將自己報(bào)告為視圖層次的一部分。該操作可以使繪制復(fù)雜內(nèi)容的自定義視圖,將自己報(bào)告為虛擬視圖樹,然后傳遞其邏輯結(jié)構(gòu)。 API 23 ADD isContextClickable() API Level 23 獲取該節(jié)點(diǎn)是否上下文可點(diǎn)擊。 API 24 ADD setImportantForAccessibility(boolean important) API Level 24 設(shè)置該節(jié)點(diǎn)對(duì)無(wú)障礙很重要。 setDrawingOrder(int drawingOrderInParent) API Level 24 設(shè)置該節(jié)點(diǎn)相關(guān)視圖的繪制順序。 getDrawingOrder() API Level 24。獲取該節(jié)點(diǎn)中視圖的相對(duì)繪制順序。繪制順序只決定于節(jié)點(diǎn)的父級(jí),所以該索引只與其兄弟姐妹相關(guān)。在一些情景下,繪制順序是基本同步的,所以兩個(gè)兄弟姐妹的返回值相同是可能的。返回值會(huì)被跳過(guò)也是可能的。 isImportantForAccessibility() API Level 24 返回該節(jié)點(diǎn)是否來(lái)源于一個(gè)對(duì)無(wú)障礙相當(dāng)重要的視圖。 performGlobalAction Action 釋義 GLOBAL_ACTION_BACK 相當(dāng)于點(diǎn)擊物理按鍵返回 GLOBAL_ACTION_HOME 相當(dāng)于點(diǎn)擊物理按鍵Home鍵 GLOBAL_ACTION_NOTIFICATIONS 相當(dāng)于下滑打開通知 GLOBAL_ACTION_RECENTS 相當(dāng)于點(diǎn)擊物理按鍵最近任務(wù)鍵 GLOBAL_ACTION_QUICK_SETTINGS 打開快速設(shè)置 GLOBAL_ACTION_POWER_DIALOG 打開長(zhǎng)按電源鍵的彈框 2.1.5 自定義AccessibilityService類的常規(guī)使用 public class MyAccessibilityService extends AccessibilityService { @Override protected void onServiceConnected() { super.onServiceConnected(); } @Override public void onAccessibilityEvent(AccessibilityEvent event) { // 1.AccessibilityEvent中一些常用的使用方法 // 這里我們獲取到該輔助功能的事件類型 // 事件類型請(qǐng)參照 2.1.3中AccessibilityEventTypes表 int eventType = event.getEventType(); // 輸出事件的字符串type String typeStr = event.eventTypeToString(eventType); // 根據(jù)事件類型來(lái)分發(fā)我們的需要的操作,這里以窗口變化為例 if(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED == eventType){ // 判斷我們的輔助功能是否在約定好的應(yīng)用界面執(zhí)行,以設(shè)置界面為例 if("com.android.settings".equals(event.getPackageName()){ // doSomeThing } } else if(AccessibilityEvent.TYPE_GESTURE_DETECTION_START == eventType) { // 在監(jiān)測(cè)到手勢(shì)的時(shí)候 } else { // 在完成操作時(shí),可以關(guān)閉自己的服務(wù),下次使用再次開啟。 // API > = 24 disableSelf(); } // 2.通過(guò)event來(lái)遍歷我們的nodeInfo if (VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) // 這里使用getResource()方法其實(shí)是從AccessibilityEvent繼承的 // AccessibilityRecord中抽取AccessibilityNodeInfo // 實(shí)際調(diào)用的是AccessibilityRecord中的方法,返回的是AccessibilityNodeInfo mSourceNode AccessibilityNodeInfo info = event.getSource(); else info = getRootInActiveWindow(); // 3.遍歷info中的子節(jié)點(diǎn) if (info.getChildCount() != 0){ // 通過(guò)一個(gè)循環(huán)將info的子節(jié)點(diǎn)遍歷 for (int i = 0; i < info.getChildCount(); i++) { // 獲取子節(jié)點(diǎn)中某個(gè)特定的node,這里通過(guò)以下方法通過(guò)ID查找 List<AccessibilityNodeInfo> list = info.findAccessibilityNodeInfosByViewId("com.android" +".settings:id/xxxx"); // 通過(guò)text查找 List<AccessibilityNodeInfo> list = info.findAccessibilityNodeInfosByText("xxxx"); // 打印nodeinfo的信息 Log.e("InfoType: " + info.getClassName()); Log.e("InfoText: " + info.getText()); Log.e("InfoPkgName: " + info.getPackageName()); Log.e("InfoViewId: " + info.getViewIdResourceName()); } } // 4.為節(jié)點(diǎn)添加操作 // 1) 首先獲取到我們的節(jié)點(diǎn) AccessibilityNodeInfo info = event.getSource(); // 2) 通過(guò)查找指定的ID、text來(lái)查找一個(gè)系列的節(jié)點(diǎn),返回一個(gè)list,需要判斷l(xiāng)ist.size()是否為空 List<AccessibilityNodeInfo> list = info.findAccessibilityNodeInfosByViewId("pkgName." + "id"); AccessibilityNodeInfo info = list.get(0); // 3) 為節(jié)點(diǎn)添加操作,點(diǎn)擊事件(事件可參照AccessibilityNodeInfo表) info.performAction(AccessibilityNodeInfo.ACTION_CLICK); // 4) 添加node可用的action,給node添加一個(gè)可清除焦點(diǎn)的操作 // 通過(guò)addAction(AccessibilityNodeInfo.AccessibilityAction action) info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_CLEAR_FOCUS); // 獲取該node上可用的action屬性list,可以用來(lái)查看該node的屬性 List<AccessibilityNodeInfo.AccessibilityAction> listAction = info.getActionList(); // 5.獲取該節(jié)點(diǎn)上子節(jié)點(diǎn)個(gè)數(shù) int childCount = info.getChildCount(); // 6.操作完成后,回收實(shí)例,返回一個(gè)下次可用的實(shí)例 info.recycle(); // 需要注意的是,在node.performAction之后,調(diào)用本地廣播的話,之后的globeAction不會(huì)起作用,例: sureStopNode.performAction(AccessibilityNodeInfo.ACTION_CLICK); sureStopNode.recycle(); SystemMessage.getInstance().send(SystemMessage.ACTION_POWER_BOOSTER_NEXT); performGlobalAction();// 這句話是不起作用的 // 7.輔助功能的一些適用場(chǎng)景: // 1)部分應(yīng)用中獲取短信驗(yàn)證碼(通過(guò)開啟輔助功能的方式獲取) // - 監(jiān)聽通知欄的消息(typeNotificationStateChanged) // - 彈出通知欄的時(shí)候獲取該通知的節(jié)點(diǎn)信息(event.getSource()) // - 遍歷root節(jié)點(diǎn),取得顯示信息的文本Node(info.findAccessibilityNodeInfosByViewId("pkgName." + "id")) // - 通過(guò)NodeInfo.getText()方法獲取到相應(yīng)的文本信息,并取出驗(yàn)證碼 // - 取消掉通知欄彈出框 // - 獲取到要輸入的EditText獲取直接在本應(yīng)用給需要填寫驗(yàn)證碼的區(qū)域設(shè)置文本。 // 2)部分應(yīng)用中恢復(fù)APP的初始設(shè)置(清除APP的數(shù)據(jù)) // - 跳轉(zhuǎn)到應(yīng)用詳情,通過(guò)findAccessibilityNodeInfosByViewId查找節(jié)點(diǎn) // - 通過(guò)節(jié)點(diǎn)info.performAction(AccessibilityNodeInfo.ACTION_CLICK)點(diǎn)擊清除 // - 彈出確定對(duì)話框,同上方式找到確定節(jié)點(diǎn),點(diǎn)擊后返回 // 3)監(jiān)測(cè)應(yīng)用是否在前臺(tái),APP的啟動(dòng)(通過(guò)windowstatechange事件獲取到當(dāng)前的event的pkgName) // - 通過(guò)接收typeWindowStateChanged事件,獲取event的pkgName確定哪個(gè)應(yīng)用啟動(dòng)或者在最上層顯示(懸浮窗不適用) // 4)自動(dòng)安裝與卸載軟件 // - 同3,尋找相應(yīng)的節(jié)點(diǎn),點(diǎn)擊事件 // 5)自動(dòng)化UI測(cè)試 // 6)最常見的搶紅包 // 7)通過(guò)輔助功能開啟一些權(quán)限(不需要用戶手動(dòng)點(diǎn)擊開啟了) // - 在用戶確定需要開啟權(quán)限時(shí),自動(dòng)跳轉(zhuǎn),尋找相應(yīng)的開關(guān)按鈕 // - 需要注意的是,部分開關(guān)(switch button, checkbox)可能沒有ID,需要通過(guò)info.getClassName()來(lái)判斷,屬于那種類型的view。 } @Override public void onInterrupt() { } } 需要重寫的一些方法: onServiceConnected() 該方法在初始化輔助功能服務(wù)時(shí)調(diào)用,可以在這時(shí)做相應(yīng)的初始化工作。 onAccessibilityEvent() 在獲取到指定的監(jiān)聽事件時(shí),通過(guò)回調(diào)這個(gè)方法來(lái)進(jìn)行對(duì)應(yīng)的操作 onInterrupt() 系統(tǒng)想要中斷輔助功能時(shí)會(huì)調(diào)用該方法 當(dāng)然service中的onUnbind()方法也同樣適用,在onUnbind()中釋放一些資源也是可以的。 Note: 這里需要了解的是輔助功能最重要的就是手機(jī)機(jī)型的適配。由于各個(gè)廠商的系統(tǒng)不一樣,導(dǎo)致了我們?cè)讷@取一些節(jié)點(diǎn)時(shí),需要的節(jié)點(diǎn)ID不同(通過(guò)ID獲取節(jié)點(diǎn)時(shí)一種比較高效的方式)。而我們一般通過(guò)Device Monitor中的Hierarchy View獲取節(jié)點(diǎn)信息。同時(shí)在此方式下,很多手機(jī)沒法獲取到節(jié)點(diǎn)信息,我們就需要使用添加flagReportViewIds進(jìn)行手動(dòng)遍歷界面節(jié)點(diǎn)的方式獲取nodeInfo。 以上是輔助功能常規(guī)使用以及使用場(chǎng)景的介紹。下面為輔助功能的注冊(cè)。 <service android:name=".我們自己繼承自AccessibilityService的類" android:label="@string/app_name" android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"> <intent-filter> <action android:name="android.accessibilityservice.AccessibilityService"/> </intent-filter> <meta-data android:name="android.accessibilityservice" android:resource="@xml/第二個(gè)輔助功能配置方式的文件,存放在xml下"/> </service> 2.2 API > 20 新增方法,接口(預(yù)覽版)使用探究: 2.2.1 AccessibilityService新增方法一覽: API 21: Method 描述 getWindows() 返回窗口最上層的一個(gè)用戶可交互的窗口信息節(jié)點(diǎn) List<AccessibilityWindowInfo> 獲取屏幕上的窗口。 返回一個(gè)有目標(biāo)的用戶可以與之進(jìn)行交互的窗口,而不是所有的窗口。 為了訪問(wèn)Windows,服務(wù)必須通過(guò)在其元數(shù)據(jù)中設(shè)置AccessibilityService_canRetrieveWindowContent屬性來(lái)聲明檢索窗口內(nèi)容的功能。此外,服務(wù)必須選擇通過(guò)設(shè)置FLAG_RETRIEVE_INTERACTIVE_WINDOWS標(biāo)志來(lái)檢索交互式窗口。 使用此方法來(lái)獲取我們屏幕上最上層的一個(gè)窗口根節(jié)點(diǎn)。 API 24: Method 描述 getSoftKeyboardController() 返回軟鍵盤控制器,可用于查詢和修改軟鍵盤顯示模式。 返回AccessibilityService.SoftKeyboardController其中可以使用添加addOnShowModeChangedListener()的方式來(lái)進(jìn)行對(duì)鍵盤的顯示隱藏狀態(tài)監(jiān)聽,通過(guò)getShowMode()獲取到軟鍵盤的顯示隱藏狀態(tài),setShowMode(int showMode)設(shè)置軟鍵盤的顯示隱藏狀態(tài)。 Method 描述 disableSelf() 關(guān)閉自己service的方法,在設(shè)置界面可以看到輔助功能狀態(tài)被關(guān)閉 通過(guò)在服務(wù)中調(diào)用該方法可以將自己的服務(wù)停止,同時(shí)在輔助功能開啟界面上的開關(guān)也會(huì)隨之關(guān)閉。 Method 描述 dispatchGesture(GestureDescription gesture, AccessibilityService.GestureResultCallback callback, Handler handler) 將手勢(shì)發(fā)送到觸摸屏。 可以通過(guò)設(shè)定GestureDescription將手勢(shì)的軌跡顯示在觸摸屏上,同時(shí)可以通過(guò)GestureResultCallback回調(diào)獲得事件的完成情況。 Method 描述 findFocus(int focus) 找到具有指定焦點(diǎn)類型的視圖。 這里的焦點(diǎn)類型有FOCUS_INPUT和FOCUS_ACCESSIBILITY分別代表了輸入焦點(diǎn)和無(wú)障礙重點(diǎn)。 FOCUS_ACCESSIBILITY這個(gè)焦點(diǎn),是需要使用setAccessibilityFocused(boolean isFocus)方法進(jìn)行設(shè)置過(guò)得焦點(diǎn)。 需要注意的是:如果要使用該方法的話,需要先設(shè)置AccessibilityService_canRetrieveWindowContent同時(shí)添加一個(gè)flag:FLAG_RETRIEVE_INTERACTIVE_WINDOWS。 Method 描述 getMagnificationController() 返回放大控制器,可用于查詢和修改顯示放大的狀態(tài)。 返回:AccessibilityService.MagnificationController。為了控制放大倍數(shù),輔助功能服務(wù)必須通過(guò)在其元數(shù)據(jù)中設(shè)置AccessibilityService_canControlMagnification屬性來(lái)聲明該功能。 API 26: Method 描述 getAccessibilityButtonController() 系統(tǒng)導(dǎo)航區(qū)域內(nèi)的輔助功能按鈕控制器 返回:AccessibilityButtonController: 當(dāng)設(shè)置FLAG_REQUEST_ACCESSIBILITY_BUTTON時(shí),此類可用于查詢輔助功能按鈕的狀態(tài)并注冊(cè)回調(diào)以進(jìn)行交互,并對(duì)可訪問(wèn)性按鈕進(jìn)行狀態(tài)更改。 注意:此類和FLAG_REQUEST_ACCESSIBILITY_BUTTON不應(yīng)該被用作通過(guò)AccessibilityService為用戶提供功能的唯一手段。 一些設(shè)備實(shí)現(xiàn)可以選擇不提供軟件呈現(xiàn)的系統(tǒng)導(dǎo)航區(qū)域,使得該功能永久不可用。 注意:在支持輔助功能按鈕的設(shè)備實(shí)現(xiàn)中,它可能始終不可用,例如前臺(tái)應(yīng)用程序使用SYSTEM_UI_FLAG_HIDE_NAVIGATION時(shí)。 用戶還可以選擇將該按鈕分配給另一個(gè)可訪問(wèn)性服務(wù)或功能。 在每種情況下,將調(diào)用注冊(cè)的AccessibilityButtonController.AccessibilityButtonCallback的onAvailabilityChanged(AccessibilityButtonController,boolean)方法來(lái)提供對(duì)可訪問(wèn)性按鈕對(duì)注冊(cè)服務(wù)的可用性的更改的通知。 注意底部導(dǎo)航欄的小人: image 下面是一個(gè)簡(jiǎn)單的用例: public class MyAccessibilityService extends AccessibilityService { @Override protected void onServiceConnected() { super.onServiceConnected(); AccessibilityServiceInfo info = new AccessibilityServiceInfo(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { info.flags = AccessibilityServiceInfo.FLAG_REQUEST_ACCESSIBILITY_BUTTON; } else { info.flags = AccessibilityServiceInfo.FLAG_REPORT_VIEW_IDS; } info.eventTypes = AccessibilityEvent.TYPES_ALL_MASK; info.feedbackType = AccessibilityServiceInfo.FEEDBACK_GENERIC; info.notificationTimeout = 100; setServiceInfo(info); } @Override public void onAccessibilityEvent(AccessibilityEvent event) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { AccessibilityButtonController mAccessibilityButtonController = getAccessibilityButtonController(); mAccessibilityButtonController.registerAccessibilityButtonCallback(new AccessibilityButtonController.AccessibilityButtonCallback() { @Override public void onClicked(AccessibilityButtonController controller) { super.onClicked(controller); // 底部導(dǎo)航欄中輔助功能按鈕點(diǎn)擊事件回調(diào) Toast.makeText(MyAccessibilityService.this, "on Click", Toast.LENGTH_SHORT).show(); } @Override public void onAvailabilityChanged(AccessibilityButtonController controller, boolean available) { super.onAvailabilityChanged(controller, available); // 輔助功能可用性改變的回調(diào)。返回了輔助功能底部按鈕是否可用的布爾值,和按鈕控制器 // available = true 表示該按鈕對(duì)本服務(wù)可用 // available = false 是由于設(shè)備顯示了按鈕,或按鈕被分配到另一個(gè)服務(wù)或其他原因。 } }); } } @Override public void onInterrupt() { } } 在開啟輔助功能之后,如果是O系統(tǒng)的話,在底部導(dǎo)航欄會(huì)出現(xiàn)一個(gè)輔助功能的小人。同時(shí)這個(gè)小人可以接收到點(diǎn)擊事件,和輔助功能可用狀態(tài)變化。 Method 描述 getFingerprintGestureController() 返回指紋手勢(shì)控制器 指紋手勢(shì)控制器:FingerprintGestureController 只要設(shè)備具有能夠檢測(cè)手勢(shì)的傳感器,AccessibilityService可以捕獲在設(shè)備的指紋傳感器上執(zhí)行的手勢(shì)。 使用時(shí)需要聲明CAPABILITY_CAN_CAPTURE_FINGERPRINT_GESTURES同時(shí)需要權(quán)限USE_FINGERPRINT,由于沒有真機(jī)調(diào)試該方法,待Google發(fā)布正式版API后繼續(xù)研究 支持的四個(gè)事件: 常量 描述 FINGERPRINT_GESTURE_SWIPE_DOWN 指紋手勢(shì)下滑。 FINGERPRINT_GESTURE_SWIPE_LEFT 指紋手勢(shì)左滑。 FINGERPRINT_GESTURE_SWIPE_RIGHT 指紋手勢(shì)右滑。 FINGERPRINT_GESTURE_SWIPE_DOWN 指紋手勢(shì)上滑。 公有方法 方法 描述 isGestureDetectionAvailable() 判斷手勢(shì)監(jiān)測(cè)是否可用。 registerFingerprintGestureCallback(FingerprintGestureController.FingerprintGestureCallback callback, Handler handler) 通過(guò)該方法注冊(cè)一個(gè)指紋手勢(shì)的回調(diào)。 unregisterFingerprintGestureCallback(FingerprintGestureController.FingerprintGestureCallback callback) 取消注冊(cè)。 registerFingerprintGestureCallback(FingerprintGestureController.FingerprintGestureCallback, Handler) 取消注冊(cè)。 其中的FingerprintGestureController.FingerprintGestureCallback與之前的輔助功能按鈕回調(diào)基本相同,都只有兩個(gè)方法。 方法 描述 onGestureDetected(int gesture) 這里獲取到相應(yīng)的手勢(shì)。 onGestureDetectionAvailabilityChanged(boolean available) 這里返回了手勢(shì)監(jiān)測(cè)是否可用。 2.2.1 AccessibilityNodeInfo新增方法一覽: API 21 Method 描述 getError() 獲取該節(jié)點(diǎn)的錯(cuò)誤文本。 setError(CharSequence error) 設(shè)置該節(jié)點(diǎn)的錯(cuò)誤文本。 以上兩個(gè)方法需要搭配使用。 Method 描述 getWindow() 獲取該節(jié)點(diǎn)所屬的窗口(根節(jié)點(diǎn)) 通過(guò)該方法,我們可以使用一個(gè)子節(jié)點(diǎn)來(lái)重新獲取到我們的根節(jié)點(diǎn)。在需要多次操作界面元素的情況下(同時(shí)沒有產(chǎn)生windowstatechange事件),我們可以不通過(guò)監(jiān)聽事件來(lái)進(jìn)行下一個(gè)節(jié)點(diǎn)的操作。 Method 描述 addAction(AccessibilityNodeInfo.AccessibilityAction action) 為一個(gè)nodeInfo添加一個(gè)操作,API 21 removeAction(AccessibilityNodeInfo.AccessibilityAction action) 移除一個(gè)可以在該節(jié)點(diǎn)上執(zhí)行的操作。 removeChild(View root, int virtualDescendantId) 移除給定根節(jié)點(diǎn)的一個(gè)虛擬子元素。 removeChild(View child) 移除一個(gè)子元素。 第一個(gè)addAction(AccessibilityNodeInfo.AccessibilityAction action)方法是API 21時(shí)替代API 20中的addAction(int action)方法。 提供了一個(gè)在輔助功能外操作節(jié)點(diǎn)的方法,該方法不能在輔助功能服務(wù)中調(diào)用,不然會(huì)報(bào)錯(cuò)java.lang.IllegalStateException: Cannot perform this action on a sealed instance. 后三個(gè)方法使用的前提都是需要事先在節(jié)點(diǎn)中添加了操作,或者視圖,不然都不會(huì)起作用。要說(shuō)明的是removeAction方法也需要在服務(wù)外調(diào)用,不然也要報(bào)錯(cuò) API 22 Method 描述 getTraversalAfter() 當(dāng)前節(jié)點(diǎn)被訪問(wèn)后,獲取無(wú)障礙遍歷中的下一個(gè)節(jié)點(diǎn)。 getTraversalBefore() 當(dāng)前節(jié)點(diǎn)被訪問(wèn)后,獲取無(wú)障礙遍歷中的上一個(gè)節(jié)點(diǎn)。 setTraversalAfter(View view) 設(shè)置無(wú)障礙遍歷中下一個(gè)被訪問(wèn)的視圖。一個(gè)屏幕閱讀器在訪問(wèn)該節(jié)點(diǎn)內(nèi)容之前,必須訪問(wèn)另一個(gè)節(jié)點(diǎn)的內(nèi)容。如果 virtualDescendantId 等于 NO_ID,root被設(shè)置為前任。 setTraversalAfter(View root, int virtualDescendantId) 設(shè)置無(wú)障礙遍歷中下一個(gè)被訪問(wèn)的視圖。 setTraversalBefore(View view) 設(shè)置無(wú)障礙遍歷中當(dāng)前訪問(wèn)節(jié)點(diǎn)的上一個(gè)視圖。 通過(guò)在view的xml屬性中添加android:accessibilityTraversalAfter="+id"方式來(lái)進(jìn)行輔助功能遍歷時(shí)的順序后,通過(guò)本方法獲取下一個(gè)節(jié)點(diǎn)。 通過(guò)在view的xml屬性中添加android:accessibilityTraversalBefore="+id"方式來(lái)進(jìn)行輔助功能遍歷時(shí)的順序,同上。 通過(guò)View.setAccessibilityTraversalBefore(+id)方式設(shè)置順序。 API 23 Method 描述 isContextClickable() 獲取該節(jié)點(diǎn)是否上下文可點(diǎn)擊。 通過(guò)View的setContextClickable(Boolean isClickable)方法設(shè)置一個(gè)View是否可以點(diǎn)擊。然后通過(guò)該方法,我們可以獲取到節(jié)點(diǎn)上下文的可否點(diǎn)擊狀態(tài)。 API 24 Method 描述 setImportantForAccessibility(boolean important) 設(shè)置該節(jié)點(diǎn)對(duì)無(wú)障礙很重要。 isImportantForAccessibility() 返回該節(jié)點(diǎn)是否來(lái)源于一個(gè)對(duì)無(wú)障礙相當(dāng)重要的視圖。 通過(guò)View的XML屬性設(shè)置android:importantForAccessibility=""狀態(tài)后,我們可以通過(guò)本方法獲取到該狀態(tài)的boolean值。 Method 描述 setDrawingOrder(int drawingOrderInParent) 設(shè)置與此節(jié)點(diǎn)對(duì)應(yīng)的視圖的繪圖順序。 getDrawingOrder() 獲取該節(jié)點(diǎn)中視圖的相對(duì)繪制順序。 同樣的不能在輔助功能服務(wù)中調(diào)用該方法。 參考ViewGroup.setChildrenDrawingOrderEnabled()中children的繪制順序理解。 返回與該節(jié)點(diǎn)對(duì)應(yīng)的視圖相對(duì)于其兄弟姐妹的繪圖位置。 返回的數(shù)值從1開始,表示相對(duì)于父節(jié)點(diǎn)中,并列view的繪制順序。
|
|
來(lái)自: 思想戰(zhàn)神 > 《待分類》