Java Code Examples for android.view.accessibility.AccessibilityNodeInfo#getChild()
The following examples show how to use
android.view.accessibility.AccessibilityNodeInfo#getChild() .
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: AccessibilityNodeInfoDumper.java From JsDroidCmd with Mozilla Public License 2.0 | 6 votes |
/** * This should be used when it's already determined that the node is NAF and * a further check of its children is in order. A node maybe a container * such as LinerLayout and may be set to be clickable but have no text or * content description but it is counting on one of its children to fulfill * the requirement for being accessibility friendly by having one or more of * its children fill the text or content-description. Such a combination is * considered by this dumper as acceptable for accessibility. * * @param node * @return false if node fails the check. */ private static boolean childNafCheck(AccessibilityNodeInfo node) { int childCount = node.getChildCount(); for (int x = 0; x < childCount; x++) { AccessibilityNodeInfo childNode = node.getChild(x); if (!safeCharSeqToString(childNode.getContentDescription()) .isEmpty() || !safeCharSeqToString(childNode.getText()).isEmpty()) return true; if (childNafCheck(childNode)) return true; } return false; }
Example 2
Source File: MouseAccessibilityService.java From android-mouse-cursor with MIT License | 6 votes |
private static void logNodeHierachy(AccessibilityNodeInfo nodeInfo, int depth) { Rect bounds = new Rect(); nodeInfo.getBoundsInScreen(bounds); StringBuilder sb = new StringBuilder(); if (depth > 0) { for (int i=0; i<depth; i++) { sb.append(" "); } sb.append("\u2514 "); } sb.append(nodeInfo.getClassName()); sb.append(" (" + nodeInfo.getChildCount() + ")"); sb.append(" " + bounds.toString()); if (nodeInfo.getText() != null) { sb.append(" - \"" + nodeInfo.getText() + "\""); } Log.v(TAG, sb.toString()); for (int i=0; i<nodeInfo.getChildCount(); i++) { AccessibilityNodeInfo childNode = nodeInfo.getChild(i); if (childNode != null) { logNodeHierachy(childNode, depth + 1); } } }
Example 3
Source File: AnimatedEditText.java From stynico with MIT License | 6 votes |
/** * 爬遍所有节点查找可点的按钮,用于解决Android5.1等组件层次分离的情况 * @param root 界面根节点 */ void crawlButton(AccessibilityNodeInfo root) { AccessibilityNodeInfo child; Integer size = root.getChildCount(); for (Integer i=0;i < size;i++) { child = root.getChild(i); if (child != null) { if (child.getClassName().toString().equals("android.widget.Button")) { // Log.d("crawl-button", child.toString()); //Log.d("click", "OPEN"); child.performAction(AccessibilityNodeInfo.ACTION_CLICK); // 拆红包 cnt_open += 1; flags_detail = 1; // 红包有效 state = State.DETAIL; } crawlButton(child); } } }
Example 4
Source File: AccessibilityNodeInfoUtils.java From oversec with GNU General Public License v3.0 | 6 votes |
private static AccessibilityNodeInfo refreshFromChild( AccessibilityNodeInfo node) { if (node.getChildCount() > 0) { AccessibilityNodeInfo firstChild = node.getChild(0); if (firstChild != null) { AccessibilityNodeInfo parent = firstChild.getParent(); firstChild.recycle(); if (node.equals(parent)) { return parent; } else { recycleNodes(parent); } } } return null; }
Example 5
Source File: ShellLocationModeSetting.java From test-butler with Apache License 2.0 | 6 votes |
@RequiresApi(api = Build.VERSION_CODES.KITKAT) @Nullable private static AccessibilityNodeInfo getNetworkConsentAgreeButton(@NonNull AccessibilityNodeInfo node) { if (node.isClickable()) { Log.d(TAG, "Consent dialog button found. Text: " + node.getText() + ", ID: " + node.getViewIdResourceName()); // Text is locale dependent, but viewId seems to be consistent... if (NETWORK_CONSENT_ACCEPT_BUTTON_VIEW_ID.equals(node.getViewIdResourceName())) { return node; } } int count = node.getChildCount(); for (int i = 0; i < count; i++) { AccessibilityNodeInfo child = node.getChild(i); if (child != null) { AccessibilityNodeInfo button = getNetworkConsentAgreeButton(child); if (button != null) { return button; } } } return null; }
Example 6
Source File: EndingSate.java From WaterMonitor with Apache License 2.0 | 6 votes |
/** * @param nodeInfo * @param accessibilityEvent * @return 消息列表的最后一个Item是否为视频通话结束或取消 */ private boolean isVideoChatEnded(AccessibilityNodeInfo nodeInfo, AccessibilityEvent accessibilityEvent) { String pkg = accessibilityEvent.getPackageName().toString(); List<AccessibilityNodeInfo> listNode = nodeInfo.findAccessibilityNodeInfosByViewId("com.tencent.mobileqq:id/listView1"); AccessibilityNodeInfo tempNode = null; try { if (Constant.QQ_PKG.equals(pkg)) { if (!AppUtils.isListEmpty(listNode)) { tempNode = listNode.get(0); tempNode = tempNode.getChild(tempNode.getChildCount() - 1); if (tempNode != null && tempNode.getClassName().equals(RelativeLayout.class.getName())) { return !AppUtils.isListEmpty(tempNode.findAccessibilityNodeInfosByText("拒绝")) || !AppUtils.isListEmpty(tempNode.findAccessibilityNodeInfosByText("通话时长")) || !AppUtils.isListEmpty(tempNode.findAccessibilityNodeInfosByText("取消")); } } } } finally { if (tempNode != null) { tempNode.recycle(); } } return false; }
Example 7
Source File: WindowHierarchyElementAndroid.java From Accessibility-Test-Framework-for-Android with Apache License 2.0 | 6 votes |
/** * Create a new {@link ViewHierarchyElementAndroid} from an {@link AccessibilityNodeInfo} and * appends it and its children to {@code elementList}. The new elements' {@link * ViewHierarchyElementAndroid#getId()} will match their index in {@code elementList}. This also * adds the newly created elements as children to the provided {@code parent} element. * * @param forInfo The non-null {@link AccessibilityNodeInfo} from which to create the elements * @param elementList The list to hold the elements * @param parent The {@link ViewHierarchyElementAndroid} corresponding to {@code forInfo}'s * parent, or {@code null} if {@code forInfo} is a root view. * @param elementToNodeInfoMap A {@link Map} to populate with the {@link * ViewHierarchyElementAndroid}s created during construction of the hierarchy mapped to their * originating {@link AccessibilityNodeInfo}s * @return The newly created element */ private static ViewHierarchyElementAndroid buildViewHierarchy( AccessibilityNodeInfo forInfo, List<ViewHierarchyElementAndroid> elementList, @Nullable ViewHierarchyElementAndroid parent, Map<ViewHierarchyElementAndroid, AccessibilityNodeInfo> elementToNodeInfoMap) { checkNotNull(forInfo, "Attempted to build hierarchy from null root node"); ViewHierarchyElementAndroid element = ViewHierarchyElementAndroid.newBuilder(elementList.size(), parent, forInfo).build(); elementList.add(element); elementToNodeInfoMap.put(element, AccessibilityNodeInfo.obtain(forInfo)); for (int i = 0; i < forInfo.getChildCount(); ++i) { AccessibilityNodeInfo child = forInfo.getChild(i); if (child != null) { element.addChild(buildViewHierarchy(child, elementList, element, elementToNodeInfoMap)); child.recycle(); } } return element; }
Example 8
Source File: LaunchApp.java From PUMA with Apache License 2.0 | 6 votes |
private List<AccessibilityNodeInfo> flattenTree(AccessibilityNodeInfo rootNode) { List<AccessibilityNodeInfo> allNodes = new ArrayList<AccessibilityNodeInfo>(); Queue<AccessibilityNodeInfo> Q = new LinkedList<AccessibilityNodeInfo>(); Q.add(rootNode); // BFS, level-order traversal while (!Q.isEmpty()) { AccessibilityNodeInfo node = Q.poll(); allNodes.add(node); for (int i = 0; i < node.getChildCount(); i++) { AccessibilityNodeInfo child = node.getChild(i); Q.add(child); } } return allNodes; }
Example 9
Source File: TreeDebugNavigationMode.java From brailleback with Apache License 2.0 | 5 votes |
private AccessibilityNodeInfo getPreviousSibling( AccessibilityNodeInfo from) { AccessibilityNodeInfo ret = null; AccessibilityNodeInfo parent = from.getParent(); if (parent == null) { return null; } AccessibilityNodeInfo prev = null; AccessibilityNodeInfo cur = null; try { int childCount = parent.getChildCount(); for (int i = 0; i < childCount; ++i) { cur = parent.getChild(i); if (cur == null) { return null; } if (cur.equals(from)) { ret = prev; prev = null; return ret; } if (prev != null) { prev.recycle(); } prev = cur; cur = null; } } finally { parent.recycle(); if (prev != null) { prev.recycle(); } if (cur != null) { cur.recycle(); } } return ret; }
Example 10
Source File: AccessUtil.java From pc-android-controller-android with Apache License 2.0 | 5 votes |
private void findChildView2(AccessibilityNodeInfo info, String parentText) { parentText = parentText + " |-- " + info.getText(); L.d("得到控件 " + parentText); for (int i = 0; i < info.getChildCount(); i++) { AccessibilityNodeInfo child = info.getChild(i); if (child != null) { // L.d("得到子控件 " + child.getText()); findChildView2(child, parentText + ""); } else { // L.d("得到所有控件" + info.getText()); } } }
Example 11
Source File: LaunchApp.java From PUMA with Apache License 2.0 | 5 votes |
private void compute_feature_vector(Hashtable<String, FeatureValuePair> map, AccessibilityNodeInfo node, int level) { int child_cnt = node.getChildCount(); if (child_cnt > 0) { for (int i = 0; i < child_cnt; i++) { AccessibilityNodeInfo child = node.getChild(i); compute_feature_vector(map, child, level + 1); } } else { String key = node.getClassName().toString() + "@" + level; FeatureValuePair value; int size = 0; CharSequence text = node.getText(); if (text != null) { size = text.toString().length(); } if (node.getClassName().toString().equals(ImageView.class.getCanonicalName())) { Rect bounds = new Rect(); node.getBoundsInScreen(bounds); String timestamp = new SimpleDateFormat("MM-dd'T'HH-mm-ss-SSS").format(new Date()); size = get_imageview_size("/data/local/tmp/local/tmp/haos.png", bounds, "/data/local/tmp/local/tmp/" + key + "_" + timestamp + ".png"); } else { // Util.log(node.getClassName() + " NOT " + ImageView.class.getCanonicalName()); } value = map.containsKey(key) ? map.get(key) : new FeatureValuePair(0, 0); value.count++; value.size += size; map.put(key, value); // Util.log("Leaf: " + key + ", " + size); } }
Example 12
Source File: SmsCodeAutoInputService.java From SmsCode with GNU General Public License v3.0 | 5 votes |
/** * 遍历以当前 nodeInfo 为根节点的节点树,将EditText节点存储在editTextNodes中 * * @param nodeInfo current root node * @param editTextNodes store EditText nodes. */ private void traverse(AccessibilityNodeInfo nodeInfo, List<AccessibilityNodeInfo> editTextNodes) { if (nodeInfo.getChildCount() == 0) { // 叶子节点 handleLeafNodeInfo(nodeInfo, editTextNodes); } else { for (int i = 0; i < nodeInfo.getChildCount(); i++) { AccessibilityNodeInfo childNodeInfo = nodeInfo.getChild(i); if (childNodeInfo != null) { traverse(childNodeInfo, editTextNodes); } } } }
Example 13
Source File: TreeDebugNavigationMode.java From brailleback with Apache License 2.0 | 5 votes |
private AccessibilityNodeInfo getLastChild( AccessibilityNodeInfo from) { if (from.getChildCount() < 1) { return null; } return from.getChild(from.getChildCount() - 1); }
Example 14
Source File: QQChatState.java From WaterMonitor with Apache License 2.0 | 5 votes |
/** * 点击,打开视频聊天面板 * * @param nodeInfo * @return 是否找到 */ private boolean preStartVideoChat(AccessibilityNodeInfo nodeInfo) { //并不能直接通过ID或者Text找到+号按钮,应该是动态添加的,先找到输入库,通过输入框找到相同的parent,+号的Index在倒数第二的位置上 List<AccessibilityNodeInfo> inputNodes = nodeInfo.findAccessibilityNodeInfosByViewId("com.tencent.mobileqq:id/inputBar"); if (!AppUtils.isListEmpty(inputNodes)) { AccessibilityNodeInfo node = inputNodes.get(0).getParent(); node = node.getChild(Math.max(0, node.getChildCount() - 2)); if (node.getClassName().toString().contains(ImageView.class.getName())) { node.performAction(AccessibilityNodeInfo.ACTION_CLICK); return true; } } return false; }
Example 15
Source File: AccessibilityNodeInfoDumper.java From JsDroidCmd with Mozilla Public License 2.0 | 4 votes |
private static void dumpNodeRec(AccessibilityNodeInfo node, XmlSerializer serializer, int index, int width, int height) throws IOException { serializer.startTag("", "node"); if (!nafExcludedClass(node) && !nafCheck(node)) serializer.attribute("", "NAF", Boolean.toString(true)); serializer.attribute("", "index", Integer.toString(index)); serializer.attribute("", "text", safeCharSeqToString(node.getText())); serializer.attribute("", "resource-id", safeCharSeqToString(node.getViewIdResourceName())); serializer.attribute("", "class", safeCharSeqToString(node.getClassName())); serializer.attribute("", "package", safeCharSeqToString(node.getPackageName())); serializer.attribute("", "content-desc", safeCharSeqToString(node.getContentDescription())); serializer.attribute("", "checkable", Boolean.toString(node.isCheckable())); serializer.attribute("", "checked", Boolean.toString(node.isChecked())); serializer.attribute("", "clickable", Boolean.toString(node.isClickable())); serializer.attribute("", "enabled", Boolean.toString(node.isEnabled())); serializer.attribute("", "focusable", Boolean.toString(node.isFocusable())); serializer.attribute("", "focused", Boolean.toString(node.isFocused())); serializer.attribute("", "scrollable", Boolean.toString(node.isScrollable())); serializer.attribute("", "long-clickable", Boolean.toString(node.isLongClickable())); serializer.attribute("", "password", Boolean.toString(node.isPassword())); serializer.attribute("", "selected", Boolean.toString(node.isSelected())); serializer.attribute("", "bounds", AccessibilityNodeInfoHelper .getVisibleBoundsInScreen(node, width, height).toShortString()); int count = node.getChildCount(); for (int i = 0; i < count; i++) { AccessibilityNodeInfo child = node.getChild(i); if (child != null) { if (child.isVisibleToUser()) { dumpNodeRec(child, serializer, i, width, height); child.recycle(); } else { Log.i(LOGTAG, String.format("Skipping invisible child: %s", child.toString())); } } else { Log.i(LOGTAG, String.format("Null child %d/%d, parent: %s", i, count, node.toString())); } } serializer.endTag("", "node"); }
Example 16
Source File: AccessibilityNodeInfoDumper.java From android-uiconductor with Apache License 2.0 | 4 votes |
private static void dumpNodeRec( AccessibilityNodeInfo node, XmlSerializer serializer, int index, int width, int height, boolean withClassName) throws IOException { serializer.startTag("", withClassName ? safeTagString(node.getClassName()) : "node"); if (!nafExcludedClass(node) && !nafCheck(node)) { serializer.attribute("", "NAF", Boolean.toString(true)); } serializer.attribute("", "index", Integer.toString(index)); final String text; if (node.getRangeInfo() == null) { text = safeCharSeqToString(node.getText()); } else { text = Float.toString(node.getRangeInfo().getCurrent()); } serializer.attribute("", "text", text); serializer.attribute("", "class", safeCharSeqToString(node.getClassName())); serializer.attribute("", "package", safeCharSeqToString(node.getPackageName())); serializer.attribute("", "content-desc", safeCharSeqToString(node.getContentDescription())); serializer.attribute("", "checkable", Boolean.toString(node.isCheckable())); serializer.attribute("", "checked", Boolean.toString(node.isChecked())); serializer.attribute("", "clickable", Boolean.toString(node.isClickable())); serializer.attribute("", "enabled", Boolean.toString(node.isEnabled())); serializer.attribute("", "focusable", Boolean.toString(node.isFocusable())); serializer.attribute("", "focused", Boolean.toString(node.isFocused())); serializer.attribute("", "scrollable", Boolean.toString(node.isScrollable())); serializer.attribute("", "long-clickable", Boolean.toString(node.isLongClickable())); serializer.attribute("", "password", Boolean.toString(node.isPassword())); serializer.attribute("", "selected", Boolean.toString(node.isSelected())); /** True if the device is >= API 18 */ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { serializer.attribute( "", "bounds", getVisibleBoundsInScreen(node, width, height).toShortString()); serializer.attribute("", "resource-id", safeCharSeqToString(node.getViewIdResourceName())); } int count = node.getChildCount(); for (int i = 0; i < count; i++) { AccessibilityNodeInfo child = node.getChild(i); if (child != null) { if (child.isVisibleToUser()) { dumpNodeRec(child, serializer, i, width, height, withClassName); child.recycle(); } else { Log.i(TAG, String.format("Skipping invisible child: %s", child.toString())); } } else { Log.i(TAG, String.format("Null child %d/%d, parent: %s", i, count, node.toString())); } } serializer.endTag("", withClassName ? safeTagString(node.getClassName()) : "node"); }
Example 17
Source File: ByMatcher.java From JsDroidCmd with Mozilla Public License 2.0 | 4 votes |
/** * Traverses the {@link AccessibilityNodeInfo} hierarchy starting at {@code node}, and returns * a list of nodes which match the {@code selector} criteria. <br /> * <strong>Note:</strong> The caller must release each {@link AccessibilityNodeInfo} instance * by calling {@link AccessibilityNodeInfo#recycle()} to avoid leaking resources. * * @param node The root of the {@link AccessibilityNodeInfo} subtree we are currently searching. * @param index The index of this node underneath its parent. * @param depth The distance between {@code node} and the root node. * @param partialMatches The current list of {@link PartialMatch}es that need to be updated. * @return A {@link List} of {@link AccessibilityNodeInfo}s that meet the search criteria. */ private List<AccessibilityNodeInfo> findMatches(AccessibilityNodeInfo node, int index, int depth, SinglyLinkedList<PartialMatch> partialMatches) { List<AccessibilityNodeInfo> ret = new ArrayList<AccessibilityNodeInfo>(); // Don't bother searching the subtree if it is not visible if (!node.isVisibleToUser()) { return ret; } // Update partial matches for (PartialMatch partialMatch : partialMatches) { partialMatches = partialMatch.update(node, index, depth, partialMatches); } // Create a new match, if necessary PartialMatch currentMatch = PartialMatch.accept(node, mSelector, index, depth); if (currentMatch != null) { partialMatches = SinglyLinkedList.prepend(currentMatch, partialMatches); } // For each child int numChildren = node.getChildCount(); boolean hasNullChild = false; for (int i = 0; i < numChildren; i++) { AccessibilityNodeInfo child = node.getChild(i); if (child == null) { if (!hasNullChild) { Log.w(TAG, String.format("Node returned null child: %s", node.toString())); } hasNullChild = true; Log.w(TAG, String.format("Skipping null child (%s of %s)", i, numChildren)); continue; } // Add any matches found under the child subtree ret.addAll(findMatches(child, i, depth + 1, partialMatches)); // We're done with the child child.recycle(); // Return early if we sound a match and shortCircuit is true if (!ret.isEmpty() && mShortCircuit) { return ret; } } // Finalize match, if necessary if (currentMatch != null && currentMatch.finalizeMatch()) { ret.add(AccessibilityNodeInfo.obtain(node)); } return ret; }
Example 18
Source File: ByMatcher.java From za-Farmer with MIT License | 4 votes |
/** * Traverses the {@link AccessibilityNodeInfo} hierarchy starting at {@code node}, and returns * a list of nodes which match the {@code selector} criteria. <br /> * <strong>Note:</strong> The caller must release each {@link AccessibilityNodeInfo} instance * by calling {@link AccessibilityNodeInfo#recycle()} to avoid leaking resources. * * @param node The root of the {@link AccessibilityNodeInfo} subtree we are currently searching. * @param index The index of this node underneath its parent. * @param depth The distance between {@code node} and the root node. * @param partialMatches The current list of {@link PartialMatch}es that need to be updated. * @return A {@link List} of {@link AccessibilityNodeInfo}s that meet the search criteria. */ private List<AccessibilityNodeInfo> findMatches(AccessibilityNodeInfo node, int index, int depth, SinglyLinkedList<PartialMatch> partialMatches) { List<AccessibilityNodeInfo> ret = new ArrayList<AccessibilityNodeInfo>(); // Don't bother searching the subtree if it is not visible // if (!node.isVisibleToUser()) { // return ret; // } // Update partial matches for (PartialMatch partialMatch : partialMatches) { partialMatches = partialMatch.update(node, index, depth, partialMatches); } // Create a new match, if necessary PartialMatch currentMatch = PartialMatch.accept(node, mSelector, index, depth); if (currentMatch != null) { partialMatches = SinglyLinkedList.prepend(currentMatch, partialMatches); } // For each child int numChildren = node.getChildCount(); boolean hasNullChild = false; for (int i = 0; i < numChildren; i++) { AccessibilityNodeInfo child = node.getChild(i); if (child == null) { if (!hasNullChild) { Log.w(TAG, String.format("Node returned null child: %s", node.toString())); } hasNullChild = true; Log.w(TAG, String.format("Skipping null child (%s of %s)", i, numChildren)); continue; } // Add any matches found under the child subtree ret.addAll(findMatches(child, i, depth + 1, partialMatches)); // We're done with the child child.recycle(); // Return early if we sound a match and shortCircuit is true if (!ret.isEmpty() && mShortCircuit) { return ret; } } // Finalize match, if necessary if (currentMatch != null && currentMatch.finalizeMatch() && node.isVisibleToUser()) { ret.add(AccessibilityNodeInfo.obtain(node)); } return ret; }
Example 19
Source File: QQClient.java From Anti-recall with GNU Affero General Public License v3.0 | 4 votes |
/** * 好友: * 姓名 last-3 android.widget.TextView * 消息 5-[]-last android.widget.TextView focusable * 文本框 7-0 android.widget.EditText * 发送按钮 7-1 android.widget.Button * <p> * 群: * 群名 1 * 消息 4/5- * <p> * 群里的临时会话: * 姓名 1-0 * 消息 6-[]-last * 文本框 8-0 * 发送按钮 8-1 */ protected boolean init(AccessibilityNodeInfo root) { if (root.getChildCount() < 10) { // 正常是13 // 有其他消息是14 // 非好友是10 Log.v(TAG, "init: root.childCount: " + root.getChildCount()); return false; } // List<AccessibilityNodeInfo> inputList; // List<AccessibilityNodeInfo> sendList; // inputList = root.findAccessibilityNodeInfosByViewId(IdInput); // sendList = root.findAccessibilityNodeInfosByViewId(IdSend); // if (inputList.size() == 0) { // Log.d(TAG, "init: input is null, return"); // return false; // } // if (sendList.size() == 0) { // Log.d(TAG, "init: send button is null, return"); // return false; // } // inputNode = inputList.get(0); // sendBtnNode = sendList.get(0); List<AccessibilityNodeInfo> titleList; titleList = root.findAccessibilityNodeInfosByViewId(IdTitle); if (titleList.size() == 0) { Log.d(TAG, "init: title is null, return"); return false; } titleNode = titleList.get(0); if (titleNode.getText() == null) { Log.d(TAG, "init: name is null,return"); return false; } title = titleNode.getText() + ""; chatGroupViewNode = root.getChild(0); if (chatGroupViewNode == null) { Log.d(TAG, "init: chatView node is null, return"); return false; } if (!IdChatGroupView.equals(chatGroupViewNode.getViewIdResourceName())) { Log.d(TAG, "init: not chat view, return"); return false; } isOtherMsg = IdOtherMsg.equals(root.getChild(1).getViewIdResourceName()); return true; }
Example 20
Source File: SaiyAccessibilityService.java From Saiy-PS with GNU Affero General Public License v3.0 | 4 votes |
/** * Recursively examine the {@link AccessibilityNodeInfo} object * * @param parent the {@link AccessibilityNodeInfo} parent object * @return the extracted text or null if no text was contained in the child objects */ private String examineChild(@Nullable final AccessibilityNodeInfo parent) { if (DEBUG) { MyLog.i(CLS_NAME, "examineChild"); } if (parent != null) { for (int i = 0; i < parent.getChildCount(); i++) { final AccessibilityNodeInfo nodeInfo = parent.getChild(i); if (nodeInfo != null) { if (DEBUG) { MyLog.i(CLS_NAME, "examineChild: nodeInfo: getClassName: " + nodeInfo.getClassName()); MyLog.i(CLS_NAME, "examineChild: nodeInfo: contentDesc: " + nodeInfo.getContentDescription()); } if (nodeInfo.getText() != null) { if (DEBUG) { MyLog.i(CLS_NAME, "examineChild: have text: returning: " + nodeInfo.getText().toString()); } return nodeInfo.getText().toString(); } else { if (DEBUG) { MyLog.i(CLS_NAME, "examineChild: text: null: recurse"); } final int childCount = nodeInfo.getChildCount(); if (DEBUG) { MyLog.i(CLS_NAME, "examineChild: childCount: " + childCount); } if (childCount > 0) { final String text = examineChild(nodeInfo); if (text != null) { if (DEBUG) { MyLog.i(CLS_NAME, "examineChild: have recursive text: returning: " + text); } return text; } else { if (DEBUG) { MyLog.i(CLS_NAME, "examineChild: recursive text: null"); } } } } } else { if (DEBUG) { MyLog.i(CLS_NAME, "examineChild: nodeInfo null"); } } } } else { if (DEBUG) { MyLog.i(CLS_NAME, "examineChild: parent null"); } } return null; }