简介

AccessibilityService的设计初衷是为了辅助有身体缺陷的群体使用Android应用,它的设计贯穿着Android的控件树View, ViewGroup, ViewRootImpl体系。借助于system_server进程的中转,能够注册Accessibility事件的客户端可以具备通过system_server提供的Accessibility服务来实现监听、操作其它应用视图的功能。这个功能十分强大,可以模拟用户的行为去操作其它APP,常常被用在自动化测试、微信抢红包、自动回复等功能实现中。
写这个的初衷有二:
整体图
类图
整体设计图
实例代码
public class AutoDismissService extends AccessibilityService {
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
if (event == null) {
return;
}
// 自动将android系统弹出的其它crash dialog取消
dismissAppErrorDialogIfExists(event);
}
private void dismissAppErrorDialogIfExists(AccessibilityEvent event) {
// WINDOW视图变化才进行对应操作
if ((event.getEventType() == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED
&& event.getPackageName().equals("android")) {
// 查找带有"OK"字符的可点击Node
AccessibilityNodeInfo nodeInfo = findViewByText("OK", true);
if (nodeInfo != null) {
// 查找到后执行点击操作
performViewClick(nodeInfo);
}
}
public AccessibilityNodeInfo findViewByText(String text, boolean clickable) {
// 获取当前窗口父节点
AccessibilityNodeInfo accessibilityNodeInfo = getRootInActiveWindow();
if (accessibilityNodeInfo == null) {
return null;
}
// 获取到满足字符要求的节点
List nodeInfoList = accessibilityNodeInfo.findAccessibilityNodeInfosByText(text);
if (nodeInfoList != null && !nodeInfoList.isEmpty()) {
for (AccessibilityNodeInfo nodeInfo : nodeInfoList) {
if (nodeInfo != null && (nodeInfo.isClickable() == clickable)) {
return nodeInfo;
}
}
}
return null;
}
public void performViewClick(AccessibilityNodeInfo nodeInfo) {
if (nodeInfo == null) {
return;
}
// 由下至上进行查询,直到寻找到可点击的节点
while (nodeInfo != null) {
if (nodeInfo.isClickable()) {
nodeInfo.performAction(AccessibilityNodeInfo.ACTION_CLICK);
break;
}
nodeInfo = nodeInfo.getParent();
}
}
}