AutoxJS脚本保姆级教程

news2024/11/24 20:53:39

目录

引言

准备工作

脚本开发

邮件提示(不使用邮件推送的可以跳过这步)

节假日判断(不需要判断节假日的可以跳过)

问题及技巧归总

JS语法错误:软件更新

按钮或组件无法找到

使用定时器等待组件出现

root环境下才能用shell的root模式

主线程堵塞问题

全局日志记录

巧用id或text

Tasker和AutoXjs自启问题

效果展示

写在最后

注意:该脚本请勿用于商用,侵删

相关代码


引言

2021年的时候分享了一个自动化脚本的文章,介绍了使用Tasker+Autojs实现自动化操作。现在公司更换了新的考勤软件,脚本也做了许多期迭代,所以更新了一版脚本分享的文章,并记录一些遇到的问题

准备工作

同这篇文章:

  • 目标App换成北sen
  • 电脑+VSCode
  • 安卓模拟器推荐个资源网站雷电模拟器 v4.0.83 / v5.0.60 绿色版 / 雷电模拟器9 v9.0.50.0 绿色版-六音
  • AutoX.js
  • Tasker,中文站,原网站

脚本开发

开发调试的过程可以参照这篇文章

这里直接贴出脚本

/*
 * @Author: Hunter
 * @Date: 2023-07-10 17:46:35
 * @LastEditTime: 2023-07-18 14:56:28
 * @LastEditors: Hunter
 * @Description:
 * @FilePath: \北sen\main.js
 * 可以输入预定的版权声明、个性签名、空行等
 */
var appName = "北森iTalent", //app名
  packageName = getPackageName(appName), //包名
  roundTimer = 60 * 1000, //超时定时器间隔60秒
  randomTimer = parseInt(Math.random() * 5 * 60 * 1000), //随机定时器0-5分钟(精确到毫秒)
  maxRetryCount = 3, //重试打卡次数
  useEmail = true, // 是否发送邮件
  useDate = true, // 是否检查节假日
  cardMenuBtn = () => id("mIVBottomCenter").findOne().bounds(), //打卡界面菜单
  cardViewBtn = () => text("签到").findOne().bounds(), //打卡界面按钮
  positionBtn = () => id("tv_sign_company_status").text("办公地点"), //定位成功按钮
  cardTakeBtn = () => id("rlt_sign_click").findOne(); //打卡按钮
let logs = ``;
// 日志记录
const __log = function () {
  logs += `
  ${new Date()}:${JSON.stringify(arguments)}
  `;
  toast(JSON.stringify(arguments));
  console.trace.apply(null, arguments);
};
const getLog = () => logs;
const mailApi = "https://api.emailjs.com/api/v1.0/email/send", //邮箱请求地址
  mailConfig = {
    user_id: "user_xxxxxxxxxxxxxxxxxxxxxxhj",
    service_id: "sexxxxxxxmk",
    template_id: "templxxxxxxxxxxmn",
    accessToken: "8xxxxxxxxxxxxxxxxxxxxxxxxxxx9",
    template_params: {
      title: "自动打卡通知",
      content: `打卡成功
      日志:${getLog()}
      `,
      email: "xxxxxxxxx@qq.com",// 接收消息的邮箱
    },
  }, //邮箱配置,需要去emailjs官网申请api,每月免费200次
  dateApi = "http://api.tianapi.com/jiejiari/index", //节假日接口
  dateConfig = {
    key: "9dxxxxxxxxxxxxxxxxxx93",
    date: formatDate(new Date()),
  }; //在天行数据申请节假日api(每天免费查询100次):https://www.tianapi.com/
__log("随机延迟时间:", randomTimer);
if (useDate) {
  // 检查是否开启节假日检测
  checkDateIsWork(dateConfig, function (res) {
    if (res.newslist[0].isnotwork) {
      sendEmail(setNewMessage("今天是法定节假日,无需打卡"));
      exitApp(true);
      return;
    }
    exitApp(false);
    setTimeout(init, randomTimer);
  });
} else {
  exitApp(false);
  setTimeout(init, randomTimer);
}

