因蚂蚁森林界面UI更新,本方法原理已失效

于2020年11月30日 更新

应用界面



前言

最初,我有一个朋友问我能不能有办法监听到另一个App界面的内容,一旦有特定的消息出现就提醒用户,就这样,我接触到了AccessibityService。这个项目很好写,所以很快就实现了。主要是那个app结点都能直接获取到,也都能点击。有一天,我收蚂蚁森林能量,好友比较多,就在想,我能不能写一个基于AccessibilityService的自动收集能量的应用,造福一下懒人


运行效果

APP已放在末尾,欢迎大家测试


所用技术

AccessibilityService + 多线程 + 手势


项目开始

实现逻辑

说明
所有判断页面是否加载完成,用户名是否匹配的操作都是在开辟的子线程(图中橙色部分)中进行,主线程的MainHandler 接收来自子线程发送的消息,进行处理。


一些问题的解决

一、怎么获得webView中的结点信息

二、怎么判断webView加载完成了

三、怎么点击按钮


第一个问题,webView就像浏览器一样,里面的内容是网页的内容。

在webView中,所有的通过搜索获取结点List的方法失效了,但是可以通过不停地得到子节点、判断、得到子节点、判断的方法粗略的得到结点信息。

可以借助安卓的 uiautomatorviewer 工具查看结点树,但是这里的结点树也可能和实际运行的有点点出入,主要是webview 加载成功和不成功 之间有些变化,其他的结点结构是固定的,所以可取。

我是用dfs的方式得到webView的结点

private AccessibilityNodeInfo returnWebView(AccessibilityNodeInfo nowNode){if(nowNode==null) return null;if(nowNode.getClassName().toString().equals("android.webkit.WebView")){return nowNode;}if(nowNode.getChildCount()==0) return null;int size = nowNode.getChildCount();AccessibilityNodeInfo webViewNode = null;for(int i=0;i<size;i++){webViewNode = returnWebView(nowNode.getChild(i));if(webViewNode!=null) return webViewNode;}return null;
}

UIautomatorviewer具体怎么使用网上有很多博客,就不说了


第二个问题,怎么判断webView是否加载完成。

老实说,没有特别好的办法。你看一般的浏览器加载网页,有些时候加载的快,有些时候加载得慢,网页上很多东西的加载都是异步的。我很难准确的找到一个判定条件说网页绝对加载完成了。我用的办法是子线程判断关键信息是否加载完成了,只要我要点击的按钮加载完成了,就判定webView加载完成了。

private void LoadingForest(){//判定已载入的规则:只包含能量的view节点子孩子数大于等于4new Thread(new Runnable() {@Overridepublic void run() {debug("加载蚂蚁森林...");Message message = Message.obtain();int MaxCount = MAX_REQUEST_TIME;WebViewNode = null;while(MaxCount > 0 ){MaxCount--;sleep(500);rootNode = getRootInActiveWindow();//Frameif(rootNode==null || rootNode.getChildCount()==0) continue;WebViewNode = returnWebView(rootNode);if(WebViewNode==null || WebViewNode.getChildCount()==0) continue;nowNode = WebViewNode.getChild(0);if(nowNode==null || nowNode.getChildCount()==0) continue;nowNode = nowNode.getChild(0);if (nowNode==null || nowNode.getChildCount()<3) continue;nowNode = nowNode.getChild(2);
//                        dfs(nowNode);if(nowNode.getChildCount()>=4) break;}if(MaxCount==0){message.what = -1;}else{message.what = 6;}MainHandler.sendMessage(message);}}).start();
}

第三个问题 ,怎么点击

通过手势,可以实现滑动 和点击

滑动

