diff --git a/app/src/main/java/com/stardust/scriptdroid/ui/codegeneration/CodeGenerateDialog.java b/app/src/main/java/com/stardust/scriptdroid/ui/codegeneration/CodeGenerateDialog.java
index 9028fc3d..edc9df42 100644
--- a/app/src/main/java/com/stardust/scriptdroid/ui/codegeneration/CodeGenerateDialog.java
+++ b/app/src/main/java/com/stardust/scriptdroid/ui/codegeneration/CodeGenerateDialog.java
@@ -16,7 +16,8 @@ import com.bignerdranch.expandablerecyclerview.ChildViewHolder;
import com.bignerdranch.expandablerecyclerview.ExpandableRecyclerAdapter;
import com.bignerdranch.expandablerecyclerview.ParentViewHolder;
import com.bignerdranch.expandablerecyclerview.model.Parent;
-import com.stardust.autojs.codegeneration.UiSelectorGenerator;
+import com.stardust.app.DialogUtils;
+import com.stardust.autojs.codegeneration.CodeGenerator;
import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.ui.widget.CheckBoxCompat;
import com.stardust.theme.dialog.ThemeColorMaterialDialogBuilder;
@@ -66,39 +67,39 @@ public class CodeGenerateDialog extends ThemeColorMaterialDialogBuilder {
super(context);
mRootNode = rootNode;
mTargetNode = targetNode;
- positiveText(R.string.text_generate_and_copy);
- neutralText(R.string.text_generate_and_open_editor);
- onPositive(((dialog, which) -> generateCodeAndCopy()));
- onNeutral(((dialog, which) -> generateCodeAndOpenEditor()));
+ positiveText(R.string.text_generate);
+ negativeText(R.string.text_cancel);
+ onPositive(((dialog, which) -> generateCodeAndShow()));
setupViews();
}
- private void generateCodeAndCopy() {
+ private void generateCodeAndShow() {
String code = generateCode();
if (code == null) {
Toast.makeText(getContext(), R.string.text_generate_fail, Toast.LENGTH_SHORT).show();
return;
}
- ClipboardUtil.setClip(getContext(), code);
- Toast.makeText(getContext(), R.string.text_already_copy_to_clip, Toast.LENGTH_SHORT).show();
+ DialogUtils.showDialog(new ThemeColorMaterialDialogBuilder(getContext())
+ .title(R.string.text_generated_code)
+ .content(code)
+ .positiveText(R.string.text_copy)
+ .onPositive(((dialog, which) -> ClipboardUtil.setClip(getContext(), code)))
+ .build());
}
- private void generateCodeAndOpenEditor() {
-
- }
private String generateCode() {
- UiSelectorGenerator generator = new UiSelectorGenerator(mRootNode, mTargetNode);
+ CodeGenerator generator = new CodeGenerator(mRootNode, mTargetNode);
OptionGroup settings = getOptionGroup(R.string.text_options);
generator.setUsingId(settings.getOption(R.string.text_using_id_selector).checked);
generator.setUsingText(settings.getOption(R.string.text_using_text_selector).checked);
generator.setUsingDesc(settings.getOption(R.string.text_using_desc_selector).checked);
generator.setSearchMode(getSearchMode());
setAction(generator);
- return generator.generate();
+ return generator.generateCode();
}
- private void setAction(UiSelectorGenerator generator) {
+ private void setAction(CodeGenerator generator) {
OptionGroup action = getOptionGroup(R.string.text_action);
if (action.getOption(R.string.text_click).checked) {
generator.setAction(AccessibilityNodeInfoCompat.ACTION_CLICK);
@@ -117,18 +118,18 @@ public class CodeGenerateDialog extends ThemeColorMaterialDialogBuilder {
private int getSearchMode() {
OptionGroup selectMode = getOptionGroup(R.string.text_select);
if (selectMode.getOption(R.string.text_find_one).checked) {
- return UiSelectorGenerator.FIND_ONE;
+ return CodeGenerator.FIND_ONE;
}
if (selectMode.getOption(R.string.text_until_find).checked) {
- return UiSelectorGenerator.UNTIL_FIND;
+ return CodeGenerator.UNTIL_FIND;
}
if (selectMode.getOption(R.string.text_wait_for).checked) {
- return UiSelectorGenerator.WAIT_FOR;
+ return CodeGenerator.WAIT_FOR;
}
if (selectMode.getOption(R.string.text_wait_for).checked) {
- return UiSelectorGenerator.EXISTS;
+ return CodeGenerator.EXISTS;
}
- return UiSelectorGenerator.FIND_ONE;
+ return CodeGenerator.FIND_ONE;
}
private void setupViews() {
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 0eafa6cb..4834a95f 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -299,7 +299,7 @@
使用id选择
使用文本选择(text)
使用描述选择(desc)
- 生成并复制
+ 生成
生成并打开编辑器
生成失败了o(╥﹏╥)o
key_documentation_source
@@ -326,4 +326,6 @@
打包插件不可用
详情
打开
+ 生成结果
+ 复制
diff --git a/autojs/src/main/java/com/stardust/autojs/codegeneration/CodeGenerator.java b/autojs/src/main/java/com/stardust/autojs/codegeneration/CodeGenerator.java
new file mode 100644
index 00000000..32379af5
--- /dev/null
+++ b/autojs/src/main/java/com/stardust/autojs/codegeneration/CodeGenerator.java
@@ -0,0 +1,193 @@
+package com.stardust.autojs.codegeneration;
+
+import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
+
+import com.stardust.automator.UiGlobalSelector;
+import com.stardust.automator.UiObject;
+import com.stardust.view.accessibility.NodeInfo;
+
+/**
+ * Created by Stardust on 2017/12/7.
+ */
+
+public class CodeGenerator {
+
+ public static final int UNTIL_FIND = 0;
+ public static final int FIND_ONE = 1;
+ public static final int WAIT_FOR = 2;
+ public static final int EXISTS = 3;
+
+ private ReadOnlyUiObject mRoot;
+ private ReadOnlyUiObject mTarget;
+ private boolean mUsingId = true;
+ private boolean mUsingDesc = true;
+ private boolean mUsingText = true;
+ private int mSearchMode = FIND_ONE;
+ private int mAction = -1;
+
+ public CodeGenerator(NodeInfo root, NodeInfo target) {
+ this(new ReadOnlyUiObject(root), new ReadOnlyUiObject(target));
+ }
+
+ public CodeGenerator(ReadOnlyUiObject root, ReadOnlyUiObject target) {
+ mRoot = root;
+ mTarget = target;
+ }
+
+
+ public void setUsingId(boolean usingId) {
+ mUsingId = usingId;
+ }
+
+ public void setUsingDesc(boolean usingDesc) {
+ mUsingDesc = usingDesc;
+ }
+
+ public void setUsingText(boolean usingText) {
+ mUsingText = usingText;
+ }
+
+ public void setSearchMode(int searchMode) {
+ mSearchMode = searchMode;
+ }
+
+ public void setAction(int action) {
+ mAction = action;
+ }
+
+ public String generateCode() {
+ UiObject collection = getCollectionParent(mTarget);
+ if (collection != null) {
+ return generateCodeForCollectionChild(collection, mTarget);
+ }
+
+ UiSelectorGenerator generator = new UiSelectorGenerator(mRoot, mTarget);
+ generator.setSearchMode(mSearchMode);
+ generator.setUsingDesc(mUsingDesc);
+ generator.setUsingId(mUsingId);
+ generator.setUsingText(mUsingText);
+ String selector = generateCode(generator, mRoot, mTarget, 2, 2);
+ if (selector == null)
+ return null;
+ return generateAction(selector);
+ }
+
+ protected String generateCode(UiSelectorGenerator generator, UiObject root, UiObject target, int maxParentLevel, int maxChildrenLevel) {
+ String selector = generator.generateSelectorCode();
+ if (selector != null) {
+ return selector;
+ }
+ if (maxChildrenLevel > 0) {
+ for (int i = 0; i < target.childCount(); i++) {
+ UiObject child = target.child(i);
+ if (child == null)
+ continue;
+ String childCode = generateCode(root, child, 0, maxChildrenLevel - 1);
+ if (childCode != null) {
+ return childCode + ".parent()";
+ }
+ }
+ }
+ if (maxParentLevel > 0 && target.parent() != null) {
+ int index = target.indexInParent();
+ if (index > 0) {
+ String parentCode = generateCode(root, target.parent(), maxParentLevel - 1, 0);
+ if (parentCode != null) {
+ return parentCode + "child(" + index + ")";
+ }
+ }
+ }
+ return null;
+ }
+
+ protected String generateCode(UiObject root, UiObject target, int maxParentLevel, int maxChildrenLevel) {
+ UiSelectorGenerator generator = new UiSelectorGenerator(root, target);
+ generator.setUsingId(mUsingId);
+ return generateCode(generator, root, target, maxParentLevel, maxChildrenLevel);
+ }
+
+ private String generateAction(String selector) {
+ if (selector == null)
+ return null;
+ if (mSearchMode == WAIT_FOR) {
+ return selector + ".waitFor()";
+ }
+ if (mSearchMode == EXISTS) {
+ return "if(" + selector + ".exists()){\n \n}";
+ }
+ String action = getAction();
+ if (action.isEmpty()) {
+ return selector;
+ } else {
+ return selector + "." + action;
+ }
+ }
+
+ private String getAction() {
+ switch (mAction) {
+ case AccessibilityNodeInfoCompat.ACTION_CLICK:
+ return "click()";
+ case AccessibilityNodeInfoCompat.ACTION_LONG_CLICK:
+ return "longClick()";
+
+ case AccessibilityNodeInfoCompat.ACTION_SCROLL_BACKWARD:
+ return "scrollBackward()";
+
+ case AccessibilityNodeInfoCompat.ACTION_SCROLL_FORWARD:
+ return "scrollForward()";
+
+ case AccessibilityNodeInfoCompat.ACTION_SET_TEXT:
+ return "setText(\"\")";
+ }
+ return "";
+ }
+
+ private String generateCodeForCollectionChild(UiObject collection, UiObject target) {
+ UiObject parent = target.parent();
+ if (parent == null)
+ return null;
+ UiObject collectionItem = null;
+ for (int i = 0; i < collection.childCount(); i++) {
+ if (inherits(collection.child(i), target)) {
+ collectionItem = collection.child(i);
+ break;
+ }
+ }
+ if (collectionItem == null)
+ return null;
+ String collectionCode = generateCode(mRoot, collection, 2, 0);
+ if (collectionCode == null)
+ return null;
+ String itemCode = generateCode(collectionItem, target, 1, 2);
+ if (itemCode == null)
+ return null;
+ return collectionCode + ".findOne().children().forEach(child => {\n"
+ + "var target = child.findOne(" + itemCode + ");\n"
+ + "target." + getAction() + ";\n"
+ + "});";
+ }
+
+ private boolean inherits(UiObject root, UiObject target) {
+ for (int i = 0; i < root.childCount(); i++) {
+ UiObject child = root.child(i);
+ if (child != null) {
+ if (child.equals(target) || inherits(child, target)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private UiObject getCollectionParent(UiObject target) {
+ UiObject parent = target.parent();
+ while (parent != null) {
+ if (parent.rowCount() > 0 || parent.columnCount() > 0) {
+ return parent;
+ }
+ parent = parent.parent();
+ }
+ return null;
+ }
+
+}
diff --git a/autojs/src/main/java/com/stardust/autojs/codegeneration/ReadOnlyUiObject.java b/autojs/src/main/java/com/stardust/autojs/codegeneration/ReadOnlyUiObject.java
index 119860f8..c2fb2758 100644
--- a/autojs/src/main/java/com/stardust/autojs/codegeneration/ReadOnlyUiObject.java
+++ b/autojs/src/main/java/com/stardust/autojs/codegeneration/ReadOnlyUiObject.java
@@ -6,7 +6,6 @@ import android.support.annotation.Nullable;
import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
import com.stardust.automator.UiObject;
-import com.stardust.automator.UiObjectCollection;
import com.stardust.view.accessibility.NodeInfo;
/**
@@ -16,19 +15,27 @@ import com.stardust.view.accessibility.NodeInfo;
public class ReadOnlyUiObject extends UiObject {
private NodeInfo mNodeInfo;
- private boolean mUsingId;
- private boolean mUsingText;
- private boolean mUsingDesc;
public ReadOnlyUiObject(NodeInfo info) {
- super(info, info.depth);
+ super(info, info.depth, -1);
+ mNodeInfo = info;
+ }
+
+ public ReadOnlyUiObject(NodeInfo info, int indexInParent) {
+ super(info, info.depth, indexInParent);
mNodeInfo = info;
}
@Nullable
@Override
public UiObject child(int i) {
- return new ReadOnlyUiObject(mNodeInfo.getChildren().get(i));
+ return new ReadOnlyUiObject(mNodeInfo.getChildren().get(i), i);
+ }
+
+ @Nullable
+ @Override
+ public UiObject parent() {
+ return mNodeInfo.parent == null ? null : new ReadOnlyUiObject(mNodeInfo.parent);
}
@Override
@@ -189,6 +196,82 @@ public class ReadOnlyUiObject extends UiObject {
return mNodeInfo.scrollable;
}
+ @Override
+ public boolean isCheckable() {
+ return checkable();
+ }
+
+ @Override
+ public boolean isChecked() {
+ return checked();
+ }
+
+ @Override
+ public boolean isFocusable() {
+ return focusable();
+ }
+
+ @Override
+ public boolean isFocused() {
+ return focused();
+ }
+
+ @Override
+ public boolean isVisibleToUser() {
+ return visibleToUser();
+ }
+
+ @Override
+ public boolean isAccessibilityFocused() {
+ return accessibilityFocused();
+ }
+
+ @Override
+ public boolean isSelected() {
+ return selected();
+ }
+
+ @Override
+ public boolean isClickable() {
+ return clickable();
+ }
+
+ @Override
+ public boolean isLongClickable() {
+ return longClickable();
+ }
+
+ @Override
+ public boolean isEnabled() {
+ return enabled();
+ }
+
+ @Override
+ public boolean isPassword() {
+ return password();
+ }
+
+ @Override
+ public boolean isScrollable() {
+ return scrollable();
+ }
+
+
+ @Override
+ public boolean isContextClickable() {
+ return mNodeInfo.contextClickable;
+ }
+
+ @Override
+ public boolean isDismissable() {
+ return mNodeInfo.dismissable;
+ }
+
+ @Override
+ public boolean isEditable() {
+ return mNodeInfo.editable;
+ }
+
@Override
public int row() {
return mNodeInfo.row;
@@ -223,4 +306,27 @@ public class ReadOnlyUiObject extends UiObject {
public void recycle() {
}
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ if (!super.equals(o)) return false;
+
+ ReadOnlyUiObject that = (ReadOnlyUiObject) o;
+
+ return mNodeInfo.equals(that.mNodeInfo);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = super.hashCode();
+ result = 31 * result + mNodeInfo.hashCode();
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return mNodeInfo.toString();
+ }
}
diff --git a/autojs/src/main/java/com/stardust/autojs/codegeneration/UiSelectorGenerator.java b/autojs/src/main/java/com/stardust/autojs/codegeneration/UiSelectorGenerator.java
index 2161ceca..89f257ed 100644
--- a/autojs/src/main/java/com/stardust/autojs/codegeneration/UiSelectorGenerator.java
+++ b/autojs/src/main/java/com/stardust/autojs/codegeneration/UiSelectorGenerator.java
@@ -1,49 +1,81 @@
package com.stardust.autojs.codegeneration;
-import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
-
import com.stardust.automator.UiGlobalSelector;
+import com.stardust.automator.UiObject;
import com.stardust.util.Consumer;
-import com.stardust.view.accessibility.NodeInfo;
+
+import static com.stardust.autojs.codegeneration.CodeGenerator.FIND_ONE;
+import static com.stardust.autojs.codegeneration.CodeGenerator.UNTIL_FIND;
/**
- * Created by Stardust on 2017/8/4.
+ * Created by Stardust on 2017/12/7.
*/
public class UiSelectorGenerator {
-
- public static final int UNTIL_FIND = 0;
- public static final int FIND_ONE = 1;
- public static final int WAIT_FOR = 2;
- public static final int EXISTS = 3;
-
- private ReadOnlyUiObject mRoot;
- private ReadOnlyUiObject mTarget;
+ private UiObject mRoot;
+ private UiObject mTarget;
private boolean mUsingId = true;
private boolean mUsingDesc = true;
private boolean mUsingText = true;
- private UiGlobalSelector mUiGlobalSelector;
private int mSearchMode = FIND_ONE;
- private int mAction = -1;
- public UiSelectorGenerator(NodeInfo root, NodeInfo target) {
- this(new ReadOnlyUiObject(root), new ReadOnlyUiObject(target));
- }
-
- public UiSelectorGenerator(ReadOnlyUiObject root, ReadOnlyUiObject target) {
+ public UiSelectorGenerator(UiObject root, UiObject target) {
mRoot = root;
mTarget = target;
}
- public void setSearchMode(int searchMode) {
- mSearchMode = searchMode;
+ public UiGlobalSelector generateSelector() {
+ UiGlobalSelector selector = new UiGlobalSelector();
+ if (mUsingId &&
+ tryWithStringCondition(selector, mTarget.id(), selector::id)) {
+ return selector;
+ }
+
+ if (tryWithStringCondition(selector, mTarget.className(), selector::className)) {
+ return selector;
+ }
+ if (mUsingText &&
+ tryWithStringCondition(selector, mTarget.text(), selector::text)) {
+ return selector;
+ }
+ if (mUsingDesc &&
+ tryWithStringCondition(selector, mTarget.desc(), selector::desc)) {
+ return selector;
+ }
+ if (mTarget.scrollable() && tryWithBooleanCondition(selector, mTarget.scrollable(), selector::scrollable)) {
+ return selector;
+ }
+ if (mTarget.clickable() && tryWithBooleanCondition(selector, mTarget.clickable(), selector::clickable)) {
+ return selector;
+ }
+ if (mTarget.selected() && tryWithBooleanCondition(selector, mTarget.selected(), selector::selected)) {
+ return selector;
+ }
+ if (mTarget.checkable() && tryWithBooleanCondition(selector, mTarget.checkable(), selector::checkable)) {
+ return selector;
+ }
+ if (mTarget.checked() && tryWithBooleanCondition(selector, mTarget.checked(), selector::checked)) {
+ return selector;
+ }
+ if (mTarget.longClickable() && tryWithBooleanCondition(selector, mTarget.longClickable(), selector::longClickable)) {
+ return selector;
+ }
+ if (tryWithIntCondition(selector, mTarget.depth(), selector::depth)) {
+ return selector;
+ }
+ return null;
}
- public void setAction(int action) {
- mAction = action;
+ public String generateSelectorCode() {
+ UiGlobalSelector selector = generateSelector();
+ if (selector == null) {
+ return null;
+ }
+ return selector + (mSearchMode == FIND_ONE ? ".findOne()" : ".untilFind()");
}
+
public void setUsingId(boolean usingId) {
mUsingId = usingId;
}
@@ -56,94 +88,37 @@ public class UiSelectorGenerator {
mUsingText = usingText;
}
+ public void setSearchMode(int searchMode) {
+ mSearchMode = searchMode;
+ }
- private boolean tryWithStringCondition(String name, String value, Consumer condition, StringBuilder code) {
- if (value == null || value.isEmpty())
+ private boolean tryWithBooleanCondition(UiGlobalSelector selector, boolean value, Consumer condition) {
+ condition.accept(value);
+ return shouldStopGeneration(selector);
+ }
+
+
+ private boolean tryWithStringCondition(UiGlobalSelector selector, String value, Consumer condition) {
+ if (value == null || value.isEmpty()) {
return false;
- code.append('.').append(name).append("(\"").append(value).append("\")");
+ }
condition.accept(value);
- return isConditionEnough();
+ return shouldStopGeneration(selector);
}
- private boolean tryWithIntCondition(String name, int value, Consumer condition, StringBuilder code) {
- code.append('.').append(name).append('(').append(value).append(')');
- condition.accept(value);
- return isConditionEnough();
- }
-
- private boolean isConditionEnough() {
+ private boolean shouldStopGeneration(UiGlobalSelector selector) {
if (mSearchMode == UNTIL_FIND) {
- return !mUiGlobalSelector.findAndReturnList(mRoot).isEmpty();
+ return !selector.findAndReturnList(mRoot).isEmpty();
} else {
- return mUiGlobalSelector.findAndReturnList(mRoot).size() == 1;
+ return selector.findAndReturnList(mRoot).size() == 1;
}
}
- public String generate() {
- String selector = generateSelector();
- if (selector == null) {
- return null;
- }
- //remove '.'
- selector = selector.substring(1);
- if (mSearchMode == WAIT_FOR) {
- return selector + ".waitFor()";
- }
- if (mSearchMode == EXISTS) {
- return "if(" + selector + ".exists()){\n \n}";
- }
- String action = getAction();
- if (action == null) {
- return selector;
- } else {
- return selector + action;
- }
-
+ private boolean tryWithIntCondition(UiGlobalSelector selector, int value, Consumer condition) {
+ condition.accept(value);
+ return shouldStopGeneration(selector);
}
- private String getAction() {
- switch (mAction) {
- case AccessibilityNodeInfoCompat.ACTION_CLICK:
- return ".click()";
- case AccessibilityNodeInfoCompat.ACTION_LONG_CLICK:
- return ".longClick()";
- case AccessibilityNodeInfoCompat.ACTION_SCROLL_BACKWARD:
- return ".scrollBackward()";
-
- case AccessibilityNodeInfoCompat.ACTION_SCROLL_FORWARD:
- return ".scrollForward()";
-
- case AccessibilityNodeInfoCompat.ACTION_SET_TEXT:
- return ".setText(\"\")";
- }
- return null;
- }
-
- private String generateSelector() {
- mUiGlobalSelector = new UiGlobalSelector();
- StringBuilder code = new StringBuilder();
- if (mUsingId &&
- tryWithStringCondition("id", mTarget.id(), mUiGlobalSelector::id, code)) {
- return code.toString();
- }
- if (tryWithIntCondition("depth", mTarget.depth(), mUiGlobalSelector::depth, code)) {
- return code.toString();
- }
- if (tryWithStringCondition("className", mTarget.className(), mUiGlobalSelector::className, code)) {
- return code.toString();
- }
-
- if (mUsingText &&
- tryWithStringCondition("text", mTarget.text(), mUiGlobalSelector::text, code)) {
- return code.toString();
- }
-
- if (mUsingDesc &&
- tryWithStringCondition("desc", mTarget.desc(), mUiGlobalSelector::desc, code)) {
- return code.toString();
- }
- return null;
- }
}
diff --git a/automator/src/main/java/com/stardust/automator/UiGlobalSelector.java b/automator/src/main/java/com/stardust/automator/UiGlobalSelector.java
index e2b3c865..e792acab 100644
--- a/automator/src/main/java/com/stardust/automator/UiGlobalSelector.java
+++ b/automator/src/main/java/com/stardust/automator/UiGlobalSelector.java
@@ -178,6 +178,11 @@ public class UiGlobalSelector {
protected boolean isIncluded(UiObject nodeInfo) {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && nodeInfo.getDrawingOrder() == order;
}
+
+ @Override
+ public String toString() {
+ return "drawingOrder(" + order + ")";
+ }
});
return this;
}
@@ -430,5 +435,13 @@ public class UiGlobalSelector {
return this;
}
-
+ @Override
+ public String toString() {
+ StringBuilder str = new StringBuilder();
+ for (ListFilter filter : mFilters) {
+ str.append(filter.toString()).append(".");
+ }
+ str.deleteCharAt(str.length() - 1);
+ return str.toString();
+ }
}
diff --git a/automator/src/main/java/com/stardust/automator/UiObject.java b/automator/src/main/java/com/stardust/automator/UiObject.java
index a8bcff33..2e107b66 100644
--- a/automator/src/main/java/com/stardust/automator/UiObject.java
+++ b/automator/src/main/java/com/stardust/automator/UiObject.java
@@ -37,37 +37,39 @@ public class UiObject extends AccessibilityNodeInfoCompat {
public static UiObject createRoot(AccessibilityNodeInfo root) {
- return new UiObject(root, null, 0);
+ return new UiObject(root, null, 0, -1);
}
public static UiObject createRoot(AccessibilityNodeInfo root, AccessibilityNodeInfoAllocator allocator) {
- return new UiObject(root, allocator, 0);
+ return new UiObject(root, allocator, 0, -1);
}
private AccessibilityNodeInfoAllocator mAllocator = null;
private String mStackTrace = "";
private int mDepth = 0;
+ private final int mIndexInParent;
public UiObject(Object info) {
- this(info, 0);
+ this(info, 0, -1);
}
- public UiObject(Object info, AccessibilityNodeInfoAllocator allocator, int depth) {
+ public UiObject(Object info, AccessibilityNodeInfoAllocator allocator, int depth, int indexInParent) {
super(info);
mDepth = depth;
mAllocator = allocator;
+ mIndexInParent = indexInParent;
if (DEBUG)
mStackTrace = Arrays.toString(Thread.currentThread().getStackTrace());
}
- public UiObject(Object info, AccessibilityNodeInfoAllocator allocator) {
- this(info, allocator, 0);
+ public UiObject(Object info, AccessibilityNodeInfoAllocator allocator, int indexInParent) {
+ this(info, allocator, 0, indexInParent);
}
- public UiObject(Object info, int depth) {
- this(info, null, depth);
+ public UiObject(Object info, int depth, int indexInParent) {
+ this(info, null, depth, indexInParent);
}
@Nullable
@@ -76,7 +78,7 @@ public class UiObject extends AccessibilityNodeInfoCompat {
AccessibilityNodeInfoCompat parent = super.getParent();
if (parent == null)
return null;
- return new UiObject(parent.getInfo(), mDepth - 1);
+ return new UiObject(parent.getInfo(), mDepth - 1, -1);
} catch (IllegalStateException e) {
// FIXME: 2017/5/5
return null;
@@ -89,13 +91,17 @@ public class UiObject extends AccessibilityNodeInfoCompat {
AccessibilityNodeInfoCompat child = super.getChild(i);
if (child == null)
return null;
- return new UiObject(child.getInfo(), mDepth + 1);
+ return new UiObject(child.getInfo(), mDepth + 1, i);
} catch (IllegalStateException e) {
// FIXME: 2017/5/5
return null;
}
}
+ public int indexInParent() {
+ return mIndexInParent;
+ }
+
public UiObjectCollection find(UiGlobalSelector selector) {
return selector.findOf(this);
}
@@ -105,11 +111,11 @@ public class UiObject extends AccessibilityNodeInfoCompat {
}
public UiObjectCollection children() {
- ArrayList list = new ArrayList<>(getChildCount());
+ ArrayList list = new ArrayList<>(getChildCount());
for (int i = 0; i < getChildCount(); i++) {
- list.add(getChild(i));
+ list.add(child(i));
}
- return UiObjectCollection.ofCompat(list);
+ return UiObjectCollection.of(list);
}
public int childCount() {
@@ -428,20 +434,6 @@ public class UiObject extends AccessibilityNodeInfoCompat {
return new UiGlobalSelector().id(viewId).findAndReturnList(this);
}
- public static List compatListToUiObjectList(List compats, AccessibilityNodeInfoAllocator allocator) {
- // FIXME: 2017/11/5 lost depth info
- List uiObjects = new ArrayList<>(compats.size());
- for (AccessibilityNodeInfoCompat compat : compats) {
- if (compat != null)
- uiObjects.add(new UiObject(compat.getInfo(), allocator));
- }
- return uiObjects;
- }
-
- public static List compatListToUiObjectList(List compats) {
- return compatListToUiObjectList(compats, null);
- }
-
@Override
public void recycle() {
try {
@@ -451,4 +443,5 @@ public class UiObject extends AccessibilityNodeInfoCompat {
}
}
+
}
diff --git a/automator/src/main/java/com/stardust/automator/UiObjectCollection.java b/automator/src/main/java/com/stardust/automator/UiObjectCollection.java
index d4ae681d..1435a356 100644
--- a/automator/src/main/java/com/stardust/automator/UiObjectCollection.java
+++ b/automator/src/main/java/com/stardust/automator/UiObjectCollection.java
@@ -31,10 +31,6 @@ public class UiObjectCollection {
public static final UiObjectCollection EMPTY = UiObjectCollection.of(Collections.emptyList());
- public static UiObjectCollection ofCompat(List list) {
- return new UiObjectCollection(UiObject.compatListToUiObjectList(list));
- }
-
public static UiObjectCollection of(List list) {
return new UiObjectCollection(list);
}
diff --git a/automator/src/main/java/com/stardust/automator/filter/BooleanFilter.java b/automator/src/main/java/com/stardust/automator/filter/BooleanFilter.java
index 1f01dd01..627d8a0b 100644
--- a/automator/src/main/java/com/stardust/automator/filter/BooleanFilter.java
+++ b/automator/src/main/java/com/stardust/automator/filter/BooleanFilter.java
@@ -42,6 +42,11 @@ public class BooleanFilter extends DfsFilter {
public boolean get(UiObject node) {
return node.isCheckable();
}
+
+ @Override
+ public String toString() {
+ return "checkable";
+ }
};
public static final BooleanSupplier CHECKED = new BooleanSupplier() {
@@ -50,6 +55,11 @@ public class BooleanFilter extends DfsFilter {
public boolean get(UiObject node) {
return node.isChecked();
}
+
+ @Override
+ public String toString() {
+ return "checked";
+ }
};
public static final BooleanSupplier FOCUSABLE = new BooleanSupplier() {
@@ -58,6 +68,11 @@ public class BooleanFilter extends DfsFilter {
public boolean get(UiObject node) {
return node.isFocusable();
}
+
+ @Override
+ public String toString() {
+ return "focusable";
+ }
};
public static final BooleanSupplier FOCUSED = new BooleanSupplier() {
@@ -66,6 +81,11 @@ public class BooleanFilter extends DfsFilter {
public boolean get(UiObject node) {
return node.isFocused();
}
+
+ @Override
+ public String toString() {
+ return "focused";
+ }
};
public static final BooleanSupplier VISIBLE_TO_USER = new BooleanSupplier() {
@@ -74,6 +94,11 @@ public class BooleanFilter extends DfsFilter {
public boolean get(UiObject node) {
return node.isVisibleToUser();
}
+
+ @Override
+ public String toString() {
+ return "visibleToUser";
+ }
};
public static final BooleanSupplier ACCESSIBILITY_FOCUSED = new BooleanSupplier() {
@@ -82,6 +107,11 @@ public class BooleanFilter extends DfsFilter {
public boolean get(UiObject node) {
return node.isAccessibilityFocused();
}
+
+ @Override
+ public String toString() {
+ return "accessibilityFocused";
+ }
};
public static final BooleanSupplier SELECTED = new BooleanSupplier() {
@@ -90,6 +120,11 @@ public class BooleanFilter extends DfsFilter {
public boolean get(UiObject node) {
return node.isSelected();
}
+
+ @Override
+ public String toString() {
+ return "selected";
+ }
};
public static final BooleanSupplier CLICKABLE = new BooleanSupplier() {
@@ -98,6 +133,11 @@ public class BooleanFilter extends DfsFilter {
public boolean get(UiObject node) {
return node.isClickable();
}
+
+ @Override
+ public String toString() {
+ return "clickable";
+ }
};
public static final BooleanSupplier LONG_CLICKABLE = new BooleanSupplier() {
@@ -106,6 +146,11 @@ public class BooleanFilter extends DfsFilter {
public boolean get(UiObject node) {
return node.isLongClickable();
}
+
+ @Override
+ public String toString() {
+ return "longClickable";
+ }
};
public static final BooleanSupplier ENABLED = new BooleanSupplier() {
@@ -114,6 +159,11 @@ public class BooleanFilter extends DfsFilter {
public boolean get(UiObject node) {
return node.isEnabled();
}
+
+ @Override
+ public String toString() {
+ return "enabled";
+ }
};
@@ -123,6 +173,11 @@ public class BooleanFilter extends DfsFilter {
public boolean get(UiObject node) {
return node.isPassword();
}
+
+ @Override
+ public String toString() {
+ return "password";
+ }
};
public static final BooleanSupplier SCROLLABLE = new BooleanSupplier() {
@@ -131,6 +186,11 @@ public class BooleanFilter extends DfsFilter {
public boolean get(UiObject node) {
return node.isScrollable();
}
+
+ @Override
+ public String toString() {
+ return "scrollable";
+ }
};
public static final BooleanSupplier EDITABLE = new BooleanSupplier() {
@@ -139,6 +199,11 @@ public class BooleanFilter extends DfsFilter {
public boolean get(UiObject node) {
return node.isEditable();
}
+
+ @Override
+ public String toString() {
+ return "editable";
+ }
};
public static final BooleanSupplier CONTENT_INVALID = new BooleanSupplier() {
@@ -146,6 +211,11 @@ public class BooleanFilter extends DfsFilter {
public boolean get(UiObject node) {
return node.isContentInvalid();
}
+
+ @Override
+ public String toString() {
+ return "contentInvalid";
+ }
};
public static final BooleanSupplier CONTEXT_CLICKABLE = new BooleanSupplier() {
@@ -155,6 +225,11 @@ public class BooleanFilter extends DfsFilter {
public boolean get(UiObject node) {
return node.isContextClickable();
}
+
+ @Override
+ public String toString() {
+ return "checkable";
+ }
};
public static final BooleanSupplier MULTI_LINE = new BooleanSupplier() {
@@ -163,6 +238,11 @@ public class BooleanFilter extends DfsFilter {
public boolean get(UiObject node) {
return node.isMultiLine();
}
+
+ @Override
+ public String toString() {
+ return "multiLine";
+ }
};
public static final BooleanSupplier DISMISSABLE = new BooleanSupplier() {
@@ -171,6 +251,11 @@ public class BooleanFilter extends DfsFilter {
public boolean get(UiObject node) {
return node.isDismissable();
}
+
+ @Override
+ public String toString() {
+ return "dismissable";
+ }
};
private BooleanSupplier mBooleanSupplier;
@@ -186,4 +271,8 @@ public class BooleanFilter extends DfsFilter {
return nodeInfo != null && mBooleanSupplier.get(nodeInfo) == mExceptedValue;
}
+ @Override
+ public String toString() {
+ return mBooleanSupplier.toString() + "(" + mExceptedValue + ")";
+ }
}
diff --git a/automator/src/main/java/com/stardust/automator/filter/BoundsFilter.java b/automator/src/main/java/com/stardust/automator/filter/BoundsFilter.java
index 37cade4d..1b243fec 100644
--- a/automator/src/main/java/com/stardust/automator/filter/BoundsFilter.java
+++ b/automator/src/main/java/com/stardust/automator/filter/BoundsFilter.java
@@ -5,6 +5,8 @@ import android.graphics.Rect;
import com.stardust.automator.UiObject;
import com.stardust.view.accessibility.AccessibilityNodeInfoHelper;
+import java.util.Locale;
+
/**
* Created by Stardust on 2017/3/9.
*/
@@ -33,4 +35,11 @@ public class BoundsFilter extends DfsFilter {
return boundsInScreen.equals(mBounds);
return mBounds.contains(boundsInScreen);
}
+
+ @Override
+ public String toString() {
+ return String.format(Locale.getDefault(), "bounds%s(%d, %d, %d, %d)", mType == TYPE_EQUALS ? "" :
+ mType == TYPE_INSIDE ? "Inside" : "Contains",
+ mBounds.left, mBounds.top, mBounds.right, mBounds.bottom);
+ }
}
diff --git a/automator/src/main/java/com/stardust/automator/filter/ClassNameFilter.java b/automator/src/main/java/com/stardust/automator/filter/ClassNameFilter.java
index 9cb3b6a6..611646ff 100644
--- a/automator/src/main/java/com/stardust/automator/filter/ClassNameFilter.java
+++ b/automator/src/main/java/com/stardust/automator/filter/ClassNameFilter.java
@@ -14,6 +14,11 @@ public class ClassNameFilter {
CharSequence charSequence = nodeInfo.getClassName();
return charSequence == null ? null : charSequence.toString();
}
+
+ @Override
+ public String toString() {
+ return "className";
+ }
};
public static ListFilter equals(String text) {
diff --git a/automator/src/main/java/com/stardust/automator/filter/DescFilter.java b/automator/src/main/java/com/stardust/automator/filter/DescFilter.java
index fb066721..92517644 100644
--- a/automator/src/main/java/com/stardust/automator/filter/DescFilter.java
+++ b/automator/src/main/java/com/stardust/automator/filter/DescFilter.java
@@ -14,6 +14,11 @@ public class DescFilter {
CharSequence charSequence = nodeInfo.getContentDescription();
return charSequence == null ? null : charSequence.toString();
}
+
+ @Override
+ public String toString() {
+ return "desc";
+ }
};
public static ListFilter equals(String text) {
diff --git a/automator/src/main/java/com/stardust/automator/filter/IdFilter.java b/automator/src/main/java/com/stardust/automator/filter/IdFilter.java
index 6aa934dc..917129fa 100644
--- a/automator/src/main/java/com/stardust/automator/filter/IdFilter.java
+++ b/automator/src/main/java/com/stardust/automator/filter/IdFilter.java
@@ -16,6 +16,11 @@ public class IdFilter extends ListFilter.Default {
public String getKey(UiObject nodeInfo) {
return nodeInfo.getViewIdResourceName();
}
+
+ @Override
+ public String toString() {
+ return "id";
+ }
};
public static StringEqualsFilter equals(String id) {
diff --git a/automator/src/main/java/com/stardust/automator/filter/IntFilter.java b/automator/src/main/java/com/stardust/automator/filter/IntFilter.java
index fed85da3..d5b356a7 100644
--- a/automator/src/main/java/com/stardust/automator/filter/IntFilter.java
+++ b/automator/src/main/java/com/stardust/automator/filter/IntFilter.java
@@ -17,6 +17,11 @@ public class IntFilter extends DfsFilter {
public int get(UiObject object) {
return object.depth();
}
+
+ @Override
+ public String toString() {
+ return "depth";
+ }
};
public static final IntProperty ROW = new IntProperty() {
@@ -24,6 +29,11 @@ public class IntFilter extends DfsFilter {
public int get(UiObject object) {
return object.row();
}
+
+ @Override
+ public String toString() {
+ return "row";
+ }
};
public static final IntProperty ROW_COUNT = new IntProperty() {
@@ -31,6 +41,11 @@ public class IntFilter extends DfsFilter {
public int get(UiObject object) {
return object.rowCount();
}
+
+ @Override
+ public String toString() {
+ return "rowCount";
+ }
};
public static final IntProperty ROW_SPAN = new IntProperty() {
@@ -38,6 +53,11 @@ public class IntFilter extends DfsFilter {
public int get(UiObject object) {
return object.rowSpan();
}
+
+ @Override
+ public String toString() {
+ return "rowSpan";
+ }
};
public static final IntProperty COLUMN = new IntProperty() {
@@ -45,6 +65,11 @@ public class IntFilter extends DfsFilter {
public int get(UiObject object) {
return object.column();
}
+
+ @Override
+ public String toString() {
+ return "column";
+ }
};
public static final IntProperty COLUMN_COUNT = new IntProperty() {
@@ -52,6 +77,11 @@ public class IntFilter extends DfsFilter {
public int get(UiObject object) {
return object.columnCount();
}
+
+ @Override
+ public String toString() {
+ return "columnCount";
+ }
};
public static final IntProperty COLUMN_SPAN = new IntProperty() {
@@ -59,6 +89,11 @@ public class IntFilter extends DfsFilter {
public int get(UiObject object) {
return object.columnSpan();
}
+
+ @Override
+ public String toString() {
+ return "columnSpan";
+ }
};
private IntProperty mIntProperty;
@@ -73,4 +108,9 @@ public class IntFilter extends DfsFilter {
protected boolean isIncluded(UiObject nodeInfo) {
return mIntProperty.get(nodeInfo) == mValue;
}
+
+ @Override
+ public String toString() {
+ return mIntProperty.toString() + "(" + mValue + ")";
+ }
}
diff --git a/automator/src/main/java/com/stardust/automator/filter/PackageNameFilter.java b/automator/src/main/java/com/stardust/automator/filter/PackageNameFilter.java
index ab48dc25..17436b03 100644
--- a/automator/src/main/java/com/stardust/automator/filter/PackageNameFilter.java
+++ b/automator/src/main/java/com/stardust/automator/filter/PackageNameFilter.java
@@ -14,6 +14,11 @@ public class PackageNameFilter {
CharSequence charSequence = nodeInfo.getPackageName();
return charSequence == null ? null : charSequence.toString();
}
+
+ @Override
+ public String toString() {
+ return "packageName";
+ }
};
public static ListFilter equals(String text) {
diff --git a/automator/src/main/java/com/stardust/automator/filter/StringContainsFilter.java b/automator/src/main/java/com/stardust/automator/filter/StringContainsFilter.java
index 21a37d74..2647cbb0 100644
--- a/automator/src/main/java/com/stardust/automator/filter/StringContainsFilter.java
+++ b/automator/src/main/java/com/stardust/automator/filter/StringContainsFilter.java
@@ -21,4 +21,8 @@ public class StringContainsFilter extends DfsFilter {
return key != null && key.contains(mContains);
}
+ @Override
+ public String toString() {
+ return mKeyGetter.toString() + "Contains(\"" + mContains + "\")";
+ }
}
diff --git a/automator/src/main/java/com/stardust/automator/filter/StringEndsWithFilter.java b/automator/src/main/java/com/stardust/automator/filter/StringEndsWithFilter.java
index 42914e7c..ee78bebd 100644
--- a/automator/src/main/java/com/stardust/automator/filter/StringEndsWithFilter.java
+++ b/automator/src/main/java/com/stardust/automator/filter/StringEndsWithFilter.java
@@ -22,4 +22,8 @@ public class StringEndsWithFilter extends DfsFilter {
return key != null && key.endsWith(mSuffix);
}
+ @Override
+ public String toString() {
+ return mKeyGetter.toString() + "EndsWith(\"" + mSuffix + "\")";
+ }
}
diff --git a/automator/src/main/java/com/stardust/automator/filter/StringEqualsFilter.java b/automator/src/main/java/com/stardust/automator/filter/StringEqualsFilter.java
index e3b84818..61059ffe 100644
--- a/automator/src/main/java/com/stardust/automator/filter/StringEqualsFilter.java
+++ b/automator/src/main/java/com/stardust/automator/filter/StringEqualsFilter.java
@@ -19,9 +19,14 @@ public class StringEqualsFilter extends DfsFilter {
@Override
protected boolean isIncluded(UiObject nodeInfo) {
String key = mKeyGetter.getKey(nodeInfo);
- if(key != null){
+ if (key != null) {
return key.equals(mText);
}
return false;
}
+
+ @Override
+ public String toString() {
+ return mKeyGetter.toString() + "(\"" + mText + "\")";
+ }
}
diff --git a/automator/src/main/java/com/stardust/automator/filter/StringMatchesFilter.java b/automator/src/main/java/com/stardust/automator/filter/StringMatchesFilter.java
index 46470eeb..bcab8b4f 100644
--- a/automator/src/main/java/com/stardust/automator/filter/StringMatchesFilter.java
+++ b/automator/src/main/java/com/stardust/automator/filter/StringMatchesFilter.java
@@ -22,4 +22,8 @@ public class StringMatchesFilter extends DfsFilter {
return key != null && key.matches(mRegex);
}
+ @Override
+ public String toString() {
+ return mKeyGetter.toString() + "Matches(\"" + mRegex + "\")";
+ }
}
diff --git a/automator/src/main/java/com/stardust/automator/filter/StringStartsWithFilter.java b/automator/src/main/java/com/stardust/automator/filter/StringStartsWithFilter.java
index e8347003..954f0f73 100644
--- a/automator/src/main/java/com/stardust/automator/filter/StringStartsWithFilter.java
+++ b/automator/src/main/java/com/stardust/automator/filter/StringStartsWithFilter.java
@@ -22,4 +22,8 @@ public class StringStartsWithFilter extends DfsFilter {
return key != null && key.startsWith(mPrefix);
}
+ @Override
+ public String toString() {
+ return mKeyGetter.toString() + "StartsWith(\"" + mPrefix + "\")";
+ }
}
diff --git a/automator/src/main/java/com/stardust/automator/filter/TextFilter.java b/automator/src/main/java/com/stardust/automator/filter/TextFilter.java
index 9cfa6593..fc87dc12 100644
--- a/automator/src/main/java/com/stardust/automator/filter/TextFilter.java
+++ b/automator/src/main/java/com/stardust/automator/filter/TextFilter.java
@@ -16,6 +16,11 @@ public class TextFilter extends ListFilter.Default {
CharSequence charSequence = nodeInfo.getText();
return charSequence == null ? null : charSequence.toString();
}
+
+ @Override
+ public String toString() {
+ return "text";
+ }
};
public static ListFilter equals(String text) {
diff --git a/automator/src/main/java/com/stardust/view/accessibility/AccessibilityService.java b/automator/src/main/java/com/stardust/view/accessibility/AccessibilityService.java
index 6b16b4c8..00680218 100644
--- a/automator/src/main/java/com/stardust/view/accessibility/AccessibilityService.java
+++ b/automator/src/main/java/com/stardust/view/accessibility/AccessibilityService.java
@@ -61,10 +61,10 @@ public class AccessibilityService extends android.accessibilityservice.Accessibi
Log.v(TAG, "onAccessibilityEvent: " + event);
if (!containsAllEventTypes && !eventTypes.contains(event.getEventType()))
return;
- int type = event.getEventType();
- if (type == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED || type == AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
- || type == AccessibilityEvent.TYPE_VIEW_HOVER_EXIT) {
- mFastRootInActiveWindow = super.getRootInActiveWindow();
+ AccessibilityNodeInfo root = super.getRootInActiveWindow();
+ if (root != null) {
+ mFastRootInActiveWindow = root;
+ Log.v(TAG, "root not null: " + event);
}
for (Map.Entry entry : mDelegates.entrySet()) {
AccessibilityDelegate delegate = entry.getValue();
@@ -164,4 +164,5 @@ public class AccessibilityService extends android.accessibilityservice.Accessibi
return stickOnKeyObserver;
}
+
}
diff --git a/automator/src/main/java/com/stardust/view/accessibility/LayoutInspector.java b/automator/src/main/java/com/stardust/view/accessibility/LayoutInspector.java
index 9cc30e1b..7d99e080 100644
--- a/automator/src/main/java/com/stardust/view/accessibility/LayoutInspector.java
+++ b/automator/src/main/java/com/stardust/view/accessibility/LayoutInspector.java
@@ -28,23 +28,28 @@ public class LayoutInspector {
Log.d(LOG_TAG, "captureCurrentWindow: service = null");
mCapture = null;
} else {
- final AccessibilityNodeInfo root = service.getRootInActiveWindow();
+ final AccessibilityNodeInfo root = getRootInActiveWindow(service);
if (root == null) {
Log.d(LOG_TAG, "captureCurrentWindow: root = null");
mCapture = null;
} else {
- mExecutor.execute(new Runnable() {
- @Override
- public void run() {
- mDumping = true;
- mCapture = NodeInfo.capture(root);
- mDumping = false;
- }
+ mExecutor.execute(() -> {
+ mDumping = true;
+ mCapture = NodeInfo.capture(root);
+ mDumping = false;
});
}
}
}
+ private AccessibilityNodeInfo getRootInActiveWindow(AccessibilityService service) {
+ AccessibilityNodeInfo root = service.getRootInActiveWindow();
+ if (root == null)
+ return service.fastRootInActiveWindow();
+ return root;
+
+ }
+
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
private void refreshChildList(AccessibilityNodeInfo root) {
if (root == null)
diff --git a/automator/src/main/java/com/stardust/view/accessibility/NodeInfo.java b/automator/src/main/java/com/stardust/view/accessibility/NodeInfo.java
index 2b334522..95a09967 100644
--- a/automator/src/main/java/com/stardust/view/accessibility/NodeInfo.java
+++ b/automator/src/main/java/com/stardust/view/accessibility/NodeInfo.java
@@ -3,6 +3,7 @@ package com.stardust.view.accessibility;
import android.graphics.Rect;
import android.support.annotation.Keep;
import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
import android.view.accessibility.AccessibilityNodeInfo;
@@ -49,9 +50,10 @@ public class NodeInfo {
public boolean checkable;
public boolean focused;
public boolean visibleToUser;
+ public NodeInfo parent;
- public NodeInfo(UiObject node) {
+ public NodeInfo(UiObject node, NodeInfo parent) {
id = simplifyId(node.getViewIdResourceName());
desc = node.desc();
className = node.className();
@@ -86,6 +88,8 @@ public class NodeInfo {
node.getBoundsInParent(mBoundsInParent);
bounds = boundsToString(mBoundsInScreen);
+ this.parent = parent;
+
}
private String simplifyId(String idResourceName) {
@@ -109,13 +113,13 @@ public class NodeInfo {
}
- public static NodeInfo capture(@NonNull UiObject parent) {
- NodeInfo nodeInfo = new NodeInfo(parent);
- int childCount = parent.getChildCount();
+ public static NodeInfo capture(@NonNull UiObject uiObject, @Nullable NodeInfo parent) {
+ NodeInfo nodeInfo = new NodeInfo(uiObject, parent);
+ int childCount = uiObject.getChildCount();
for (int i = 0; i < childCount; i++) {
- UiObject child = parent.child(i);
+ UiObject child = uiObject.child(i);
if (child != null) {
- nodeInfo.children.add(capture(child));
+ nodeInfo.children.add(capture(child, nodeInfo));
}
}
return nodeInfo;
@@ -123,11 +127,48 @@ public class NodeInfo {
public static NodeInfo capture(@NonNull AccessibilityNodeInfo root) {
UiObject r = UiObject.createRoot(root);
- return capture(r);
+ return capture(r, null);
}
@NonNull
public List getChildren() {
return children;
}
+
+ @Override
+ public String toString() {
+ return className + "{" +
+ "childCount=" + children.size() +
+ ", mBoundsInScreen=" + mBoundsInScreen +
+ ", mBoundsInParent=" + mBoundsInParent +
+ ", id='" + id + '\'' +
+ ", desc='" + desc + '\'' +
+ ", packageName='" + packageName + '\'' +
+ ", text='" + text + '\'' +
+ ", depth=" + depth +
+ ", drawingOrder=" + drawingOrder +
+ ", accessibilityFocused=" + accessibilityFocused +
+ ", checked=" + checked +
+ ", clickable=" + clickable +
+ ", contextClickable=" + contextClickable +
+ ", dismissable=" + dismissable +
+ ", editable=" + editable +
+ ", enabled=" + enabled +
+ ", focusable=" + focusable +
+ ", longClickable=" + longClickable +
+ ", row=" + row +
+ ", column=" + column +
+ ", rowCount=" + rowCount +
+ ", columnCount=" + columnCount +
+ ", rowSpan=" + rowSpan +
+ ", columnSpan=" + columnSpan +
+ ", selected=" + selected +
+ ", scrollable=" + scrollable +
+ ", bounds='" + bounds + '\'' +
+ ", checkable=" + checkable +
+ ", focused=" + focused +
+ ", visibleToUser=" + visibleToUser +
+ ", parent=" + parent.className +
+ '}';
+ }
}