function init() {
  if (!!maxRetryCount) {
    __log("剩余重试次数" + maxRetryCount);
    timeOutMsg();
    maxRetryCount--;
    startProgram();
    return;
  }
  exitApp(true);
}
//开启应用
function startProgram() {
  __log("launchApp:" + appName, launchApp(appName)); //打开app
  waitForPackage(packageName); //等待app打开
  __log("launchAppSuccess", packageName);
  openCardView();
}
//首页--->打卡页
function openCardView() {
  var cardMenuButton = cardMenuBtn();
  __log(
    "打卡界面菜单",
    click(cardMenuButton.centerX(), cardMenuButton.centerY())
  );
  var cardButton = cardViewBtn();
  __log("进入打卡界面", click(cardButton.centerX(), cardButton.centerY() - 10));
  takeCard();
}
//打卡
function takeCard() {
  __log("等待定位");
  positionBtn().waitFor();
  __log("定位成功");
  __log("点击打卡按钮", cardTakeBtn().click());
  sendSuccEmail();
  exitApp(true);
}
// 打卡成功发邮件
function sendSuccEmail() {
  const _mailConfig = mailConfig;
  _mailConfig.template_params.content += getLog();
  __log("发送邮件", sendEmail(_mailConfig));
}
//退出程序
function exitApp(exitJs, fn) {
  shell("am force-stop " + packageName, true);
  fn && fn();
  exitJs && exit();
}

// 程序超时处理
function timeOutMsg() {
  threads.start(function () {
    //在新线程执行的代码
    setTimeout(function () {
      sendEmail(setNewMessage("自动打卡超时,正在重试"));
      exitApp(false, init);
    }, roundTimer);
  });
}
// 发送邮件api
function sendEmail(params) {
  if (useEmail) {
    var res = http.post(mailApi, params || mailConfig, {
      contentType: "application/json",
    });
    return res;
  }
}
// 节假日api请求
function checkDateIsWork(params, fn) {
  var res = http.post(dateApi, params || dateConfig).body.json();

  if (res.code === 200) {
    fn(res);
    return;
  }
  __log(res);
  sendEmail(setNewMessage(res.msg));
}
// 修改默认邮件提示信息
function setNewMessage(msg) {
  var _mailConfig = simpleCloneObj(mailConfig, {
    contentType: "application/json",
  });
  _mailConfig.template_params.content = `${msg + new Date()}
  日志:${getLog()}
  `;
  return _mailConfig;
}

//日期格式转换 YYYY-MM-DD
function formatDate(date) {
  var y = date.getFullYear();
  var m = date.getMonth() + 1;
  m = m < 10 ? "0" + m : m;
  var d = date.getDate();
  d = d < 10 ? "0" + d : d;
  return y + "-" + m + "-" + d;
}

// 简单的深复制
function simpleCloneObj(target) {
  return typeof target === "object" && JSON.parse(JSON.stringify(target));
}