private void scroll(){new Thread(new Runnable() {@Overridepublic void run() {int sx = (nowUserEntrance.left+nowUserEntrance.right)>>1;int sy = nowUserEntrance.bottom;int ey = nowUserEntrance.top-21;dispatchGestureScroll(2,sx,sy,sx,ey);sleep(100);Message message = Message.obtain();message.what = 10;MainHandler.sendMessage(message);}}).start();
}private void dispatchGestureScroll(final int flag, int sx, int sy,int ex,int ey) {//        debug("sx:"+sx+"sy:"+sy+"ex:"+ex+"ey:"+ey);GestureDescription.Builder builder = new GestureDescription.Builder();Path p = new Path();p.moveTo(sx, sy);p.lineTo(ex, ey);builder.addStroke(new GestureDescription.StrokeDescription(p, 0L, 100L));GestureDescription gesture = builder.build();dispatchGesture(gesture, new AccessibilityService.GestureResultCallback() {@Overridepublic void onCompleted(GestureDescription gestureDescription) {super.onCompleted(gestureDescription);Log.d(TAG, flag+"onCompleted: 完成..........");}@Overridepublic void onCancelled(GestureDescription gestureDescription) {super.onCancelled(gestureDescription);Log.d(TAG, flag+"onCompleted: 取消..........");}}, null);
}

点击

/*** 模拟点击事件* @param flag 点击的控件类型(1 能量) (0 用户入口)* @param x 横坐标* @param y 纵坐标*/
private boolean dispatchGestureView(final int flag, int x, int y) {boolean res = false;GestureDescription.Builder builder = new GestureDescription.Builder();Path p = new Path();p.moveTo(x, y);p.lineTo(x, y);builder.addStroke(new GestureDescription.StrokeDescription(p, 0L, 100L));GestureDescription gesture = builder.build();Log.d("","点击了位置"+"("+x+","+y+")");sleep(200);res = dispatchGesture(gesture, new GestureResultCallback(){}, null);return res;
}

关于点击

为什么不直接用

Node.performAction(AccessibilityNodeIndo.CLICK)

来点击呢。呵,最初我就是这么做的,而且UIautomatorviewer也显示该按钮的clickable是true 但是就是点不了呀,后来研究了一下,发现安卓的按钮还有

