1. xml
<?xml version="1.0" encoding="utf-8"?>
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
android:accessibilityEventTypes="typeAllMask"
android:accessibilityFeedbackType="feedbackAllMask"
android:accessibilityFlags="flagDefault|flagRetrieveInteractiveWindows|flagIncludeNotImportantViews"
android:canPerformGestures="true"
android:canRequestFilterKeyEvents="true"
android:canRetrieveWindowContent="true"
android:canRequestEnhancedWebAccessibility="true"
android:description="@string/accessibility_desc"
android:notificationTimeout="100"/>
2.manifest
<service
android:name=".service.MainService"
android:enabled="true"
android:exported="true"
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_config"/>
</service>
3.获取控件信息
public class MainService extends AccessibilityService {
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
switch (event.getEventType()) {
//窗口内容发生改变时触发
case AccessibilityEvent.TYPE_VIEW_CLICKED:
//跳转到新的页面,或者弹出了window,dialog等
case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED:
//滚动时触发
case AccessibilityEvent.TYPE_VIEW_SCROLLED:
//某个view的内容发生的变化时触发
case AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED:
break;
}
// 此方法是在主线程中回调过来的,所以消息是阻塞执行的
// 获取包名
if (event.getPackageName() != null) {
String pkgName = event.getPackageName().toString();
}
int eventType = event.getEventType();
String eventText = "";
switch (eventType) {
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;
}
Log.i("eventType: ", eventText);
}
@Override
public void onInterrupt() {
Log.d(TAG, "onInterrupt()");
}
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate()");
//获取当前事件下的节点列表组
AccessibilityNodeInfo rowNode = getRootInActiveWindow();
if (rowNode != null) {
for (int i = 0; i < rowNode.getChildCount(); i++) {
if (rowNode.getChild(i) != null) {
recycle(rowNode.getChild(i));
}
}
}
/**
* 循环遍历窗口节点
*
* @param info
*/
public static void recycle(AccessibilityNodeInfo info) {
if (info.getChildCount() == 0) {
Log.i(TAG, "child widget:" + info.getClassName());
Log.i(TAG, "showDialog:" + info.canOpenPopup());
Log.i(TAG, "Text:" + info.getText());
Log.i(TAG, "windowId:" + info.getWindowId());
//添加至节点列表
nodeList.add(info);
} else {
for (int i = 0; i < info.getChildCount(); i++) {
if (info.getChild(i) != null) {
recycle(info.getChild(i));
}
}
}
}
}