邮件提示(不使用邮件推送的可以跳过这步

在代码中可以配置邮件通知的选项,或者使用useEmail来控制是否发送邮件,此外还可以参照这篇文章,使用自己的邮件推送服务

这里以emailjs为例,每个月可以调用200次。

首先绑定自己的邮件服务

接着同样参照这篇文章,配置一下邮箱的选项用于邮件推送

然后是邮件模板的配置,代码中的template_params请求参数与模板配置对应

最后是emailjs的一些id

  • service_id

  • template_id

  • user_id和accessToken

 

将这些配置项放在代码中就可以使用了

节假日判断(不需要判断节假日的可以跳过

为了计算当前日期是否是节假日,我调用了一个天行的公共api,当然也可以通过将代码中的useDate设置为false关闭该功能

注册并实名后搜索节假日

点击开通,每天免费使用100次

问题及技巧归总

在上一版本脚本迭代中遇到了以下问题以及autoxjs中的一些使用技巧,供参考

JS语法错误:软件更新

旧版本的autojs或AutoXJS可能会提示语法错误,有可能是使用了过于超前的JS语法,建议更新app版本比如字符串模板 ` ${} ` ,const 等

按钮或组件无法找到

按钮无法找到的问题出现在北sen软件中,在*人薪事中可以使用id或者text的方式找到并点击组件,但是升级安卓高版本的系统后,组件的clickable为false,可能会出现找不到组件的问题,那就只能通过例如:text("签到").findOne().bounds() 的方式来获取组件的范围,然后通过类似:click(cardButton.centerX(), cardButton.centerY()) 的方式对屏幕进行动态定位点击事件,具体可以参考上面代码中的openCardView函数的两个点击事件

使用定时器等待组件出现

使用setinterval来轮询查询页面组件的clickable是否为true,由于有时使用官方的waitfor失效,所以想到了这个方式,这种方式虽然可以解决问题,不到万不得已不推荐使用,会导致性能差

root环境下才能用shell的root模式

模拟器中需要开启root,手机也需要root才能使用root模式执行sh

主线程堵塞问题

我在脚本后续迭代中加入了主线程超时处理,超过一分钟我就会重启脚本和软件,具体参考timeOutMsg函数

全局日志记录

好的程序必定离不开日志监控及问题定位排查,在__log函数中我封装了全局的日志处理,每步操作都会记录日志信息

巧用id或text

有许多组件没有id选项,所以就只能使用text或者parent等方式取获取组件

Tasker和AutoXjs自启问题

自启问题比较棘手,我使用tasker每天定时启动autojs防止脚本执行,那么如何保证tasker自启呢?使用autojs实现的,说起来很怪,有时会偶发autojs启动了但是却无法接受tasker发的系统广播,此时重启一下autojs就可以解决,具体脚本如下

// 自启tesker,防止开机被kill
var appName = "Tasker", //app名
  packageName = getPackageName(appName); //包名
startProgram();
//开启应用
function startProgram() {
  toast("launchApp:" + appName);
  console.log("launchApp:" + appName, launchApp(appName)); //打开app
  waitForPackage(packageName); //等待app打开
  console.log("launchAppSuccess", packageName);
  toast("launchAppSuccess", packageName);
  exit();
}

效果展示

讲完了这么多,我们参考这个将脚本放在AutoXJS中演示一下

写在最后

本篇文章对以前的自动化脚本的迭代更新做了个梳理,有许多步骤在之前的文章中有,建议先过一遍,除此之外,文章总结了一些在脚本迭代过程中遇到的问题和解决技巧。其中涉及到的问题包括JS语法错误、按钮或组件无法找到、使用定时器等待组件出现、root环境下才能用shell的root模式以及主线程堵塞问题等。同时,文章提供了一些技巧,如巧用id或text获取组件、全局日志记录和Tasker与AutoX.js自启问题的解决方案。

注意:该脚本请勿用于商用,侵删

以上就是文章全部内容了,如果觉得文章不错的话,还请三连支持一下,谢谢!

相关代码

myCode: 基于js的一些小案例或者项目 - Gitee.com

邮件推送服务: 基于 TS+Node+nodemailer 实现一个开箱即用的 Node 邮件推送服务,需要获取邮箱的授权码

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/874746.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Scratch 之 单个角色模糊特效

想给单独一个角色用模糊特效&#xff0c;怎么办&#xff01;&#xff01;&#xff01; 完全不用慌&#xff0c;最近&#xff0c;我做出了超好用的个体模糊特效&#xff0c;用起来超级简单&#xff0c;接下来进入讲解。 1.原理 前几天&#xff0c;我闲来无事&#xff0c;摘下眼镜…

【2023年11月第四版教材】《第4章-信息系统管理之管理要点(第四版新增章节)(第二部分)》

信息系统管理之管理要点&#xff08;第四版新增章节&#xff09;&#xff08;第二部分&#xff09; 2 管理要点2.1 数据管理能力成熟度评估模型DCMM详细表格简要表格 2.2 组织的管理成熟度2.3 能力模型2.4 智能运维能力框架2.5 安全保护等级 2 管理要点 2.1 数据管理能力成熟度…

华为云classroom赋能--Devstar使应用开发无需从零开始

华为云DevStar为开发者提供业界主流框架代码初始化能力&#xff0c;通过GUI、API、CLI等多种方式&#xff0c;将按模板生成框架代码的能力推送至用户桌面。同时基于华为云服务资源、成熟的DevOps开发工具链和面向多场景的众多开发模板&#xff0c;提供一站式创建代码仓、自动生…

js的练习

这里写目录标题 工具代码运行结果 工具 HBuilder X 代码 <!DOCTYPE html> <html><head><meta charset"utf-8"><title></title><script>window.onload function() // 需要在body加载完成之后&#xff0c;才能通过docu…

HCIP BGP小综合

BGP小综合 AS配置AS1AS2 中的小自治系统64512AS2 中的小自治系统64513AS3 测试 首先该实验分成三个AS&#xff0c;AS2里面有联邦&#xff0c;所以配置顺序 要先将IBGP通&#xff0c;然后配置AS1,AS3和联邦 AS配置 AS1 R1 # bgp 1router-id 1.1.1.1peer 12.1.1.2 as-number …

C++ 网络编程项目fastDFS分布式文件系统(二)-redis部分

目录 1. 数据库类型 1.1 基本概念 1.2 关系/非关系型数据库搭配使用 2. Redis 2.1 基本知识点 2.2 redis常用命令 - String类型 - List类型 - Set类型 - SortedSet 类型 - Hash类型 Key 相关的命令 2.3 redis配置文件 2.4 redis数据持久化 3 hiredis的使用 1. 数据…

人类:我觉得1+1=956446,你觉得呢?大模型:啊对对对

大模型太「听话」了怎么办&#xff1f; 大型语言模型&#xff08;LLM&#xff09;的自然语言理解与生成能力一直备受称赞&#xff0c;特别是 ChatGPT 等对话式语言模型能够与人类流畅、自然地进行多轮对话。然而&#xff0c;最近一篇 Google DeepMind 的论文研究发现 LLM 普遍存…

FPGA GTP全网最细讲解 aurora 8b/10b协议OV5640摄像头视频传输 提供2套工程源码和技术支持

目录 1、前言免责声明 2、我这里已有的 GT 高速接口解决方案3、GTP 全网最细解读GTP 基本结构GTP 发送和接收处理流程GTP 的参考时钟GTP 发送接口GTP 接收接口GTP IP核调用和使用 4、设计思路框架OV5640摄像头配置及采集视频数据组包GTP aurora 8b/10b数据对齐视频数据解包图像…

WinCC V7.5 中的C脚本对话框不可见,将编辑窗口移动到可见区域的具体方法

WinCC V7.5 中的C脚本对话框不可见&#xff0c;将编辑窗口移动到可见区域的具体方法 由于 Windows 系统更新或使用不同的显示器&#xff0c;在配置C动作时&#xff0c;有可能会出现C脚本编辑窗口被移动到不可见区域的现象。 由于该窗口无法被关闭&#xff0c;故无法进行进一步…

WebRTC音视频通话-RTC直播本地视频及相册视频文件

WebRTC音视频通话-RTC直播本地视频及相册视频文件 WebRTC音视频通话-RTC直播本地视频文件效果图如下 WebRTC音视频通话-RTC直播本地视频文件时候&#xff0c;用到了AVPlayer、CADisplayLink。 一、通过AVPlayer播放本地视频 AVPlayer是什么&#xff1f; AVPlayer是基于AV…

进程间的通信

进程的通信&#xff0c;光是听概念就知道这是一个非常重要的知识点&#xff0c;但是之前学习的概念其实都无法实现真正意义上的进程间的通信&#xff1a; 子进程调用exit或Exit或_exit&#xff0c;然后父进程通过wait可以知道其状态&#xff0c;这虽然实现了消息的传递&#x…

【图像分类】理论篇(2)经典卷积神经网络 Lenet~Densenet

1、卷积运算 在二维卷积运算中&#xff0c;卷积窗口从输入张量的左上角开始&#xff0c;从左到右、从上到下滑动。 当卷积窗口滑动到新一个位置时&#xff0c;包含在该窗口中的部分张量与卷积核张量进行按元素相乘&#xff0c;得到的张量再求和得到一个单一的标量值&#xff0c…

算法与数据结构(二十三)动态规划设计:最长递增子序列

注&#xff1a;此文只在个人总结 labuladong 动态规划框架&#xff0c;仅限于学习交流&#xff0c;版权归原作者所有&#xff1b; 也许有读者看了前文 动态规划详解&#xff0c;学会了动态规划的套路&#xff1a;找到了问题的「状态」&#xff0c;明确了 dp 数组/函数的含义&a…

二叉树的存储结构(顺序存储)—— 数据结构与算法

&#x1f636;‍&#x1f32b;️Take your time ! &#x1f636;‍&#x1f32b;️ &#x1f4a5;个人主页&#xff1a;&#x1f525;&#x1f525;&#x1f525;大魔王&#x1f525;&#x1f525;&#x1f525; &#x1f4a5;代码仓库&#xff1a;&#x1f525;&#x1f525;魔…

《雷达像智能识别对抗研究进展》阅读记录

&#xff08;1&#xff09;引言 ​ 神经网络通常存在鲁棒性缺陷&#xff0c;易受到对抗攻击的威胁。攻击者可以隐蔽的诱导雷达智能目标识别做出错误预测&#xff0c;如&#xff1a; ​ a图是自行车&#xff0c;加上对抗扰动后神经网络就会将其识别为挖掘机。 &#xff08;2&a…

一探Linux下的七大进程状态

文章目录 一、前言二、操作系统学科下的进程状态1、运行状态2、阻塞状态3、挂起状态 三、Linux下的7种进程状态1、运行状态R2、浅度睡眠状态S3、深度睡眠状态D一场有趣的官司 4、停止状态T5、进程跟踪状态t6、死亡状态X7、僵死状态Z —— 两个特殊进程① 僵尸进程② 孤儿进程 四…

算法竞赛备赛之搜索与图论训练提升,暑期集训营培训

目录 1.DFS和BFS 1.1.DFS深度优先搜索 1.2.BFS广度优先搜索 2.树与图的遍历&#xff1a;拓扑排序 3.最短路 3.1.迪杰斯特拉算法 3.2.贝尔曼算法 3.3.SPFA算法 3.4.多源汇最短路Floy算法 4.最小生成树 4.1.普利姆算法 4.2.克鲁斯卡尔算法 5.二分图&#xff1a;染色法…

嵌入式学习之strcpy、memset、realloc、malloc使用方法

今天主要针对C语言的strcpy memset realloc mallooc函数进行了学习。 char* strcpy(char* destination,const char* source); void memset ( void *s , char ch, unsigned n )&#xff1b; void* realloc(void* memblock, size_t size)&#xff1b; void *malloc(size_t si…

tkinter打造三维绘图系统,附源代码

文章目录 输入数据加载数据绘图函数源代码 Python绘图系统系列&#xff1a;将matplotlib嵌入到tkinter 简单的绘图系统 数据导入 输入数据 三维绘图需要一个新的坐标变量&#xff0c;设置为z&#xff0c;这个改改UI就可以办到&#xff0c;并不困难。但是&#xff0c;此前用于…

git安装介绍

一、分布式版本控制系统Git概述 1.1 分布式版本控制系统Git介绍 版本控制定义 记录和跟踪项目中各文件内容的改动变化 保存项目的版本历史&#xff0c;以及改动原因&#xff0c;从而让用户能够查看各个历史版本 版本控制系统也是帮助人员进行协作开发的利器 为什么需要版本…