AutoxJS脚本保姆级教程

目录

引言

准备工作

脚本开发

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

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

问题及技巧归总

JS语法错误:软件更新

按钮或组件无法找到

使用定时器等待组件出现

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

主线程堵塞问题

全局日志记录

巧用id或text

Tasker和AutoXjs自启问题

效果展示

写在最后

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

相关代码


引言

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

准备工作

这篇文章

脚本开发

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

这里直接贴出脚本

javascript 复制代码
/*
 * @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: "[email protected]",// 接收消息的邮箱
    },
  }, //邮箱配置,需要去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就可以解决,具体脚本如下

javascript 复制代码
// 自启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 邮件推送服务,需要获取邮箱的授权码

相关推荐
Darling02zjh28 分钟前
GUI图形化演示
前端
Channing Lewis31 分钟前
如何判断一个网站后端是用什么语言写的
前端·数据库·python
互联网搬砖老肖41 分钟前
Web 架构之状态码全解
前端·架构
showmethetime1 小时前
matlab提取脑电数据的五种频域特征指标数值
前端·人工智能·matlab
码农捻旧1 小时前
解决Mongoose “Cannot overwrite model once compiled“ 错误的完整指南
javascript·数据库·mongodb·node.js·express
淡笑沐白1 小时前
探索Turn.js:打造惊艳的3D翻页效果
javascript·html5·turn.js
sunxunyong2 小时前
yarn任务筛选spark任务,判断内存/CPU使用超过限制任务
javascript·ajax·spark
Ynov2 小时前
详细解释api
javascript·visual studio code
左钦杨2 小时前
IOS CSS3 right transformX 动画卡顿 回弹
前端·ios·css3
NaclarbCSDN2 小时前
Java集合框架
java·开发语言·前端