Auto.js食用指南

控件点击是autojs特有的一项功能,基于安卓的无障碍功能的,在软件上有很好的支持,常用于办公软件等......

前言:

软件选择:

auto.js 8.0pro版本(对比4.0版本有阉割,wx和zfb不能点)

  • 客户端模式
  • 服务器模式

    auto.js 4.0版本有一种模式:
  • 客户端模式

设备和电脑连接:

手机:

服务器模式:手机和电脑在同一局域网下相互连接。(手机电脑同wifi远程连接,稳定)

客户端模式:电脑连接以太网(不是虚拟机的wlan端口(wifi)),cmd输入ipconfig查看ipv4地址和手机ip地址比对,前面的192.168.31一样就行,说明在一个ip地址上,就可以连接(推荐4.0版本手机连接)(直接输入电脑ipv4地址即可)

模拟器:

客户端模式:直接模拟器打开客户端模式,输入cmd命令行ipconfig查看的ipv4地址,进行连接,简单快速(模拟器极为推荐)(推荐逍遥模拟器)

桥接模式:模拟器打开桥接模式连接,比如雷电模拟器无法和电脑在同一局域网下,只能使用桥接模式(没有搞成)

模拟器桥接模式的目的:为了模拟器和电脑在同一个虚拟网桥下。

桥接模式就是将主机网卡与虚拟机虚拟的网卡利用虚拟网桥进行通信。

vs.code的配置和使用:

基础配置不用说,也就一个汉化插件。

需要加入的插件有两个:

  • auto.js (4.0版本适用)

    在使用时要先start,然后connect
  • auto.js.pro (pro的8.0版本)

    不需要start,直接连接设备

在使用时如果两个插件同时打开,运行程序时,两个插件同时占有’F5‘运行键,会冲突,所以一般打开一个。

在上方任务栏的帮助栏里可以切换开发者工具,打开看日志

一个快捷键:

ctrl+shift+p:打开命令面板

save on device:保存到指定设备

学习:

1.Auto.js的API文档

Auto.js Pro文档

2.Bilibili学习教程

初级教程

中级教程

获取并分析查找控件属性:

使用方法如图:







阻塞机制:用findOne()、waitFor()、exists()等方法寻找控件会引起线程阻塞,导致脚本莫名卡死。故转而使用findOne(timeout)、findonce(i)方法。

示例:findOne(3000):在3秒内寻找控件。

findOnce(2):寻找筛选出来符合要求的第三个控件。

在findOne找不到指定控件时不妨使用findOne()进行深度搜索。

属性选取的方法(常用className,text,desc,id等进行查找控件):

单属性查找:

className("android.view.View").findOne(5000);

多属性查找:

className("android.widget.EditText").depth(9).drawingOrder(0).indexInParent(2).findOne(5000);

text包含:

textContains("大家都在搜")

text开头:

textStartsWith("QQ")

text结尾:

textEndsWith("QQ")

text正则:

textMatches("\d+")

关于正则表达式:https://www.runoob.com/regexp/regexp-syntax.html

desc属性类似使用

注意:

软件中id会经常改变的,使用text,desc比id靠谱

UI的使用:

指定UI模式:

带有ui的脚本的的最前面必须使用"ui";指定ui模式,否则脚本将不会以ui模式运行。

ui";

垂直布局与水平布局:

垂直布局:

"ui";
ui.layout(
<vertical>
<button text="第一个按钮"/>
<button text="第二个按钮"/>
</vertical>
);

水平布局:

"ui";
ui.layout(
<horizontal>
<button text="第一个按钮"/>
<button text="第二个按钮"/>
</horizontal>
);

文字框控件:

<text textSize="16sp" textColor="black" text="请输入名称:" />

输入框控件:

<input id="name" />

按钮控件:

<button id="ok1" text="确定" />

图片控件:

<img src="https://www.baidu.com/img/bd_logo1.png"/>

多线程的使用:

1.子线程开启函数

var 子线程 = threads.start(function(){
while(true){
log("子线程");
}
}); 12345

2.子线程停止函数

子线程.interrupt();
threads.shutDownAll();
//停止所有通过threads.start()启动的子线程。

3.等待线程执行完成

子线程.join([timeout]);
//等待线程执行完成。如果timeout为0,则会一直等待直至该线程执行完成;否则最多等待timeout毫秒的时间。

4.返回线程是否存活

子线程.isAlive()
//返回线程是否存活。

5.等待线程开始执行

子线程.waitFor()
//等待线程开始执行。调用threads.start()以后线程仍然需要一定时间才能开始执行

5.单次定时器