btn.setOnTouchListener(new View.OnTouchListener() {@Overridepublic boolean onTouch(View v, MotionEvent event) {//点击事件return false;}
});

来实现点击事件,注意这里的return false ,返回false的时候,点击按钮onClick和onTouch 都会执行,而当返回true的时候,只有onTouch会执行。所以我打算用OnTouch来实现点击事件,蚂蚁森林能给我的只有按钮的坐标,通过给指定坐标的View分发TouchEvent

/*** 模拟点击事件* @param x 横坐标* @param y 纵坐标*/
private void onTouchClick(int x,int y){final long downTime = SystemClock.uptimeMillis();View b1 = findViewById(R.id.button);Log.d("","onTouchClick");MotionEvent downEvent = MotionEvent.obtain(downTime,downTime, MotionEvent.ACTION_DOWN,x,y,0);MotionEvent upEvent = MotionEvent.obtain(downTime,SystemClock.uptimeMillis(), MotionEvent.ACTION_UP,x,y,0);b1.dispatchTouchEvent(downEvent);b1.dispatchTouchEvent(upEvent);downEvent.recycle();upEvent.recycle();
}

理论上可以通过坐标来获取view,网上有方法。但是我试了很多办法也获取不到第三方的AppDecorView,因为连第三方的Activity实例都获取不到。我当时卡了好久,差点想放弃这个项目,因为连点击都不能实现还怎么收能量。。

幸好,后来发现了手势也可以实现点击,才使得前面的努力没有白费。

想要了解更多,您也可以看看续篇

蚂蚁森林自动收集能量(续)

安卓AccessibilityService实现蚂蚁森林自动收集能量 最新 多线程 + 手势 + 深搜webView相关推荐

  1. Python 蚂蚁森林自动收集能量脚本

    不需要root权限,不需要xposed框架支持 演示视频 加好友一起偷能量吗(疯狂暗示) 1962976634@qq.com 1.原理 使用adb指令模拟操作屏幕 2.准备 2.1 安装python3 ...

  2. 如何使用 AccessibilityService 实现蚂蚁森林自动收取能量,无需Root,无需连接电脑

    如何使用 AccessibilityService 实现蚂蚁森林自动收取能量,无需Root,无需连接电脑 AccessibilityService 设计初衷在于帮助残障用户使用android设备和应用 ...

  3. auto.js蚂蚁森林收能量

    auto.js蚂蚁森林收能量 在网上看了一些自动收能量的脚本 写了一个脚本 使用AutoJs运行 AutoJS下载地址 :here 运行步骤如下: 1.解锁(点亮屏幕,切换到输入密码界面,输入密码) ...

  4. iOS逆向-手把手教你写支付宝蚂蚁森林收集能量助手

    iOS逆向-手把手教你写支付宝蚂蚁森林收集能量助手 前言 发现iOS支付宝逆向的分析并不多,蚂蚁森林基于H5应用 套着UIWebView 基本也没这类JS和原生交互分析的帖子,就拿此练手吧 作技术分享 ...

  5. 模拟蚂蚁森林的能量产生过程

    模拟蚂蚁森林的能量产生过程 for i in range(100):print(""" 能量查询请输入能量来源!退出程序请输入0 能量来源如下: 生活缴费.行走捐.共享单 ...

  6. Python+uiautomator2定时偷取蚂蚁森林好友能量

    文章目录 前言 一.系统环境 二.使用步骤 1.引入库 2.电脑连接手机并打开支付宝软件 3.aircv图片识别 4.收取自己的能量 5.跳转到好友能量 6.收取好友能量 7.能量雨代码求助 三.完整 ...

  7. iphone快捷指令蚂蚁森林能量_iOS逆向-手把手教你写支付宝蚂蚁森林收集能量助手...

    iOS逆向-手把手教你写支付宝蚂蚁森林收集能量助手 前言 发现iOS支付宝逆向的分析并不多,蚂蚁森林基于H5应用 套着UIWebView 基本也没这类JS和原生交互分析的帖子,就拿此练手吧 作技术分享 ...

  8. 蚂蚁森林给别人浇水能量不足怎么解决 蚂蚁森林增加能量方法

    现在支付宝中已经退出了很多公益小游戏,比如蚂蚁庄园和蚂蚁森林了.玩过蚂蚁森林中的朋友们都知道在森林中可以给别人浇水,蚂蚁森林给别人浇水能量不足怎么解决 蚂蚁森林增加能量方法,但是如果遇到了浇水能量不足 ...

  9. AccessibilityService 进行蚂蚁森林能量收集 demo

    1. 原理 基于 AccessibilityService 模拟辅助功能 2. Demo下载 https://github.com/sufadi/AccessibilityServiceMonitor ...

最新文章

  1. HSV的数据结构各分量H S V的直观理解其实就是对应图片位置的的像素一一对应的矩阵表示
  2. linux命令之查看动态库符号-nm
  3. Linux——进程控制(总结)
  4. explicit关键字详解(C++ )
  5. 数据结构与算法--二叉树实现原理
  6. Android入门(12)| 数据持久化
  7. python复制代码会被发现吗,我发现了一个记忆代码片段,我想知道它在复制。复制...
  8. C/C++ 中的指针
  9. gcc和arm-linux-gcc区别
  10. html5d调用百度语音,易语言调用百度语音平台实现文字转换语音功能的代码
  11. 注释驱动的 Spring cache 缓存介绍
  12. README.md怎么写比较好
  13. Android中ListView复用导致布局错乱的解决方案
  14. “站长也疯狂,开车盛宴”——如何选择运维产品
  15. android httpclient 设置超时
  16. 计算机 在电厂的应用,计算机自动控制系统在火电厂中的应用
  17. 数学建模学习:因子分析
  18. ORB-SLAM2安装以及遇到问题
  19. 友情链接对网站优化有什么作用
  20. matlab编写多目标测试函数SCH, ZDT, MOP, DTLZ

热门文章

  1. BLE蓝牙模块的应用场景介绍
  2. Codeforces Round #832 (Div. 2)
  3. 解析未来教育机器人的远大市场前景
  4. 【兼容性测试】浏览器的兼容性测试从哪些方面入手?
  5. 鲜花速递的APP创意营销
  6. c语言fwrite作用,C语言fread和fwrite的用法详解(以数据块的形式读写文件)
  7. C语言#pragma使用方法
  8. 使用areaDetector和medm打开海康威视MV-CA004-10GM相机
  9. GreenDao教程(3):一对一,一对多,多对多
  10. 社会化媒体的特性和分类