国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

AccessibilityService(無障礙服務)小結

2019-11-09 13:56:25
字體:
來源:轉載
供稿:網友

https://developer.android.google.cn/guide/topics/ui/accessibility/services.html 無障礙服務,可以監聽界面的操作,比如:點擊、拖動、界面更新等信息。更為強大的是可以獲取屏幕信息,同時具備普通Service的能力。(在別人手機中植入一個無障礙服務并開啟,可以監聽他的手機操作和屏幕信息,eg:獲取微信、QQ當前聊天文字并上傳) 因為無障礙服務相比一般Service過于強大,安裝后還需要在設置->輔助功能中手動開啟。

創建AccessibilityService與聲明

https://developer.android.google.cn/reference/android/accessibilityservice/AccessibilityService.html

創建一個類繼承自AccessibilityService

public class MyAccessibilityService extends AccessibilityService{ @Override PRotected void onServiceConnected() { super.onServiceConnected(); } @Override public void onAccessibilityEvent(AccessibilityEvent event) { } @Override public void onInterrupt() { } @Override public boolean onUnbind(Intent intent) { return super.onUnbind(intent); } }

AccessibilityService繼承自普通的Service,因而具備普通Service的生存周期,同時具有自己的一些生命周期。

函數名 描述
onServiceConnected() (可選)當系統成功連接到該AccessibilityService時,將調用此方法。主要用與一次性配置或調整的代碼。
onAccessibilityEvent() (必要)當系統監測到相匹配的AccessibilityEvent事件時,將調用此方法,在整個Service的生命周期中,該方法將被多次調用。
onInterrupt() (必要)系統需要中斷AccessibilityService反饋時,將調用此方法。AccessibilityService反饋包括服務發起的震動、音頻等行為。
onUnbind() (可選)系統要關閉該服務是,將調用此方法。主要用來釋放資源。

AccessibilityService服務聲明

和普通Service一樣,AccessibilityService同樣需要在Manifest.xml中注冊。

<service android:name=".MyAccessibilityService" android:label="@string/accessibility_service_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/accessibility_service_config" /></service>

android.permission.BIND_ACCESSIBILITY_SERVICE權限和action是必須的。 同時AccessibilityService需要提供設置列表(meta-data),該設置也可以在運行時通過AccessibilityService.setServiceInfo (AccessibilityServiceInfo info)進行動態設置。不過該方式并不能設置所有的參數,因而推薦的方法為(meta-data)。 android:resource中的地址為:/res/xml/accessibility_service_config.xml。

<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android" android:descr各項參數參考AccessibilityServiceInfo。

AccessibilityServiceInfo 配置類

https://developer.android.google.cn/reference/android/accessibilityservice/AccessibilityServiceInfo.html AccessibilityService的配置類,可使用setService進行動態設置,同時和上述的accessibility_service_config.xml相對應。 以下參數可以使用“|”表示使用多個選項。

android:accessibilityEventTypes 事件類型

AccessibilityService服務響應的事件類型,只有聲明了的類型,系統才會調用該服務的onAccessibilityEvent。

常量 描述
typeViewClicked 點擊事件
typeViewSelected view被選擇
typeViewScrolled 滑動事件
typeWindowContentChanged 窗口內容該表
typeAllMask 所有事件

完整列表如下: typeViewClicked typeViewLongClicked typeViewSelected typeViewFocused typeViewTextChanged typeWindowStateChanged typeNotificationStateChanged typeViewHoverEnter typeViewHoverExit typeTouchExplorationGestureStart typeTouchExplorationGestureEnd typeWindowContentChanged typeViewScrolled typeViewTextSelectionChanged typeAnnouncement typeViewAccessibilityFocused typeViewAccessibilityFocusCleared typeViewTextTraversedAtMovementGranularity typeGestureDetectionStart typeGestureDetectionEnd typeTouchInteractionStart typeTouchInteractionEnd typeWindowsChanged typeContextClicked typeAssistReadingContext typeAllMask

android:accessibilityFeedbackType 反饋類型

AccessibilityService服務的反饋類型。

常量 描述
feedbackSpoken 語音反饋
feedbackHaptic 觸覺(震動)反饋
feedbackAudible 音頻反饋
feedbackVisual 視頻反饋
feedbackGeneric 通用反饋
feedbackAllMask 以上都具有

android:accessibilityFlags 額外聲明

一些格外的參數。