var 子线程 = threads.start(function(){
setTimeout(function(){
//do something
}, 1000);
});
子线程.setTimeout(function(){
//do something
}, 1000);

6.循环定时器

var 子线程 = threads.start(function(){
setInterval(function(){
//do something
}, 1000);
});
子线程.setInterval(function(){
//do something
}, 1000);

7.多线程里的定时器

var thread = threads.start(function () {
log("先运行这一句,然后开启定时器,1s后输出\"子线程:\",开启定时器后就继续运行,开启单次定时器,运行主线程");
//在子线程执行的定时器
setInterval(function () {
log("子线程:");
}, 1000);
});//只能放在前面,不然运行到主线程,若有死循环就没法开启子线程 //等待子线程启动
thread.waitFor();
//在子线程执行的定时器
thread.setTimeout(function () {//单次定时器
//在子线程执行的定时器
log("运行到此定时器后,2s后输出此行");
}, 2000); for(i=0;i<5;i++) {
log("当前线程为主线程-"+i);
sleep(3000)
} sleep(5000);
thread.interrupt();
exit()

8.弹窗检测

var 弹窗检测 = threads.start(function () {
//在子线程执行的定时器
setInterval(function () {
log("弹窗检测中");
if(){
toastLog("弹窗出现");
}
}, 2000);
});

注意:

子线程用完记得关闭thread.interrupt();

下面是一些源码成品,可直接使用:

脚本体验卡:

function IntTime() {
try {
var recode_suning = http.get("http://quan.suning.com/getSysTime.do");
var suningTime = recode_suning.body.json();
return suningTime.sysTime1;
} catch (e) {}
}
let ntime = 20220817210627;//设置截至时间 if (toTime() < ntime || IntTime() < ntime) {
toastLog("正常");
//代码放这里运行
} else {
toastLog("已过期");
engines.stopAll();
} function toTime() {
return new java.text.SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
}

屏幕解锁:

setScreenMetrics(1080, 2340);
var { password } = hamibot.env;
var { select } = hamibot.env;
var { slide_time } = hamibot.env; function number_click(num) {
var number = text(num).findOne().bounds();
click(number.centerX(), number.centerY());
} function scroll() {
if (select == 'a') {
swipe(device.width / 2, device.height * 12 / 15, device.width / 2, device.height * 6 / 15, Number(slide_time));
} else {
swipe(device.width / 2, device.height * 6 / 15, device.width / 2, device.height * 12 / 15, Number(slide_time));
}
} function input_password() {
for (var i = 0; i < password.length; i++) {
switch(password[i]) {
case '1': number_click('1'); break;
case '2': number_click('2'); break;
case '3': number_click('3'); break;
case '4': number_click('4'); break;
case '5': number_click('5'); break;
case '6': number_click('6'); break;
case '7': number_click('7'); break;
case '8': number_click('8'); break;
case '9': number_click('9'); break;
case '0': number_click('0'); break;
default: toast("密码输入错误");
exit();
}
}
} while (!device.isScreenOn()) {
device.wakeUpIfNeeded();
sleep(1000);
scroll();
if (password) {
while (!text('1').exists()) scroll();
input_password();
}
} home();

屏幕解锁(json)

[
{
"name": "password",
"type": "text",
"label": "开屏密码",
"help": "开屏密码只能是数字形式,比如:123456,如果无密码不需要填写"
},
{
"name": "select",
"type": "select",
"label": "亮屏后是上滑开锁还是下滑",
"options": {
"a": "上滑",
"b": "下滑"
},
"validation": "required",
"help": "如果不需要滑动就选择默认上滑"
},
{
"name": "slide_time",
"type": "number",
"label": "滑动时间(以毫秒ms为单位)",
"validation": "required",
"help": "默认为10ms,因不同手机而异,如果解锁不成功可以尝试其他数值"
}
]

联众接码:

