您可以随时随地从辅助服务中搜索辅助功能视图层次结构!虽然我建议从某种类型的可访问性事件的上下文中这样做,但您确保有屏幕内容可以遍历!这样做随机回调是最好的挑剔。这是合理的无障碍配置XML文件,使用这样的目的:
<?xml version="1.0" encoding="utf-8"?>
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
android:description="@string/accessibility_service_description"
android:accessibilityEventTypes="typeWindowContentChanged|typeWindowsChanged|typeWindowStateChanged"
android:accessibilityFlags="flagReportViewIds|flagIncludeNotImportantViews"
android:canRetrieveWindowContent="true"
android:accessibilityFeedbackType="feedbackGeneric"
android:notificationTimeout="1000"
android:settingsActivity=".SettingsActivity"
/>
下面是关于几个字段专门的一些意见。
机器人:notificationTimeout = “1000”
只有每秒获取给定类型的可访问性事件一次!在列出的事件中,任何较低的设置都是非常详细的。我们只依靠这个来调用我们的回调函数,并确保我们有节点。为了达到这些目的,每秒一次就是DUSTY。根据需要调整。
机器人:accessibilityEventTypes = “typeWindowContentChanged | typeWindowsChanged | typeWindowStateChanged”
粗略地说,这是事件,让你赶上所有的屏幕改变事件的子集。打开一个新窗口...扫描视图层次结构!
机器人:accessibilityFlags = “flagReportViewIds | flagIncludeNotImportantViews”
标志包括并不重要意见将包括AccessibilityNodeInfo层次结构有更多的意见。特别是许多布局视图,Android OS通常不会认为这是必需的。我喜欢离开这个检查,因为这也是一个开发人员可调整的属性,Android开发人员在可访问性方面非常愚蠢。最好只是抓取所有东西,并通过自己排序!
好的,所以有你的服务配置!现在,其余的很容易。你想要做的是通过根节点子节点进行递归,直到找到一个TextView节点。我在下面设置了一个愚蠢的服务,它会在每个屏幕上更新第一个TextView节点(除非它们在上面的服务配置XML中每秒超过一次),然后记录其屏幕坐标。
class MyAccessibilityService extends AccessibilityService {
@Override
public void onAccessibilityEvent(AccessibilityEvent e) {
//You can actually call getRootInActiveWindow() any time!
//Doing so here ensures that the screen is in a reasonable state
//and not in the middle of rendering or something else silly.
final AccessibilityNodeInfo textNodeInfo = findTextViewNode(getRootInActiveWindow());
if (textNodeInfo == null) return;
Rect rect = new Rect();
textNodeInfo.getBoundsInScreen(rect);
Log.i(A11yService.class.getSimpleName(), "The TextView Node: " + rect.toString());
}
public AccessibilityNodeInfo findTextViewNode(AccessibilityNodeInfo nodeInfo) {
//I highly recommend leaving this line in! You never know when the screen content will
//invalidate a node you're about to work on, or when a parents child will suddenly be gone!
//Not doing this safety check is very dangerous!
if (nodeInfo == null) return null;
Log.v(A11yService.class.getSimpleName(), nodeInfo.toString());
//Notice that we're searching for the TextView's simple name!
//This allows us to find AppCompat versions of TextView as well
//as 3rd party devs well names subclasses... though with perhaps
//a few poorly named unintended stragglers!
if (nodeInfo.getClassName().toString().contains(TextView.class.getSimpleName())) {
return nodeInfo;
}
//Do other work!
for (int i = 0; i < nodeInfo.getChildCount(); i++) {
AccessibilityNodeInfo result = findTextViewNode(nodeInfo.getChild(i));
if (result != null) return result;
}
return null;
}
//Required for a valid Accessibility Service.
@Override
public void onInterrupt() {}
}
你也可以寻找开源库我建的Accessibility Service Utilities,使所有的这些东西容易得多! A11yNodeInfoMatcher类是你想要的。