常量 描述
flagDefault 默認
flagIncludeNotImportantViews
flagRequestTouchExplorationMode
flagRequestEnhancedWebAccessibility
flagReportViewIds 允許獲得view id,需要獲取viewid的時候需要該參數,開始沒聲明導致nodeInfo. getViewIdResourceName()返回的為null
flagRequestFilterKeyEvents
flagRetrieveInteractiveWindows 允許獲得windows,使用getWindows時需要該參數,否則會返回空列表

其他可設置參數

參數名 描述
android:canRetrieveWindowContent 設置為“true”表示允許獲取屏幕信息,使用getWindows、getRootInActiveWindow等函數時需要為“true”
android:packageNames 服務響應的事件來源,若設置,則服務只能獲取該package發出的事件,不設置可獲得所有的事件源
android:notificationTimeout 同一種事件類型觸發的最短時間間隔(毫秒)
android:description 服務和行為的簡短描述

AccessibilityEvent 事件類

https://developer.android.google.cn/reference/android/view/accessibility/AccessibilityEvent.html 常用實例化途徑:在MyAccessibilityService 中 onAccessibilityEvent(AccessibilityEvent event) 獲得該實例,表示監聽事件觸發。

返回值 方法 描述
int getEventType() 獲取事件類型(點擊等)
CharSequence getPackageName() 時間來源包名
String toString() 打印事件

AccessibilityNodeInfo 結點類

https://developer.android.google.cn/reference/android/view/accessibility/AccessibilityNodeInfo.html 常用實例化途徑:AccessibilityService.getRootInActiveWindow()獲得(當前活動窗口的根節點)。AccessibilityWindowInfo類也能獲取該window下的node。 該類與下圖有對應關系(通過uiautomatorviewer工具獲得): image 常用方法:

返回值 方法 描述
List findAccessibilityNodeInfosByText(String text) 通過text尋找子節點
List findAccessibilityNodeInfosByViewId(String viewId) 通過id查找子節點
CharSequence getPackageName() Gets the package this node comes from.
AccessibilityNodeInfo getParent() Gets the parent.
AccessibilityNodeInfo getChild(int index) Get the child at given index.
int getChildCount() Gets the number of children.
CharSequence getText() Gets the text of this node.
String getViewIdResourceName() Gets the fully qualified resource name of the source view’s id.
AccessibilityWindowInfo getWindow() Gets the window to which this node belongs.
boolean isChecked() Gets whether this node is checked.
String toString() Returns a string representation of the object.

比如: 遍歷打印當前布局信息可以使用一下代碼(布局節點樹)