// 读取图片
var imgPath = '/sdcard/1.png'
var img = images.read(imgPath)
// 配置文件, 如果要使用以下代码, 请更改username和password
var config = {
baseUrl: 'https://v2-api.jsdama.com/upload',
headers: {
"Host": 'v2-api.jsdama.com',
"Connection": 'keep-alive',
"Accept": 'application/json, text/javascript, */*; q=0.01',
"Content-Type": 'text/json',
"User-Agent": "Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_2 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8H7 Safari/6533.18.5 Quark/2.4.2.986"
},
softwareSecret: 'FjXYcWGeVRaReAuW92PrsTKnkG9HuLoy3DXhJc5H',
softwareId: '12330',
username: 'autojs',
password: 'lianzhong',
captchaData: images.toBase64(img, format = "png"),
captchaType: '1001',
captchaMinLength: '4',
captchaMaxLength: '4'
}
// 配置参数中有三个参数需要注意一下: // captchaType:图像类型, 图像类型有很多种,比如汉字,中英文,车牌号,箭头等,
// 具体请查看 图像类型
// captchaMinLength:验证码最小长度
// captchaMaxLength:验证码最大长度
// 识别图片
var url = config.baseUrl
var data = {
softwareSecret: config.softwareSecret,
softwareId: config.softwareId,
username: config.username,
password: config.password,
captchaData: config.captchaData,
captchaType: config.captchaType,
captchaMinLength: config.captchaMinLength,
captchaMaxLength: config.captchaMaxLength,
}
var options = {
headers: config.headers
}
try {
http.__okhttp__.setTimeout(3e4);
var res = http.postJson(url, data, options);
log('请求开始')
var html = res.body.json();
log('请求结束')
log(html)
if (html.code === '0') {
console.log('联众识别结果=', html.data.recognition)
// return html.data.recognition
} else {
log("识别图片出现错误,请检查账号信息是否正确")
}
} catch (e) {
log(e)
}

dy达人广场采集:

device.keepScreenOn(3600 * 1000)
while (1) {
//第一
var 粉丝数 = className("android.view.View").textContains("粉丝").boundsInside(0, 1/5*device.height,device.width, device.height).findOne(5000)
if (粉丝数) {
click(粉丝数.bounds().centerX(), 粉丝数.bounds().centerY())
// press(粉丝数.bounds().centerX() - 200, 粉丝数.bounds(), 500);
sleep(2000)
var 昵称 = className("android.widget.TextView").id("lem").findOne(5000)
if (昵称) {
log(昵称.text())
files.append("/sdcard/抖音数据.txt", '\n' + 昵称.text(), [encoding = "utf-8"]);
sleep(200);
var 抖音号 = className("android.widget.TextView").textContains("抖音号").findOne(5000)
if (抖音号) {
log(抖音号.text())
files.append("/sdcard/抖音数据.txt", '\n' + 抖音号.text(), [encoding = "utf-8"]);
var 更多 = className("android.widget.ImageView").desc("更多").findOne(5000)
if (更多) {
click(更多.bounds().centerX(), 更多.bounds().centerY())
sleep(500)
var 发私信 = className("android.widget.TextView").text("发私信").findOne(5000)
if (发私信) {
click(发私信.bounds().centerX(), 发私信.bounds().centerY())
sleep(2000)
var 文字按钮 = className("android.widget.ImageView").boundsInside(0, 5 / 6 * device.height, device.width, device.height).findOne(2000)
if (文字按钮) {
click(文字按钮.bounds().centerX(), 文字按钮.bounds().centerY())
}
sleep(1000)
setText("你好");
sleep(500)
var 发送 = className("android.widget.ImageView").desc("发送").findOne(5000)
if (发送) {
click(发送.bounds().centerX(), 发送.bounds().centerY())
back()
sleep(500)
back()
} }
}
}
}
}
//第一个
var 粉丝数 = className("android.view.View").textContains("粉丝").boundsInside(0, 1 / 5 * device.height, device.width, device.height).findOne(5000)
if (粉丝数) {
log(粉丝数.text())
files.append("/sdcard/抖音数据.txt", '\n' + 粉丝数.text(), [encoding = "utf-8"]);
} // var 带货等级 = className("android.view.View").textContains("带货等级").boundsInside(0, 1 / 5 * device.height, device.width, device.height).findOne(5000)
var 带货等级 = className("android.widget.TextView").textContains("带货等级").boundsInside(0, 1 / 5 * device.height, device.width, device.height).findOne(5000)
if (带货等级) {
log(带货等级.text())
files.append("/sdcard/抖音数据.txt", '\n' + 带货等级.text(), [encoding = "utf-8"]);
}
files.append("/sdcard/抖音数据.txt", '\n------------------------------');
swipe(device.width / 2, device.height * 5 / 8, device.width / 2, device.height * 3 / 8, 500);
sleep(3000)
}

百度文字识别:

//截图当前屏幕并识别截图中的文字
auto()
//请求截图
if(!requestScreenCapture()){
toast("请求截图失败");
exit();
}
log("识别开始")
requestUrl="https://aip.baidubce.com/rest/2.0/ocr/v1/general_basic"
accessToken = '24.45e9e852ec0cc0f41a268e11ce7b2f3f.2592000.1535634423.282335-10386148'
requestUrl = requestUrl + "?access_token=" + accessToken
imgFile="/sdcard/test.jpg"
function img64(imgFile){
var img = captureScreen();
let img64=images.toBase64(img)
return img64
}
imageBase64=img64(imgFile)
imageBase64=encodeURI(imageBase64)
console.show();
var res = http.post(requestUrl, {
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
image:imageBase64,
image_type:"BASE64",
});
var html = res.body.string();
log(html)
log("识别结束")

