如何编写基于Android的AccessibilityService的自动打卡
时间:2022-04-22
本文章向大家介绍如何编写基于Android的AccessibilityService的自动打卡,主要内容包括第一节 缘由与准备、最近有时间空闲,闲来无事,想到使用钉钉打卡有时会迟到,所以周末的时候去看了相关网上资料,做了个demo。、材料:定时器,AccessibilityService、加工方案:使用定时器在签到签退期间内自启,通过AccessibilityService模拟点击:分为签到与签退两种情况。、签到正常流程:工作-》考勤打卡-》(判断是否弹出窗口-是:我知道了否跳过)-》签到。、签到迟到流程:工作-》考勤打卡-》迟到打卡。、签退正常流程:工作-》考勤打卡-》签退。、工艺难点:签到页中嵌套的是基于WebView的页面,一开始以为无法获取节点,想到通过屏幕中的位置去点击那块区域,查看官方文档发现有个方法getAccessibilityNodeProvider(),得到虚拟节点进行模拟点击。、第二节:热火朝天、技能点:判断应用状态,启动指定应用,自定义AccessibilityService控制模拟点击流程、判断应用状态:、启动指定应用:、自定义AccessibilityService控制模拟点击流程:、1.获取点击控件对象(可以通过文本不推荐通过资源id方式点击)、工作布局的资源ID:、考勤打卡布局的资源ID(这个id是动态生成的8个都是):、考勤打卡布局的资源ID:、2窗口发生变化处理:、3后续处理:、发现考勤打卡页面是基于webview的h5页面,因此暂时没有好的方法,获取webview对象,以及获取虚拟节点。、不过如果可以获取到窗口下的webview对象,那么是可以获取页面的虚拟节点,进行模拟点击。打卡是没问题的,由于现在极速打卡的功能,打开应用自动签到。、参考:、基本概念、基础应用、原理机制和需要注意的事项等,并结合实例形式分析了其使用技巧,希望通过本文能帮助到大家理解应用这部分内容。
第一节 缘由与准备
最近有时间空闲,闲来无事,想到使用钉钉打卡有时会迟到,所以周末的时候去看了相关网上资料,做了个demo。
材料:定时器,AccessibilityService
加工方案:使用定时器在签到签退期间内自启,通过AccessibilityService模拟点击:分为签到与签退两种情况。
签到正常流程:工作-》考勤打卡-》(判断是否弹出窗口-是:我知道了否跳过)-》签到。
签到迟到流程:工作-》考勤打卡-》迟到打卡。
签退正常流程:工作-》考勤打卡-》签退。
工艺难点:签到页中嵌套的是基于WebView的页面,一开始以为无法获取节点,想到通过屏幕中的位置去点击那块区域,查看官方文档发现有个方法getAccessibilityNodeProvider(),得到虚拟节点进行模拟点击。
第二节:热火朝天
技能点:判断应用状态,启动指定应用,自定义AccessibilityService控制模拟点击流程
判断应用状态:
public static boolean isBackground(Context context) {
ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningAppProcessInfo> appProcesses = activityManager.getRunningAppProcesses();
for (ActivityManager.RunningAppProcessInfo appProcess : appProcesses) {
if (appProcess.processName.equals(context.getPackageName())) {
if (appProcess.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND) {
Log.i("后台", appProcess.processName);
return true;
}else{
Log.i("前台", appProcess.processName);
return false;
}
}
}
return false;
}
启动指定应用:
public static void doStartApplicationWithPackageName(Context context, String packagename) {
// 通过包名获取此APP详细信息,包括Activities、services、versioncode、name等等
PackageInfo packageinfo = null;
try {
packageinfo = context.getPackageManager().getPackageInfo(packagename, 0);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
if (packageinfo == null) {
return;
}
// 创建一个类别为CATEGORY_LAUNCHER的该包名的Intent
Intent resolveIntent = new Intent(Intent.ACTION_MAIN, null);
resolveIntent.addCategory(Intent.CATEGORY_LAUNCHER);
resolveIntent.setPackage(packageinfo.packageName);
// 通过getPackageManager()的queryIntentActivities方法遍历
List<ResolveInfo> resolveinfoList = context.getPackageManager()
.queryIntentActivities(resolveIntent, 0);
ResolveInfo resolveinfo = resolveinfoList.iterator().next();
if (resolveinfo != null) {
// packagename = 参数packname
String packageName = resolveinfo.activityInfo.packageName;
// 这个就是我们要找的该APP的LAUNCHER的Activity[组织形式:packagename.mainActivityname]
String className = resolveinfo.activityInfo.name;
// LAUNCHER Intent
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
// 设置ComponentName参数1:packagename参数2:MainActivity路径
ComponentName cn = new ComponentName(packageName, className);
intent.setComponent(cn);
context.startActivity(intent);
}
}
自定义AccessibilityService控制模拟点击流程:
1.获取点击控件对象(可以通过文本不推荐通过资源id方式点击)
工作布局的资源ID:
考勤打卡布局的资源ID(这个id是动态生成的8个都是):
考勤打卡布局的资源ID:
2窗口发生变化处理:
@Override
public void onAccessibilityEvent(AccessibilityEvent accessibilityEvent) {
if(isFinish){
return;
}
AccessibilityNodeInfo nodeInfo = getRootInActiveWindow();
if(nodeInfo == null) {
Log.d(TAG, "rootWindow为空");
return ;
}
switch (accessibilityEvent.getEventType()){
//当窗口的状态发生改变时
case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED:
if (index==1) {
//主页点击工作
clickHome(nodeInfo,accessibilityEvent);
Log.d(TAG,"工作");
} else if (index==2) {
//工作tab点击考勤打卡
clickKaoQing(nodeInfo,accessibilityEvent);
Log.d(TAG,"点击考勤打卡");
} else if (index==3) {
//开始打卡
clickKaoQingBtn(nodeInfo,accessibilityEvent);
Log.d(TAG,"打卡");
}
break;
}
}
3后续处理:
发现考勤打卡页面是基于webview的h5页面,因此暂时没有好的方法,获取webview对象,以及获取虚拟节点。
不过如果可以获取到窗口下的webview对象,那么是可以获取页面的虚拟节点,进行模拟点击。打卡是没问题的,由于现在极速打卡的功能,打开应用自动签到。
参考:
>Android AccessibilityNodeProvider官方文档
>基于AccessibilityService制作的钉钉自动签到程序
- JS游戏开发 可移动地图的实现
- Java面试系列-多线程
- pymongo.errors:Sort operation used more than the maximum 33554432 bytes of RAM. Add an index,
- PG学习初体验--源码安装和简单命令(r8笔记第97天)
- Pymongo: TypeError: if no direction is specified, key_or_list must be an instance of list
- Java面试系列19-Struts2
- JS游戏开发,让你的静态人物动起来(来自网路)
- Golang语言websocket源码
- 社团划分——Fast Unfolding算法
- 【PSU】AIX 11g RAC自动打GI PSU5
- 详解自动识别验证码,LSTM大显身手
- 智能算法——PageRank
- 【Go 语言社区】Golang 可变参数的使用
- 【Go 语言社区】Golang源码解读之map
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- 蓝牙芯片----BK3431开发笔记------基本外部驱动应用(3)
- .net core 利用中间件处理常见的网站功能 包括 session、routers、重定向、重写和文件下载
- 蓝牙芯片----BK3431开发笔记------RW stack中添加自定义服务教程(4)
- 图像简单处理
- 蓝牙---BLE GATT介绍
- Access数据库密码破解 C#
- 没啥用,更换注册表信息使webbrower选择适合的版本
- linux下分割和合并压缩包
- 编译.net .net Core程序 代码,仅做备份
- js删除数组对象中符合条件的数据
- .net core webapi jwt 更为清爽的认证 ,续期很简单(2)
- 手把手教你写一个windows服务 【基于.net】 附实用小工具{注册服务/开启服务/停止服务/删除服务}
- 一网打尽枚举操作 .net core
- Jenkins 发布.net core 程序,服务端无法下载nuget包的解决方法 error NU1102: 找不到版本为 (>= 3.1.6) 的包
- NET Core Kestrel部署HTTPS 一个服务器绑一个证书 一个服务器绑多个证书