android.view.accessibility.AccessibilityNodeInfo#recycle ( )源码实例Demo

下面列出了android.view.accessibility.AccessibilityNodeInfo#recycle ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。

源代码1 项目: brailleback   文件: TreeDebugNavigationMode.java
private AccessibilityNodeInfo getLastDescendantDfs(
    AccessibilityNodeInfo from) {
    AccessibilityNodeInfo lastChild = getLastChild(from);
    if (lastChild == null) {
        return null;
    }
    while (true) {
        AccessibilityNodeInfo lastGrandChild = getLastChild(lastChild);
        if (lastGrandChild != null) {
            lastChild.recycle();
            lastChild = lastGrandChild;
        } else {
            break;
        }
    }
    return lastChild;
}
 
源代码2 项目: talkback   文件: WindowManager.java
/** Gets the window whose anchor equals the given node. */
public @Nullable AccessibilityWindowInfo getAnchoredWindow(
    @Nullable AccessibilityNodeInfoCompat targetAnchor) {
  if (!BuildVersionUtils.isAtLeastN() || targetAnchor == null) {
    return null;
  }

  int windowCount = mWindows.size();
  for (int i = 0; i < windowCount; ++i) {
    AccessibilityWindowInfo window = mWindows.get(i);
    if (window != null) {
      AccessibilityNodeInfo anchor = window.getAnchor();
      if (anchor != null) {
        try {
          if (anchor.equals(targetAnchor.unwrap())) {
            return window;
          }
        } finally {
          anchor.recycle();
        }
      }
    }
  }

  return null;
}
 
源代码3 项目: RedEnvelopeAssistant   文件: WechatAccService.java
public void handleLuckyMoneyReceivePage(AccessibilityNodeInfo node) {
	if (node == null)
		return;
	LogUtil.d("handleLuckyMoneyReceivePage");
	AccessibilityNodeInfo nodeDetail = RedEnvelopeHelper.getWechatRedEnvelopeOpenDetailNode(node);
	LogUtil.d("nodeDetail="+nodeDetail);
	if (nodeDetail != null) {// the red envelope already opened
								// 红包已经被打开
		if (SettingHelper.getREAutoMode())
			ActivityHelper.goHome(this);
	} else {
		AccessibilityNodeInfo nodeOpen = RedEnvelopeHelper.getWechatRedEnvelopeOpenNode(node);
		LogUtil.d("nodeOpen="+nodeOpen);
		if (nodeOpen != null) {
			nodeOpen.performAction(AccessibilityNodeInfo.ACTION_CLICK);
			nodeOpen.recycle();
		} else {// this page is loading red envelope data, no action

		}
	}
}
 
源代码4 项目: oversec   文件: OversecAccessibilityService.java
public synchronized void performActionOnFocusedNode(PerformFocusedNodeAction action) {
    AccessibilityNodeInfo focusedNode = null;
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        focusedNode = findFocus(AccessibilityNodeInfo.FOCUS_INPUT);
    }
    //In case we're dealing with a webView, findFocus won't work and just remove the top frame,
    //so check if the focused node makes sense and if not, fall back to findFocus_PreLollipop
    if (focusedNode == null || !mTree.isAEditText(focusedNode)) {
        focusedNode = findFocus_PreLollipop();
    }
    if (focusedNode == null) {
        action.performActionWhenNothingFocused();
    } else {
        action.performAction(focusedNode);
        focusedNode.recycle();
    }
}
 
源代码5 项目: AutoInteraction-Library   文件: UiTree.java
public static AccessibilityNodeInfo getRootAccessibilityNodeInfo(@NonNull AccessibilityNodeInfo accessibilityNodeInfo) throws MyException {
    if (null == accessibilityNodeInfo) {
        throw new NullPointerException("accessibilityNodeInfo");
    }
    AccessibilityNodeInfo current = null;
    try {
        current = accessibilityNodeInfo;
        while (true) {
            AccessibilityNodeInfo parent = current.getParent();
            if (null == parent) {
                return current;
            }
            current = parent;
        }
    } catch (Exception e) {
        if (null != current) {
            current.recycle();
        }
        throw new MyException(e);
    }
}
 