@Override public void onAccessibilityEvent(AccessibilityEvent accessibilityEvent) { if(accessibilityEvent.getEventType() == AccessibilityEvent.TYPE_VIEW_CLICKED){ AccessibilityNodeInfo nodeInfo = getRootInActiveWindow(); dfsnode(nodeInfo,0); } } public void dfsnode(AccessibilityNodeInfo node , int num){ StringBuilder stringBuilder = new StringBuilder(); for(int i = 0 ;i < num ; i++){ stringBuilder.append("__ "); //父子節點之間的縮進 } Log.i("####",stringBuilder.toString() + node.toString()); //打印 for(int i = 0 ; i < node.getChildCount() ; i++){ //遍歷子節點 dfsnode(node.getChild(i),num+1); } }

AccessibilityWindowInfo 窗口類

https://developer.android.google.cn/reference/android/view/accessibility/AccessibilityWindowInfo.html 常用實例化途徑:AccessibilityService.getWindows()獲得,返回值是一個list列表。

返回值 方法 描述
AccessibilityNodeInfo getRoot() 獲得該窗口的根節點信息
AccessibilityWindowInfo getChild(int index) Gets the child window at a given index.
int getChildCount() Gets the number of child windows.
int getId() Gets the unique window id.
boolean isActive() Gets if this window is active.
boolean isFocused() Gets if this window has input focus.

綜合應用,搶紅包插件

代碼來自涅槃1992:http://www.jianshu.com/p/4cd8c109cdfb 配置代碼:

<?xml version="1.0" encoding="utf-8"?><accessibility-service xmlns:android="http://schemas.android.com/apk/res/android" android:accessibilityEventTypes="typeNotificationStateChanged|typeWindowStateChanged| typeWindowContentChanged" android:accessibilityFeedbackType="feedbackGeneric" android:accessibilityFlags="flagDefault" android:canRetrieveWindowContent="true" android:notificationTimeout="100" android:packageNames="com.tencent.mm" />

Service代碼:

public class RobService extends AccessibilityService { @Override public void onAccessibilityEvent(AccessibilityEvent event) { int eventType = event.getEventType(); switch (eventType) { case AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED: handleNotification(event); break; case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED: case AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED: String className = event.getClassName().toString(); if (className.equals("com.tencent.mm.ui.LauncherUI")) { getPacket(); } else if (className.equals("com.tencent.mm.plugin.luckymoney.ui.LuckyMoneyReceiveUI")) { openPacket(); } else if (className.equals("com.tencent.mm.plugin.luckymoney.ui.LuckyMoneyDetailUI")) { close(); } break; } } /** * 處理通知欄信息 * * 如果是微信紅包的提示信息,則模擬點擊 * * @param event */ private void handleNotification(AccessibilityEvent event) { List<CharSequence> texts = event.getText(); if (!texts.isEmpty()) { for (CharSequence text : texts) { String content = text.toString(); //如果微信紅包的提示信息,則模擬點擊進入相應的聊天窗口 if (content.contains("[微信紅包]")) { if (event.getParcelableData() != null && event.getParcelableData() instanceof Notification) { Notification notification = (Notification) event.getParcelableData(); PendingIntent pendingIntent = notification.contentIntent; try { pendingIntent.send(); } catch (PendingIntent.CanceledException e) { e.printStackTrace(); } } } } } } /** * 關閉紅包詳情界面,實現自動返回聊天窗口 */ @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2) private void close() { AccessibilityNodeInfo nodeInfo = getRootInActiveWindow(); if (nodeInfo != null) { //為了演示,直接查看了關閉按鈕的id List<AccessibilityNodeInfo> infos = nodeInfo.findAccessibilityNodeInfosByViewId("@id/ez"); nodeInfo.recycle(); for (AccessibilityNodeInfo item : infos) { item.performAction(AccessibilityNodeInfo.ACTION_CLICK); } } } /** * 模擬點擊,拆開紅包 */ @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2) private void openPacket() { AccessibilityNodeInfo nodeInfo = getRootInActiveWindow(); if (nodeInfo != null) { //為了演示,直接查看了紅包控件的id List<AccessibilityNodeInfo> list = nodeInfo.findAccessibilityNodeInfosByViewId("@id/b9m"); nodeInfo.recycle(); for (AccessibilityNodeInfo item : list) { item.performAction(AccessibilityNodeInfo.ACTION_CLICK); } } } /** * 模擬點擊,打開搶紅包界面 */ @TargetApi(Build.VERSION_CODES.JELLY_BEAN) private void getPacket() { AccessibilityNodeInfo rootNode = getRootInActiveWindow(); AccessibilityNodeInfo node = recycle(rootNode); node.performAction(AccessibilityNodeInfo.ACTION_CLICK); AccessibilityNodeInfo parent = node.getParent(); while (parent != null) { if (parent.isClickable()) { parent.performAction(AccessibilityNodeInfo.ACTION_CLICK); break; } parent = parent.getParent(); } } /** * 遞歸查找當前聊天窗口中的紅包信息 * * 聊天窗口中的紅包都存在"領取紅包"一詞,因此可根據該詞查找紅包 * * @param node */ public AccessibilityNodeInfo recycle(AccessibilityNodeInfo node) { if (node.getChildCount() == 0) { if (node.getText() != null) { if ("領取紅包".equals(node.getText().toString())) { return node; } } } else { for (int i = 0; i < node.getChildCount(); i++) { if (node.getChild(i) != null) { recycle(node.getChild(i)); } } } return node; } @Override public void onInterrupt() { } @Override protected void onServiceConnected() { super.onServiceConnected(); }}
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 太保市| 安阳市| 眉山市| 西乌珠穆沁旗| 合江县| 苍梧县| 都匀市| 通辽市| 苏尼特右旗| 浪卡子县| 奇台县| 湘潭县| 辽阳县| 夏河县| 铁岭县| 平顶山市| 宿松县| 蒲江县| 那曲县| 康保县| 安阳县| 黄骅市| 屯昌县| 邢台县| 康乐县| 西林县| 甘德县| 阿勒泰市| 嘉义市| 雅安市| 巴彦县| 尼玛县| 彭泽县| 台南市| 阿拉善左旗| 福贡县| 博客| 宣化县| 楚雄市| 英超| 福泉市|