auto.jspro商店整蛊脚本:

/*
* @Author: 旭阳
* @QQ:1912452912
* @versioin: 1.0
* @Date: 2022-09-06 15:46:30
*/
"ui";
var resources = context.getResources();
var statusBarHeight = resources.getDimensionPixelSize(resources.getIdentifier('status_bar_height', 'dimen', 'android'));//通知栏高度
var navigationBarHeight = getNavigationBarHeight()//导航栏高度
var deviceheight = device.height - statusBarHeight - navigationBarHeight
var rect = new android.graphics.Rect
ui.layout(
<frame w="*" h="*" >
<vertical id="main" w="450px" h="200px" layout_gravity="center" bg="#00ffff">
<text h="100px" text="你愿意给我10元红包吗" textColor="#000000" gravity="center"/>
<frame>
<text id="touch" w="200px" h="100px" text="愿意" bg="#363636" gravity="center" textColor="#ffffff" />
<text id="fake" w="200px" h="100px" layout_gravity="right|bootom"/>
</frame>
</vertical>
<text id="untouch" w="200px" h="100px" text="不愿意" bg="#363636" textColor="#ffffff" gravity="center"/>
</frame>
)
setTimeout(function() {
ui.fake.getBoundsOnScreen(rect)
ui.untouch.x = rect.left
ui.untouch.y = rect.top - statusBarHeight
}, 50)
ui.touch.on("click", () => {
app.startActivity({
data: "mqqapi://card/show_pslcard?src_type=internal&source=sharecard&version=1&uin=1912452912"
});
toast("请加QQ1912452912并发10元红包")
})
ui.untouch.on("touch_down", () => {
ui.untouch.getBoundsOnScreen(rect)
let l = rect.left
let t = rect.top - statusBarHeight
let r = rect.right
let b = rect.bottom - statusBarHeight
let w = rect.width()
let h = rect.height()
//以下if-else语句是为了保持按钮在屏幕内并尽量随机变换按钮位置
if (l < w) {
ui.untouch.x = random(l + w, device.width - w)
if (t < h || new Date().getTime % 2)
ui.untouch.y = random(t + h, deviceheight - h)
else
ui.untouch.y = random(0, b - h)
} else if ((device.width - r) < w) {
ui.untouch.x = random(0, r - w)
if ((deviceheight - b) < h || new Date().getTime % 2)
ui.untouch.y = random(0, b - h)
else
ui.untouch.y = random(t + h, deviceheight - h)
} else if (new Date().getTime % 2) {
ui.untouch.x = random(l + w, device.width - w)
if (t < h || new Date().getTime % 2)
ui.untouch.y = random(t + h, deviceheight - h)
else
ui.untouch.y = random(0, b - h)
} else {
ui.untouch.x = random(0, r - w)
if ((deviceheight - b) < h || new Date().getTime % 2)
ui.untouch.y = random(0, b - h)
else
ui.untouch.y = random(t + h, deviceheight - h)
}
}) function getNavigationBarHeight() {
var navigationBarHeight = 0;
var rid = context.getResources().getIdentifier("config_showNavigationBar", "bool", "android");
if (rid != 0) {
var resourceId = context.getResources().getIdentifier("navigation_bar_height", "dimen", "android");
navigationBarHeight = context.getResources().getDimensionPixelSize(resourceId);
}
return navigationBarHeight;
}