源代码6 项目: oversec   文件: AccessibilityNodeInfoUtils.java
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;
}
 
源代码7 项目: oversec   文件: AccessibilityNodeInfoRef.java
/**
 * Traverses to the first child of this node if any, returning
 * {@code true} on success.
 */
public boolean firstChild() {
    if (mNode == null) {
        return false;
    }
    int childCount = mNode.getChildCount();
    for (int i = 0; i < childCount; ++i) {
        AccessibilityNodeInfo newNode = mNode.getChild(i);
        if (newNode == null) {
            return false;
        }
        if (AccessibilityNodeInfoUtils.isVisibleOrLegacy(newNode)) {
            reset(newNode);
            return true;
        }
        newNode.recycle();
    }
    return false;
}
 
源代码8 项目: brailleback   文件: TreeDebugNavigationMode.java
private AccessibilityNodeInfo getNextSibling(
    AccessibilityNodeInfo from) {
    AccessibilityNodeInfo parent = from.getParent();
    if (parent == null) {
        return null;
    }
    AccessibilityNodeInfo cur = null;
    try {
        int childCount = parent.getChildCount();
        for (int i = 0; i < childCount - 1; ++i) {
            cur = parent.getChild(i);
            if (cur == null) {
                return null;
            }
            if (cur.equals(from)) {
                return parent.getChild(i + 1);
            }
            if (cur != null) {
                cur.recycle();
                cur = null;
            }
        }
    } finally {
        parent.recycle();
        if (cur != null) {
            cur.recycle();
        }
    }
    return null;
}
 
源代码9 项目: talkback   文件: EventFilter.java
private boolean isValidScrollEvent(AccessibilityEvent event) {
  AccessibilityNodeInfo source = event.getSource();
  if (source == null) {
    return true; // Cannot check source validity, so assume that it's scrollable.
  }

  boolean valid =
      source.isScrollable() || event.getMaxScrollX() != -1 || event.getMaxScrollY() != -1;
  source.recycle();
  return valid;
}
 
源代码10 项目: talkback   文件: FocusFinder.java
public static @Nullable AccessibilityNodeInfoCompat getFocusedNode(
    AccessibilityService service, boolean fallbackOnRoot) {
  AccessibilityNodeInfo root = service.getRootInActiveWindow();
  AccessibilityNodeInfo focused = null;

  try {
    AccessibilityNodeInfo ret = null;
    if (root != null) {
      focused = root.findFocus(AccessibilityNodeInfo.FOCUS_ACCESSIBILITY);
      if (focused != null && focused.isVisibleToUser()) {
        ret = focused;
        focused = null;
      } else if (fallbackOnRoot) {
        ret = root;
        root = null;
      }
    } else {
      LogUtils.e(TAG, "No current window root");
    }

    if (ret != null) {
      return AccessibilityNodeInfoUtils.toCompat(ret);
    }
  } finally {
    if (root != null) {
      root.recycle();
    }

    if (focused != null) {
      focused.recycle();
    }
  }

  return null;
}
 
源代码11 项目: oversec   文件: OversecAccessibilityService.java
private void scrapeCompleteSubtree_MAIN(Tree.TreeNode treeNode, AccessibilityNodeInfo node, PerformNodeAction nodeAction) {
    checkHandlerThread();

    node.refresh();

    checkFocusedNode_PreLollipop(node);

    if (!node.isVisibleToUser()) {
        return;
    }

    int cc = node.getChildCount();

    for (int i = 0; i < cc; i++) {
        AccessibilityNodeInfo child = node.getChild(i);


        if (child != null) {
            Tree.TreeNode childTreeNode = mTree.put(child);
            treeNode.addChild(childTreeNode);
            if (nodeAction != null) {
                nodeAction.onNodeScanned(child);
            }
            scrapeCompleteSubtree_MAIN(childTreeNode, child, nodeAction);
            child.recycle();
        } else {
            Ln.d("SKRAPE: warning, couldn't get a child!");
            //TODO: one reason for this might be a too large binder transaction -> maybe at least give some feedback to the user
        }
    }

}
 
