原理
大致簡述一下术健,谷歌已經(jīng)在View之宿、ViewGroup、TextView等控件的文字改變苛坚、滑動比被、UI變化埋下了接口,當這些狀態(tài)變化時控件會回調(diào)系統(tǒng)API泼舱,API系統(tǒng)然后對這些對象的數(shù)據(jù)進行組裝等缀,為了數(shù)據(jù)的安全性,系統(tǒng)會重新創(chuàng)建一些對象(AccessibilityEvent娇昙、AccessibilityNodeInfo)來間接保存這些數(shù)據(jù)尺迂,然后通過跨進程將這些數(shù)據(jù)返回給對應(yīng)的Service中。使用范圍
首先冒掌,輔助功能不可能直接操作外部對象噪裕,輔助功能只能在本進程調(diào)用指定系統(tǒng)方法,由系統(tǒng)再分發(fā)給指定外部對象股毫,輔助功能做的事基本和用戶能做的差不多(比如回復微信, 微信搶紅包)
AccessibilityService用法
- 首先,
AccessibilityService
本質(zhì)上也是一個Service, 所以在Manifest.xml 中還是需要注冊對應(yīng)的Service內(nèi)容, 并且聲明權(quán)限, 示例如下:
<service
android:name=".RobService"
android:enabled="true"
android:exported="true"
android:label="學習強國"
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/myaccessibility"/>
</service>
其中resource中的配置項是單獨創(chuàng)建一個myaccessibility.xml文件
<?xml version="1.0" encoding="utf-8"?>
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
android:accessibilityEventTypes="typeAllMask" // 監(jiān)聽的事件類型, 這里表示全局監(jiān)聽
android:accessibilityFeedbackType="feedbackGeneric" //反饋類型, 這里表示通用反饋
android:accessibilityFlags="flagDefault|flagRetrieveInteractiveWindows|flagIncludeNotImportantViews"
android:canRetrieveWindowContent="true" //表示該服務(wù)能否訪問活動窗口中的內(nèi)容.也就是如果你希望在服務(wù)中獲取窗體內(nèi)容的話,則需要設(shè)置其值為true.
android:notificationTimeout="100" // 接受事件的時間間隔
android:canPerformGestures="true" //分發(fā)手勢
android:packageNames="com.tencent.mm"/>
在注冊服務(wù)完成后, 就可以創(chuàng)建一個Service繼承AccessibilityService, 并且實現(xiàn)它的
onServiceConnected
和onAccessibilityEvent
方法, 其中, 在onServiceConnected
方法中放一些資源的初始化操作, 此方法會在開啟了AccessibilityService權(quán)限的時候被調(diào)用. 在onAccessibilityEvent
實現(xiàn)對事件的處理, 比如屏幕改變事件, 消息通知事件.-
控件的查找與操作
控件的操作主要分為幾個步驟:獲取到當前界面的根節(jié)點
AccessibilityNodeInfo rootNode = getRootInActiveWindow();
-
通過id或者text文本查找到對應(yīng)的節(jié)點
- 在sdk-tools/tools目錄下, 有一個monitor.bat腳本, 雙擊這個腳本打開
Android Device Monitor
- 在電腦連接了安卓手機并且開啟了USB調(diào)試模式的情況下,
Android Device Monitor
會顯示出對應(yīng)的手機, 點擊上面的Dump View
按鈕, 此時工具會自動對當前手機界面進行分析, 并生成一個dump -
最后得到類似下圖, 用鼠標移動到對應(yīng)的控件上, 即可看到控件的屬性和文本等
截圖
控件屬性
- 在sdk-tools/tools目錄下, 有一個monitor.bat腳本, 雙擊這個腳本打開
對節(jié)點進行操作, 這里要注意到, 有一些程序做了特殊處理, 有時候在
Android Device Monitor
看到clickable屬性為true, 但不一定它就會響應(yīng)click事件, 是否響應(yīng)事件要按實際情況分析.
//獲取當前聊天頁面的根布局
AccessibilityNodeInfo rootNode = getRootInActiveWindow();
List<AccessibilityNodeInfo> listChat = rootNode.findAccessibilityNodeInfosByViewId("android:id/text1"); //根據(jù)id查找控件
//List<AccessibilityNodeInfo> listChat = rootNode.findAccessibilityNodeInfosByText("發(fā)送"); //根據(jù)文本查找控件
for (AccessibilityNodeInfo nodeInfo : listChatRecord) {
nodeInfo.performAction(AccessibilityNodeInfo.ACTION_CLICK); //點擊控件
}
- 手勢
Android提供了特殊類型的觸摸屏事件膳音,如捏合,雙擊铃诬,滾動祭陷,長按和退縮。這些都被稱為手勢趣席。
//發(fā)送一個點擊事件
Path mPath=new Path();//線性的path代表手勢路徑,點代表按下,封閉的沒用
mPath.moveTo(500, 500);
service.dispatchGesture(new GestureDescription.Builder().addStroke(new GestureDescription.StrokeDescription
(mPath, 手勢開始時間比如立即開始0, 手勢總時長比如100)).build(), 回調(diào)函數(shù)(可以為null), 回調(diào)的線程(null表示主線程));
擴展使用
- 使用webview通過js調(diào)用android代碼
在android的方法定義中, 加上@JavaScriptInterface
注釋后, 在webView.addJavascriptInterface(new JsInterface(), "Android");
然后在js中執(zhí)行"Android.方法名"
附錄
accessibilityEventTypes的取值
| constant | value | 描述 |
| - | - | - |
| typeAllMask|ffffffff|所有類型的事件
|typeAnnouncement|4000|一個應(yīng)用產(chǎn)生一個通知事件
|typeAssistReadingContext|1000000|輔助用戶讀取當前屏幕事件
|typeContextClicked|800000|view中上下文點擊事件
|typeGestureDetectionEnd|80000|監(jiān)測到的手勢事件完成
|typeGestureDetectionStart|40000|開始手勢監(jiān)測事件
|typeNotificationStateChanged|40|收到notification彈出消息事件
|typeTouchExplorationGestureEnd|400|觸摸瀏覽事件完成
|typeTouchExplorationGestureStart|200|觸摸瀏覽事件開始
|typeTouchInteractionEnd|200000|用戶觸屏事件結(jié)束
|typeTouchInteractionStart|100000|觸摸屏幕事件開始
|typeViewAccessibilityFocusCleared|10000|無障礙焦點事件清除
|typeViewAccessibilityFocused|8000|獲得無障礙的焦點事件
|typeViewClicked|1|點擊事件
|typeViewFocused|8|view獲取到焦點事件
|typeViewHoverEnter|80|一個view的懸停事件
|typeViewHoverExit|100|一個view的懸停事件結(jié)束兵志,懸停離開該view
|typeViewLongClicked|2|view的長按事件
|typeViewScrolled|1000|view的滾動事件,adapterview宣肚、scrollview
|typeViewSelected|4|view選中想罕,一般是具有選中屬性的view,例如adapter
|typeViewTextChanged|10|edittext中文字發(fā)生改變的事件
|typeViewTextSelectionChanged|2000|edittext文字選中發(fā)生改變事件
|typeViewTextTraversedAtMovementGranularity|20000|UIanimator中在一個視圖文本中進行遍歷會產(chǎn)生這個事件霉涨,多個粒度遍歷文本按价。一般用于語音閱讀context
|typeWindowContentChanged|800|窗口的內(nèi)容發(fā)生變化惭适,或者更具體的子樹根布局變化事件
|typeWindowStateChanged|20|新的彈出層導致的窗口變化(dialog、menu俘枫、popupwindow)
|typeWindowsChanged|400000|屏幕上的窗口變化事件,需要API 21+`accessibilityFeedbackType 此服務(wù)提供的反饋類型
constant | value | 描述 |
---|---|---|
feedbackAllMask | ffffffff | 取消所有的可用反饋方式 |
feedbackAudible | 4 | 可聽見的(非語音反饋) |
feedbackGeneric | 10 | 通用反饋 |
feedbackHaptic | 2 | 觸覺反饋(震動) |
feedbackSpoken | 1 | 語音反饋 |
feedbackVisual | 8 | 視覺反饋 |
- accessibilityFlags 輔助功能附加的標志逮走,多個使用 ' | '分隔
constant | value | 描述 |
---|---|---|
flagDefault | 1 | 默認的配置 |
flagEnableAccessibilityVolume | 80 | 這個標志要求系統(tǒng)內(nèi)所有的音頻通道鸠蚪,使用由STREAM_ACCESSIBILTY音量控制USAGE_ASSISTANCE_ACCESSIBILITY |
flagIncludeNotImportantViews | 2 | 表示可獲取到一些被表示為輔助功能無權(quán)獲取到的view |
flagReportViewIds | 10 | 使用該flag表示可獲取到view的ID |
flagRequestAccessibilityButton | 100 | 如果輔助功能可用,提供一個輔助功能按鈕在系統(tǒng)的導航欄 API 26+ |
flagRequestEnhancedWebAccessibility | 8 | 此類擴展的目的是為WebView中呈現(xiàn)的內(nèi)容提供更好的輔助功能支持师溅。這種擴展的一個例子是從一個安全的來源注入JavaScript茅信。如果至少有一個具有此標志的輔助功能服務(wù), 則系統(tǒng)將使能增強的web輔助功能。因此, 清除此標志并不保證該設(shè)備不會使能增強的web輔助功能, 因為可能有另一個使能的服務(wù)在使用它墓臭。 |
flagRequestFilterKeyEvents | 20 | 能夠監(jiān)聽到系統(tǒng)的物理按鍵 |
flagRequestFingerprintGestures | 200 | 監(jiān)聽系統(tǒng)的指紋手勢 API 26+ |
flagRequestTouchExplorationMode | 4 | 系統(tǒng)進入觸控探索模式蘸鲸。出現(xiàn)一個鼠標在用戶的界面 |
flagRetrieveInteractiveWindows | 40 | 該標志知識的輔助服務(wù)要訪問所有交互式窗口內(nèi)容的系統(tǒng),這個標志沒有被設(shè)置時窿锉,服務(wù)不會收到TYPE_WINDOWS_CHANGE事件酌摇。 |