Android辅助权限之微信自动评论与点赞
当我们把辅助权限玩的比较熟悉 的时候,就可以释放我们的双手做一些有趣的事情了,例如之前网上流传的微信自动抢红包插件,就是使用的这个服务,不过我们今儿讲的是微信自动评论与点赞功能(抢红包的文章网上已经有比较多)。
一、悬浮窗配置
关于悬浮窗的详细配置,请看我另一篇博文,这里不再赘述,「传送门」:
Android 辅助权限与悬浮窗
二、自动化逻辑代码实现
说明:我们通过 Monitor 工具,取到的节点 id ,在微信的每个版本是不一样的 (微信动态生成节点 id,我是通过服务器后台对不同的微信版本,维护一份 id 配置,根据请求的微信版本,返回对应得 id 值),所以本文以微信 v6.7.2 的版本作为例子,如下代码可作参考。
这里只是提供了微信自动点赞与自动评论的示例,当然本人也写了类似于微信自动加好友,自动加附近的人,检测死粉的功能,钉钉自动打卡... 这里只是抛转引玉,大家根据我提供的思路,去实现,由于源码涉及服务器相关操作,不太方便开源,
{"tasks": [{"nodes": [{"action": "scrllor", "className": "android.widget.ListView", "id": "com.tencent.mm:id/cno", "key": "nearHumanList", "text": "@附近的人列表"}, {"className": "android.widget.TextView", "id": "com.tencent.mm:id/b3i", "key": "nearHumanListName", "text": "@附近的人列表名字"}, {"className": "android.widget.TextView", "id": "com.tencent.mm:id/sm", "key": "detailName", "text": "@附近的人详情名字"}, {"className": "android.widget.ListView", "id": "com.tencent.mm:id/bcs", "key": "phoneHumanList", "text": "@手机联系人列表"}, {"className": "android.widget.TextView", "id": "com.tencent.mm:id/bgl", "key": "phoneHumanListName", "text": "@手机联系人列表名字"}, {"className": "android.widget.TextView", "id": "com.tencent.mm:id/bgm", "key": "phoneHumanListAccount", "text": "@手机联系人列表昵称"}, {"className": "android.widget.TextView", "id": "com.tencent.mm:id/sm", "key": "phoneHumandetailName", "text": "@手机联系人详情名字"}, {"className": "android.widget.ListView","id": "com.tencent.mm:id/doq","key": "momentList","text": "@朋友圈列表"}],"pages": [ ],"taskName": "微信脚本","version": "6.7.2"}]
}
复制代码 1、微信朋友圈自动点赞
效果如图(希望我朋友不会打我,这里就不视频打码了,┭┮﹏┭┮),这里面的悬浮窗可以有效阻挡用户操作,只有点击停止之后,才能操作微信界面。
/*** 朋友圈点赞* Created by czc on 2018/8/23.*/
public class LikeStrategy extends BaseStrategy {@Overrideprotected boolean handleEvent() {/*** 匹配每个界面,根据当前界面执行相关操作* 1、在微信首页点击【发现】按钮* 2、然后点击【朋友圈】,进入朋友圈界面* 3、滚动朋友圈【动态列表】,对每个动态进行点赞*/if (matchPage(Page.LauncherUI) || matchPage(Page.WxViewPager)) {clickFindBtn(getRoot());clickCommentTv(getRoot());} else if (checkWxScroller(Page.SnsTimeLineUI)) {scrollerList(getRoot());} else if (matchPage(Page.BaseP)) {} else {return false;}return true;}private void clickFindBtn(AccessibilityNodeInfo root) {NodeUtil.findNodeByTextAndClick(root, "发现");}private void clickCommentTv(AccessibilityNodeInfo root) {NodeUtil.findNodeByTextAndClick(root, "朋友圈");}private void scrollerList(AccessibilityNodeInfo root) {//这里的滚动控件对应于朋友圈动态的 ListView AccessibilityNodeInfo scrollerNode = findNodeByTaskNode(root, getNode("momentList"));if (scrollerNode == null) {Log.e(TAG, "scroller is null");return;}if (scrollerNode != null) {final int count = scrollerNode.getChildCount();for (int i = 0; i < count; i++) {AccessibilityNodeInfo child = scrollerNode.getChild(i);if (child != null && child.isVisibleToUser()) {AccessibilityNodeInfo commentNode = NodeUtil.findNodeByFilter(child, new NodeUtil.NodeFilter() {@Overridepublic String text() {return "评论";}@Overridepublic boolean filter(AccessibilityNodeInfo node) {return node.getClassName() != null && node.getClassName().equals(NodeUtil.IMAGE_VIEW)&& node.getContentDescription() != null && node.getContentDescription().toString().equals("评论");}});if (commentNode != null && commentNode.isVisibleToUser()) {NodeUtil.performClick(commentNode);NodeUtil.findNodeByFilterAndClick(root, new NodeUtil.NodeFilter() {@Overridepublic String text() {return "赞";}@Overridepublic boolean filter(AccessibilityNodeInfo node) {return node.getClassName() != null && node.getClassName().equals(NodeUtil.TEXT_VIEW)&& node.getText() != null && node.getText().toString().equals("赞");}});}}//可见的最后一个 item if (i == count - 1) {//滚动控件是否可以滚动if (scrollerNode.isScrollable()) {NodeUtil.findNodeByFilterAndClick(root, new NodeUtil.NodeFilter() {@Overridepublic String text() {return "评论";}@Overridepublic boolean filter(AccessibilityNodeInfo node) {return node.getClassName() != null && node.getClassName().equals(NodeUtil.TEXT_VIEW)&& node.getText() != null && node.getText().toString().equals("评论");}});//循环滚动performScroll(scrollerNode);}}}}}
}
复制代码 2、微信朋友圈自动评论
效果如图
/*** 朋友圈评论* Created by czc on 2018/8/23.*/
public class CommentStrategy extends BaseStrategy {@Overrideprotected boolean handleEvent() {/*** 匹配每个界面,根据当前界面执行相关操作* 1、在微信首页点击【发现】按钮* 2、然后点击【朋友圈】,进入朋友圈界面* 3、滚动朋友圈【动态列表】,对每个动态进行评论*/if (matchPage(Page.LauncherUI) || matchPage(Page.WxViewPager)) {clickFindBtn(getRoot());clickCommentTv(getRoot());} else if (checkWxScroller(Page.SnsTimeLineUI)) {scrollerList(getRoot());} else if (matchPage(Page.BaseP)) {} else {return false;}return true;}private void clickFindBtn(AccessibilityNodeInfo root) {NodeUtil.findNodeByTextAndClick(root, "发现");}private void clickCommentTv(AccessibilityNodeInfo root) {NodeUtil.findNodeByTextAndClick(root, "朋友圈");}private void scrollerList(AccessibilityNodeInfo root) {AccessibilityNodeInfo scrollerNode = findNodeByTaskNode(root, getNode("momentList"));if (scrollerNode == null) {Log.e(TAG, "scroller is null");return;}if (scrollerNode != null) {final int count = scrollerNode.getChildCount();for (int i = 0; i < count; i++) {AccessibilityNodeInfo child = scrollerNode.getChild(i);if (child != null && child.isVisibleToUser()) {AccessibilityNodeInfo commentNode = NodeUtil.findNodeByFilter(child, new NodeUtil.NodeFilter() {@Overridepublic String text() {return "评论";}@Overridepublic boolean filter(AccessibilityNodeInfo node) {return node.getClassName() != null && node.getClassName().equals(NodeUtil.IMAGE_VIEW)&& node.getContentDescription() != null && node.getContentDescription().toString().equals("评论");}});if (commentNode != null && commentNode.isVisibleToUser()) {NodeUtil.performClick(commentNode);NodeUtil.findNodeByFilterAndClick(root, new NodeUtil.NodeFilter() {@Overridepublic String text() {return "评论";}@Overridepublic boolean filter(AccessibilityNodeInfo node) {return node.getClassName() != null && node.getClassName().equals(NodeUtil.TEXT_VIEW)&& node.getText() != null && node.getText().toString().equals("评论");}});AccessibilityNodeInfo editNode = NodeUtil.findNodeByFilter(child, new NodeUtil.NodeFilter() {@Overridepublic String text() {return "评论";}@Overridepublic boolean filter(AccessibilityNodeInfo node) {return node.getClassName() != null && node.getClassName().equals(NodeUtil.EDIT_TEXT)&& node.getText() != null && node.getText().toString().equals("评论");}});if (editNode == null) {if (root != null) {editNode = root.findFocus(AccessibilityNodeInfo.FOCUS_INPUT);}}if (editNode != null) {//输入自定义评论内容NodeUtil.performPaste(editNode, "东西不错哦~");//点击【发送】NodeUtil.findNodeByTextAndClick(root, "发送");}}}if (i == count - 1) {if (scrollerNode.isScrollable()) {performScroll(scrollerNode);}}}}}
}
复制代码 3、相关工具类
工具类里面的代码是自己封装的,不一定都适用,工具类可能存在不足与缺陷,为什么执行操作需要 Sleep 1s ,因为太快的话,有些界面的节点信息还没更新出来,会导致点击失败等情况:
/*** Created by czc on 2017/7/3.*/
public class NodeUtil {private static final String TAG = "NodeUtil";private static final int millis = 1000;public static final String LIST_VIEW = "android.widget.ListView";public static final String ABS_LIST_VIEW = "android.widget.AbsListView";public static final String SCROLL_VIEW = "android.widget.ScrollView";public static final String TEXT_VIEW = "android.widget.TextView";public static final String BUTTON = "android.widget.Button";public static final String VIEW = "android.view.View";public static final String IMAGE_VIEW = "android.widget.ImageView";public static final String IMAGE_BUTTON = "android.widget.ImageButton";public static final String GRID_VIEW = "android.widget.GridView";public static final String EDIT_TEXT = "android.widget.EditText";public static final String RELATIVE_LAYOUT = "android.widget.RelativeLayout";public static final String LINEAR_LAYOUT = "android.widget.LinearLayout";public static final String LINEAR_LAYOUT_COMPAT = "android.support.v7.widget.LinearLayoutCompat";public static void sleep(long times) {try {Thread.sleep(times);} catch (InterruptedException e) {e.printStackTrace();}}public static boolean checkNodeText(AccessibilityNodeInfo nodeInfo) {if (nodeInfo == null) {return false;}return !StringUtil.isEmpty(nodeInfo.getText().toString());}public static boolean checkNodeDes(AccessibilityNodeInfo nodeInfo) {if (nodeInfo == null) {return false;}return !StringUtil.isEmpty(nodeInfo.getContentDescription());}public static boolean performClick(AccessibilityNodeInfo node) {AccessibilityNodeInfo clickNode = node;if (clickNode == null) {return false;}while (clickNode != null&& !clickNode.isClickable()) {clickNode = clickNode.getParent();}if (clickNode != null) {boolean result = clickNode.performAction(AccessibilityNodeInfo.ACTION_CLICK);sleep();return result;}Log.e(TAG, "clickNode is null");return false;}// root下,通过 adb 命令执行点击public static boolean performShellClick(AccessibilityNodeInfo node) {AccessibilityNodeInfo clickNode = node;if (clickNode == null) {return false;}Rect r = new Rect();node.getBoundsInScreen(r);if (r.centerX() > ScreenUtils.getScreenWidth(OttUtil.get().getApp())|| r.centerY() > ScreenUtils.getScreenHeight(OttUtil.get().getApp())|| r.centerX() <= 0|| r.centerY() <= 0) {return false;}String cmd = String.format("input tap %d %d", r.centerX(), r.centerY());ShellUtils.CommandResult commandResult = ShellUtils.execCmd(cmd, true);sleep();return commandResult.result != -1;}// root下,通过 adb 命令执行长按public static boolean performShellLongClick(AccessibilityNodeInfo node, long time) {AccessibilityNodeInfo clickNode = node;if (clickNode == null) {return false;}Rect r = new Rect();clickNode.getBoundsInScreen(r);int x = r.centerX();int y = r.centerY();String cmd = String.format("input swipe %d %d %d %d %d", x, y, x, y, time);ShellUtils.CommandResult commandResult = ShellUtils.execCmd(cmd, true);NodeUtil.sleep(time);return commandResult.result != -1;}// root下,通过 adb 命令执行滚动public static boolean performShellScroll() {int screenWidth = ScreenUtils.getScreenWidth(OttUtil.get().getApp());int screenHeight = ScreenUtils.getScreenHeight(OttUtil.get().getApp());String cmd = String.format("input swipe %d %d %d %d %d", screenWidth / 2, (int) (screenHeight * (3 * 1.0f / 5)),screenWidth / 2, screenHeight / 5, 1500L);ShellUtils.CommandResult commandResult = ShellUtils.execCmd(cmd, true);NodeUtil.sleep(500);return commandResult.result != -1;}public static boolean performScroll(AccessibilityNodeInfo scrollerNode) {while (scrollerNode != null && !scrollerNode.isScrollable()) {scrollerNode = scrollerNode.getParent();}if (scrollerNode != null) {boolean result = scrollerNode.performAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD);sleep();return result;}Log.e(TAG, "scrollerNode is null");return false;}public static boolean performScrollBack(AccessibilityNodeInfo scrollerNode) {while (scrollerNode != null && !scrollerNode.isScrollable()) {scrollerNode = scrollerNode.getParent();}if (scrollerNode != null) {boolean result = scrollerNode.performAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD);sleep();return result;}return false;}/*** 执行粘贴操作(注意:执行之后,会 sleep 1s)* @param ct* @param node* @param text* @return*/public static boolean performPaste(Context ct, AccessibilityNodeInfo node, String text) {if (node == null || StringUtil.isEmpty(text)) {return false;}boolean result;if (Build.VERSION.SDK_INT >= 21) {Bundle arguments = new Bundle();arguments.putCharSequence(AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, text);result = node.performAction(AccessibilityNodeInfo.ACTION_SET_TEXT, arguments);sleep();return result;} else {ClipboardManager cm = (ClipboardManager) ct.getSystemService(Context.CLIPBOARD_SERVICE);ClipData mClipData = ClipData.newPlainText("text", text);cm.setPrimaryClip(mClipData);result = node.performAction(AccessibilityNodeInfo.ACTION_PASTE);sleep();return result;}}public static boolean hasNode(AccessibilityNodeInfo root, String text) {if (root == null || StringUtil.isEmpty(text)) {return false;}List nodeList = root.findAccessibilityNodeInfosByText(text);if (nodeList == null || nodeList.isEmpty()) {return false;}return true;}public static AccessibilityNodeInfo findNodeByFilter(AccessibilityNodeInfo root, String text, NodeFilter filter) {if (root == null || StringUtil.isEmpty(text)) {return null;}List nodeList = root.findAccessibilityNodeInfosByText(text);if (nodeList == null || nodeList.isEmpty()) {return null;}AccessibilityNodeInfo clickNode = null;for (AccessibilityNodeInfo nodeInfo : nodeList) {if (filter.filter(nodeInfo)) {clickNode = nodeInfo;break;}}return clickNode;}public static AccessibilityNodeInfo findNodeByFilter(AccessibilityNodeInfo root, NodeTextFilter filter) {if (root == null || filter == null || StringUtil.isEmpty(filter.fiterText())) {return null;}List nodeList = root.findAccessibilityNodeInfosByText(filter.fiterText());if (nodeList == null || nodeList.isEmpty()) {return null;}AccessibilityNodeInfo clickNode = null;for (AccessibilityNodeInfo nodeInfo : nodeList) {if (filter.filter(nodeInfo)) {clickNode = nodeInfo;break;}}return clickNode;}public static AccessibilityNodeInfo findNodeByFilter(AccessibilityNodeInfo root, NodeIdFilter filter) {if (root == null || filter == null || StringUtil.isEmpty(filter.fiterViewId())) {return null;}List nodeList = root.findAccessibilityNodeInfosByViewId(filter.fiterViewId());if (nodeList == null || nodeList.isEmpty()) {return null;}AccessibilityNodeInfo clickNode = null;for (AccessibilityNodeInfo nodeInfo : nodeList) {if (filter.filter(nodeInfo)) {clickNode = nodeInfo;break;}}return clickNode;}public static AccessibilityNodeInfo findNodeByText(AccessibilityNodeInfo root, String text) {if (root == null || StringUtil.isEmpty(text)) {return null;}List nodeList = root.findAccessibilityNodeInfosByText(text);if (nodeList == null || nodeList.isEmpty()) {return null;}AccessibilityNodeInfo clickNode = null;for (AccessibilityNodeInfo nodeInfo : nodeList) {boolean eqText = nodeInfo.getText() != null && nodeInfo.getText().toString().equals(text);boolean eqDesc = nodeInfo.getContentDescription() != null && nodeInfo.getContentDescription().toString().equals(text);if (eqText || eqDesc) {clickNode = nodeInfo;break;}}return clickNode;}public static AccessibilityNodeInfo findNodeContainsText(AccessibilityNodeInfo root, String text) {if (root == null || StringUtil.isEmpty(text)) {return null;}List nodeList = root.findAccessibilityNodeInfosByText(text);if (nodeList == null || nodeList.isEmpty()) {return null;}AccessibilityNodeInfo clickNode = null;for (AccessibilityNodeInfo nodeInfo : nodeList) {boolean eqText = nodeInfo.getText() != null && nodeInfo.getText().toString().contains(text);boolean eqDesc = nodeInfo.getContentDescription() != null && nodeInfo.getContentDescription().toString().contains(text);if (eqText || eqDesc) {clickNode = nodeInfo;break;}}return clickNode;}public static boolean findNodeByTextAndClick(AccessibilityNodeInfo root, String text) {if (root == null || StringUtil.isEmpty(text)) {return false;}List nodeList = root.findAccessibilityNodeInfosByText(text);if (nodeList == null || nodeList.isEmpty()) {return false;}AccessibilityNodeInfo clickNode = null;for (AccessibilityNodeInfo nodeInfo : nodeList) {boolean eqText = nodeInfo.getText() != null && nodeInfo.getText().toString().equals(text);boolean eqDesc = nodeInfo.getContentDescription() != null && nodeInfo.getContentDescription().toString().equals(text);if (eqText || eqDesc) {clickNode = nodeInfo;break;}}return performClick(clickNode);}public static boolean findNodeByIdAndClick(AccessibilityNodeInfo root, String id) {if (root == null || StringUtil.isEmpty(id)) {return false;}List nodeList = root.findAccessibilityNodeInfosByViewId(id);if (nodeList == null || nodeList.isEmpty()) {return false;}return performClick(nodeList.get(0));}public static boolean findNodeContainsTextAndClick(AccessibilityNodeInfo root, String text) {if (root == null || StringUtil.isEmpty(text)) {return false;}List nodeList = root.findAccessibilityNodeInfosByText(text);if (nodeList == null || nodeList.isEmpty()) {return false;}AccessibilityNodeInfo clickNode = null;for (AccessibilityNodeInfo nodeInfo : nodeList) {boolean eqText = nodeInfo.getText() != null && nodeInfo.getText().toString().contains(text);boolean eqDesc = nodeInfo.getContentDescription() != null && nodeInfo.getContentDescription().toString().contains(text);if (eqText || eqDesc) {clickNode = nodeInfo;break;}}Log.i(TAG, "点击:"+text+"!");return performClick(clickNode);}public static boolean findNodeByIdTextAndClick(AccessibilityNodeInfo root, String id, String text, boolean isNewPage) {AccessibilityNodeInfo clickNode = findNodeByIdAndText(root, id, text);if (clickNode == null) {return false;}return performClick(clickNode);}public static boolean findNodeByIdClassAndClick(AccessibilityNodeInfo root, String id, String className, boolean isNewPage) {AccessibilityNodeInfo clickNode = findNodeByIdAndClassName(root, id, className);if (clickNode == null) {return false;}return performClick(clickNode);}public static AccessibilityNodeInfo findNodeByIdAndClassName(AccessibilityNodeInfo root, String id, String className) {if (root == null) {return null;}List idNodeInfoList = root.findAccessibilityNodeInfosByViewId(id);if (idNodeInfoList == null || idNodeInfoList.isEmpty()) {return null;}for (int i = 0; i < idNodeInfoList.size(); i++) {AccessibilityNodeInfo nodeInfo = idNodeInfoList.get(i);if (nodeInfo == null) {continue;}//根据className过滤if (!StringUtil.isEmpty(className)) {if (className.equals(nodeInfo.getClassName())) {return nodeInfo;}}}return null;}public static AccessibilityNodeInfo findNodeByTextAndClass(AccessibilityNodeInfo root, String text, String clazz) {if (root == null) {return null;}List idNodeInfoList = root.findAccessibilityNodeInfosByText(text);if (idNodeInfoList == null || idNodeInfoList.isEmpty()) {return null;}AccessibilityNodeInfo clickNode = null;for (int i = 0; i < idNodeInfoList.size(); i++) {AccessibilityNodeInfo nodeInfo = idNodeInfoList.get(i);if (nodeInfo == null) {continue;}//根据class过滤if (!StringUtil.isEmpty(clazz)) {if (clazz.equals(nodeInfo.getClassName().toString())) {clickNode = nodeInfo;break;}}}if (clickNode == null) {return null;}return clickNode;}public static AccessibilityNodeInfo findNodeByIdAndText(AccessibilityNodeInfo root, String id, String text) {if (root == null) {return null;}List idNodeInfoList = root.findAccessibilityNodeInfosByViewId(id);if (idNodeInfoList == null || idNodeInfoList.isEmpty()) {return null;}AccessibilityNodeInfo clickNode = null;for (int i = 0; i < idNodeInfoList.size(); i++) {AccessibilityNodeInfo nodeInfo = idNodeInfoList.get(i);if (nodeInfo == null) {continue;}//根据text过滤if (!StringUtil.isEmpty(nodeInfo.getText())&& !StringUtil.isEmpty(text)) {if (text.equals(nodeInfo.getText())) {clickNode = nodeInfo;break;}}}if (clickNode == null) {return null;}return clickNode;}/*** @param root* @param id* @param className* @return*/public static List findNodeByIdAndClassNameList(AccessibilityNodeInfo root, String id, String className) {if (root == null) {return null;}List resultList = new ArrayList<>();List idNodeInfoList = root.findAccessibilityNodeInfosByViewId(id);if (idNodeInfoList == null || idNodeInfoList.isEmpty()) {return null;}for (int i = 0; i < idNodeInfoList.size(); i++) {AccessibilityNodeInfo nodeInfo = idNodeInfoList.get(i);if (nodeInfo == null) {continue;}//根据className过滤if (!StringUtil.isEmpty(className)) {if (className.equals(nodeInfo.getClassName())) {resultList.add(nodeInfo);}}}return resultList;}public static AccessibilityNodeInfo findNodeByClass(AccessibilityNodeInfo root, String className) {if (TextUtils.isEmpty(className) || root == null) {return null;}int childCount = root.getChildCount();for (int i = 0; i < childCount; i++) {AccessibilityNodeInfo rootChild = root.getChild(i);if (rootChild != null) {if (className.equals(rootChild.getClassName().toString().trim())) {return rootChild;}}}return null;}public static List findNodeByClassList(AccessibilityNodeInfo root, String className) {List list = new ArrayList<>();if (TextUtils.isEmpty(className) || root == null) {return Collections.EMPTY_LIST;}int childCount = root.getChildCount();for (int i = 0; i < childCount; i++) {AccessibilityNodeInfo rootChild = root.getChild(i);if (rootChild != null) {if (className.equals(rootChild.getClassName().toString().trim())) {list.add(rootChild);}}}return list;}public static List traverseNodefilterByDesc(AccessibilityNodeInfo root, final String desc) {if (TextUtils.isEmpty(desc) || root == null) {return null;}List list = new ArrayList<>();traverseNodeClassToList(root, list, new NodeFilter() {@Overridepublic boolean filter(AccessibilityNodeInfo node) {return node.getContentDescription() != null && desc.equals(node.getContentDescription().toString());}});return list;}public static List traverseNodeByClassName(AccessibilityNodeInfo root, final String className) {if (TextUtils.isEmpty(className) || root == null) {return Collections.EMPTY_LIST;}List list = new ArrayList<>();traverseNodeClassToList(root, list, new NodeFilter() {@Overridepublic boolean filter(AccessibilityNodeInfo node) {return node.getClassName() != null && className.equals(node.getClassName().toString());}});return list;}private static void traverseNodeClassToList(AccessibilityNodeInfo node, List list, NodeFilter filter) {if (node == null || node.getChildCount() == 0) {return;}for (int i = 0; i < node.getChildCount(); i++) {AccessibilityNodeInfo child = node.getChild(i);if (child != null) {if (filter.filter(child)) {list.add(child);}if (child.getChildCount() > 0) {traverseNodeClassToList(child, list, filter);}}}}public interface NodeFilter {boolean filter(AccessibilityNodeInfo node);}public interface NodeTextFilter extends NodeFilter {String fiterText();}public interface NodeIdFilter extends NodeFilter {String fiterViewId();}
}复制代码 在部分 Root 的手机,我们可以通过辅助权限找到该节点在屏幕上的位置,并获取中心点:
Rect r = new Rect();
node.getBoundsInScreen(r);
if (r.centerX() > ScreenUtils.getScreenWidth(OttUtil.get().getApp())|| r.centerY() > ScreenUtils.getScreenHeight(OttUtil.get().getApp())|| r.centerX() <= 0|| r.centerY() <= 0) {return false;
}
String cmd = String.format("input tap %d %d", r.centerX(), r.centerY());
复制代码 再去执行相关操作:
ShellUtils.CommandResult commandResult = ShellUtils.execCmd(cmd, true);
复制代码 更多技术分享,请加微信公众号——码农茅草屋:
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