源代码12 项目: LaunchEnr   文件: CustomActionsPopup.java
private List<AccessibilityAction> getActionList() {
    if (mIcon == null || !(mIcon.getTag() instanceof ItemInfo)) {
        return Collections.EMPTY_LIST;
    }

    AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain();
    mDelegate.addSupportedActions(mIcon, info, true);
    List<AccessibilityAction> result = new ArrayList<>(info.getActionList());
    info.recycle();
    return result;
}
 
源代码13 项目: talkback   文件: AccessibilityNode.java
private final void recycle(AccessibilityNodeInfo node, String caller) {
  try {
    node.recycle();
  } catch (IllegalStateException e) {
    logOrThrow(
        e,
        "Caught IllegalStateException from accessibility framework with %s trying to recycle"
            + " node %s",
        caller,
        node);
  }
}
 
源代码14 项目: brailleback   文件: CustomLabelManager.java
/**
 * Creates a {@link Label} and persists it to the label database, and
 * refreshes the label cache.
 * <p>
 * NOTE: This method will not attempt to recycle {@code node}.
 *
 * @param node The node to label
 * @param userLabel The label provided for the node by the user
 */
public void addLabel(AccessibilityNodeInfo node, String userLabel) {
    if (node == null) {
        throw new IllegalArgumentException("Attempted to add a label for a null node.");
    }

    final AccessibilityNodeInfo internalNodeCopy = AccessibilityNodeInfo.obtain(node);
    addLabel(internalNodeCopy.getViewIdResourceName(), userLabel);
    internalNodeCopy.recycle();
}
 
源代码15 项目: oversec   文件: AccessibilityNodeInfoRef.java
/**
 * Traverses to the previous sibling of this node within its parent,
 * returning {@code true} on success.
 */
public boolean previousSibling() {
    if (mNode == null) {
        return false;
    }
    AccessibilityNodeInfo parent = mNode.getParent();
    if (parent == null) {
        return false;
    }
    try {
        int childNumber = getChildNumber(parent);
        for (int i = childNumber - 1; i >= 0; --i) {
            AccessibilityNodeInfo newNode = parent.getChild(i);
            if (newNode == null) {
                return false;
            }
            if (AccessibilityNodeInfoUtils.isVisibleOrLegacy(newNode)) {
                reset(newNode);
                return true;
            }
            newNode.recycle();
        }
    } finally {
        parent.recycle();
    }
    return false;
}
 
源代码16 项目: oversec   文件: AccessibilityNodeInfoRef.java
/**
 * Traverses to the next sibling of this node within its parent, returning
 * {@code true} on success.
 */
public boolean nextSibling() {
    if (mNode == null) {
        return false;
    }
    AccessibilityNodeInfo parent = mNode.getParent();
    if (parent == null) {
        return false;
    }
    try {
        int childCount = parent.getChildCount();
        int childNumber = getChildNumber(parent);
        if (childNumber < 0) {
            return false;
        }
        for (int i = childNumber + 1; i < childCount; ++i) {
            AccessibilityNodeInfo newNode =
                    parent.getChild(i);
            if (newNode == null) {
                return false;
            }
            if (AccessibilityNodeInfoUtils.isVisibleOrLegacy(newNode)) {
                reset(newNode);
                return true;
            }
            newNode.recycle();
        }
    } finally {
        parent.recycle();
    }
    return false;
}
 