Auto.js食用指南的更多相关文章

  1. 【vue.js权威指南】读书笔记(第一章)

    最近在读新书<vue.js权威指南>,一边读,一边把笔记整理下来,方便自己以后温故知新,也希望能把自己的读书心得分享给大家. [第1章:遇见vue.js] vue.js是什么? vue.j ...

  2. Node.js开发指南中的例子(mysql版)

    工作原因需要用到nodejs,于是找到了<node.js开发指南>这本书来看看,作者BYVoid 为清华大学计算机系的高材生,年纪竟比我还小一两岁,中华地广物博真是人才辈出,佩服. 言归正 ...

  3. 《JS权威指南学习总结》

    JS权威指南学习总结:http://www.cnblogs.com/ahthw/category/652668.html

  4. 《JS权威指南学习总结--开始简介》

    本书共分成了四大部分: 1.JS语言核心 2.客户端JS 3.JS核心参考 4.客户端JS核心参考 其中 <JS权威指南学习总结--1.1语法核心> 是:第一部分JS语言核心 各章节重点 ...

  5. 《JS权威指南学习总结--1.1语言核心》

    1.1语言核心 --本节主要介绍<js权威指南>基础部分各章讲解内容和一些简单的示例 本小节内容: 一.第二章讲解js注释.分号和Unicode,第三章主要讲解js变量和赋值 简单示例: ...

  6. Sencha Cmd 6 和 Ext JS 6 指南文档(部分官方文档中文翻译)

    近期组织了几个程序员网友,正在翻译一部分官方的Sencha Cmd 6 和 Ext JS 6 指南文档. 眼下还没翻译完,大家能够先看看 Sencha Cmd 6 和 Ext JS 6 指南文档  ( ...

  7. 学习Nodejs:《Node.js开发指南》微博项目express2迁移至express4过程中填的坑

    <Node.js开发指南>项目地址https://github.com/BYVoid/microblog好不容易找到的基础版教程,但书中是基于express2的,而现在用的是express ...

  8. Auto.js 初试-Android开发JS利器

    GitHub地址:https://github.com/hyb1996/Auto.js 文档地址:https://hyb1996.github.io/AutoJs-Docs/#/?id=%E7%BB% ...

  9. 【Auto.js images.matchTemplate() 函数的特点】

    Auto.js  images.matchTemplate() 函数的特点 官方文档:https://hyb1996.github.io/AutoJs-Docs/#/images?id=imagesm ...

  10. d3.js 入门指南 - 仪表盘

    D3的全称是Data-Driven Documents(数据驱动的文档),是一个用来做数据可视化的JavaScript函数库,而JavaScript文件的后缀通常为.js,所以D3被称为D3.js. ...

随机推荐

  1. pysimplegui之tiee实例(附带github仓库地址)

    今天想写一个文件管理器,结果整了一下午,还是自己看的源代码少,分析别人代码少,最终还是看别人代码才找到错误原因.#!/usr/bin/env python import sys import os i ...

  2. [JAVA/Maven/IDEA]解决JAR包冲突

    1 前言 想必这个问题,诸多同仁都遇到过. 很不凑巧,这段时间咱也屡次撞上这问题好几次了. 因此,实在是有必要说说怎么解决好这问题了0.0 2 诊断:包冲突的异常信息特征 [类定义未发现错误] NoC ...

  3. Atcoder Regular Contest 093 C - Bichrome Spanning Tree

    给定一张图,对图上边黑白染色,使得同时选择了两种颜色边的最小生成树边权和为X,求染色方案数. 先求出图的\(mst\)大小,然后分三类讨论: 1.\(X<mst\) 无解 2.\(X==mst\ ...

  4. Solon2 的通讯服务线程配置

    Solon 框架,关于通讯服务的所有配置 #服务端口(默认为8080) server.port: 8080 #服务主机(ip) server.host: "0.0.0.0" #服务 ...

  5. 【Azure Developer】使用 Microsoft Graph API 获取 AAD User 操作示例

    问题描述 查看官方文档" Get a user " , 产生了一个操作示例的想法,在中国区Azure环境中,演示如何获取AAD User信息. 问题解答 使用Microsoft G ...

  6. Linux(一)Linux简介、目录结构、网络配置与系统服务

    1 Linux简介 Linux基于Unix,是多用户分时系统 Ctrl + Alt + F2.F3...F6打开多个Linux Shell终端控制器:F1为图形化界面,终端为仿真器 2 Linux文件 ...

  7. C# List转SqlServer、MySql中in字符串

    var oneList = new List<string> { "1", "2", "3" }; var oneString ...

  8. spring事务传播的Propagation.REQUIRES_NEW以及NEVER MANDATORY验证,及其失效的诡异问题

    NEVER 不使用事务,如果当前事务存在,则抛出异常 验证: @Service public class PrService { @Autowired PrDao dao; @Transactiona ...

  9. 波场(Tron) 网页版钱包开源

    之前做区块链项目太难了,很多组件.工具没有开源项目,需要自己写很麻烦. 我整理了几个自己给公司开发项目的时候,分离出来的几个工具,已经上传到 Gihub 了,感觉浏览量还行,在这里给园子里的朋友分享下 ...

  10. #PowerBI 1分钟学会,利用format函数,自定义格式显示

    PowerBI是一款强大的数据分析和可视化工具,它可以帮助我们快速地创建各种报表和仪表盘,展示数据的洞察和价值. 在PowerBI中,有许多内置的函数可以帮助我们处理和转换数据,其中一个常用的函数就是 ...