【发布时间】:2015-04-25 01:33:19
【问题描述】:
我正在为 Android 编写一个 AccessibilityService,直到 API 级别 20,我一直在使用 AccessibilityEvent.getSource() 方法在触发 onAccessibilityEvent(AccessibilityEvent event) 时获取可遍历的 AccessibilityNodeInfo。虽然生成的AccessibilityNodeInfo 并不总是反映屏幕的内容,但仍然可以使用它。
从 API 级别 21 开始,新的 AccessibilityService.getWindows() 应该不仅能够更好地表示视图层次结构(即,尊重 Z 顺序),而且还应该能够公开一个节点包括当前输入法 (IME) 中的所有视图。我想利用这一点,但我无法这样做,我不知道我到底做错了什么。顺便说一句,除了极少的 java 文档之外,我找不到任何有关如何执行此操作的更详细信息。
我已经做了以下事情:
- 配置服务以检索窗口内容 (
android:canRetrieveWindowContent="true") - 在服务标志中添加了
flagRetrieveInteractiveWindows
我的代码如下:
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
ArrayList<AccessibilityNodeInfo> nodes = getNodesFromWindows();
switch (event_type) {
case AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED:
case AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED:
case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED:
//case AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED:
case AccessibilityEvent.TYPE_VIEW_FOCUSED:
case AccessibilityEvent.TYPE_VIEW_SELECTED:
case AccessibilityEvent.TYPE_VIEW_SCROLLED:
//case AccessibilityEvent.TYPE_VIEW_CLICKED:
updateTargetLeafs(nodes);
}
}
getNodesFromWindows() 在哪里执行以下操作:
private ArrayList<AccessibilityNodeInfo> getNodesFromWindows() {
List<AccessibilityWindowInfo> windows = getWindows();
ArrayList<AccessibilityNodeInfo> nodes =
new ArrayList<AccessibilityNodeInfo>();
if (windows.size() > 0) {
for (AccessibilityWindowInfo window : windows) {
nodes.add(window.getRoot());
}
}
return nodes;
}
在此之后,updateTargetLeafs() 将所有可点击、启用和可见的节点收集到一个单独的 AccessibilityNodeInfo ArrayList 中,以便我可以随意索引和访问它们(见下文)。在 API 级别 20 及以下使用 AccessibilityEvent.getSource() 时,此数组的大小始终接近屏幕上的视图数量,但当我使用 AccessibilityService.getWindows() 时,大小几乎始终为 1(有时为 0),并且边界列表中唯一的AccessibilityNodeInfo 总是在屏幕之外。
编辑:添加用于遍历所有子节点的代码(其中mNodes 是getNodesFromWindows() 的输出):
...
ArrayList<AccessibilityNodeInfo> theseleafs =
new ArrayList<AccessibilityNodeInfo>();
AccessibilityNodeInfo thisnode;
Queue<AccessibilityNodeInfo> q =
new LinkedList<AccessibilityNodeInfo>();
for (AccessibilityNodeInfo n : mNodes) {
q.add(n);
}
while (!q.isEmpty()) {
thisnode = q.poll();
if (shouldIncludeNode(thisnode)) {
//Add only if it fulfills all requirements!
theseleafs.add(thisnode);
}
for (i=0; i<thisnode.getChildCount(); ++i) {
AccessibilityNodeInfo n = thisnode.getChild(i);
if (n != null) q.add(n); // Add only if not null!
}
};
LogD("MyTag", theseleafs.size() + " leafs in this node!");
...
奇怪,我知道,但我做错了什么?
【问题讨论】:
标签: java android accessibility android-5.0-lollipop accessibilityservice