private WindowHierarchyElementAndroid construct(
    int id,
    @Nullable WindowHierarchyElementAndroid parent,
    AccessibilityWindowInfo fromWindow,
    Map<ViewHierarchyElementAndroid, AccessibilityNodeInfo> elementToNodeInfoMap) {
  // Bookkeeping
  this.parentId = (parent != null) ? parent.getId() : null;

  // Window properties
  this.windowId = fromWindow.getId();
  this.layer = fromWindow.getLayer();
  this.type = fromWindow.getType();
  this.focused = fromWindow.isFocused();
  this.accessibilityFocused = fromWindow.isAccessibilityFocused();
  this.active = fromWindow.isActive();

  android.graphics.Rect tempRect = new android.graphics.Rect();
  fromWindow.getBoundsInScreen(tempRect);
  this.boundsInScreen = new Rect(tempRect.left, tempRect.top, tempRect.right, tempRect.bottom);

  // Build the window's view hierarchy
  AccessibilityNodeInfo rootInfo = fromWindow.getRoot();
  this.viewHierarchyElements = new ArrayList<>(); // The ultimate size is unknown
  if (rootInfo != null) {
    buildViewHierarchy(
        rootInfo, viewHierarchyElements, null /* no parent */, elementToNodeInfoMap);
    rootInfo.recycle();
  } else {
    // This could occur in the case where the application state changes between the time that
    // the AccessibilityWindowInfo object is obtained and when its root AccessibilityNodeInfo is
    // extracted.
    LogUtils.w(TAG, "Constructed WindowHierarchyElement with no valid root.");
  }
  return new WindowHierarchyElementAndroid(
      id,
      parentId,
      childIds,
      windowId,
      layer,
      type,
      focused,
      accessibilityFocused,
      active,
      boundsInScreen,
      viewHierarchyElements);
}
 
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");
}
 
源代码19 项目: oversec   文件: OversecAccessibilityService.java
private void handleScrapeAll_MAIN(String reason, PerformNodeAction nodeAction) {
        checkHandlerThread();

        mTree.clear();
        AccessibilityNodeInfo rootNode = null;
        try {
            rootNode = getRootInActiveWindow();
        } catch (Exception ex) {
            Ln.e(ex);
            return;
        }
        try {
            if (rootNode != null) {

                //fail-fast if this is not a package we're interested in
                CharSequence csPackageName = rootNode.getPackageName();
                if (csPackageName == null) return;
                String aPackageName = rootNode.getPackageName().toString();
                boolean ours = mCore.getDb().isShowDecryptOverlay(aPackageName);
                if (!ours) {
                    mCore.onAcsScrapeCompleted(aPackageName, null);
                    return;
                }

                findFocusedNodePreLollipop_startTransaction();
                if (LoggingConfig.INSTANCE.getLOG()) {
                    Ln.d("SKRAPE: FULL SCAN, root=%s", rootNode.hashCode());
                }

                mTree.addRootNode(rootNode);

                scrapeSubtree_MAIN(rootNode, "handleScrapeAll_MAIN-> " + reason, nodeAction);

                rootNode.recycle();

                findFocusedNodePreLollipop_commitTransaction();

                publishChanges_MAIN();


            } else {
                Ln.w("SKRAPE: getRootInActiveWindow returned null node!");
                clearFocusedNode_PreLollipop();
                //TODO: one reason for this might be a too large binder transaction -> maybe at least give some feedback to the user
                //TODO: or somehow scrape sub-nodes first in order to have separate smalle transactions?#
//            How to Prevent MAX binder transaction / max parcel overflow, Could happen when getting a list node with many immediate GPG text views (the listnode prefetches its children, and if all of them have a long pgp encoded text, this may just be too much for a single binder transaction)
//            size is 1 mb, let's say 50 nodes gives 20 k per node,   worst case every character is encoded with 4 bytes gives 5 k text!!!  -> might just be enough for pgp
//                    >hmmm, prefetching descendants works recursively, but will always fetch max. 50 nodes,
//            -> hopefully not needed but there's noreal way around it!other than using reflection to get the child node's IDs and then manually doing refresh

            }

        } finally {
            if (nodeAction != null) {
                nodeAction.onScrapeComplete();
            }
        }

    }
 
源代码20 项目: JsDroidCmd   文件: ByMatcher.java
/**
 * 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;
}