【2024年】autoXJS自动化刷币任务实战训练,ks极速版
菜鸟黄某 2024-07-29 15:37:03 阅读 56
【2024年】 KS
文章目录
【2024年】 KS效果图引言准备工作脚本开发功能简介主程序代码 `KSapp.js`工具类模块代码 `Tools.js`
效果图
引言
最新:https://blog.csdn.net/weixin_62061392/article/details/136074769
仅供学习!其他用途自负
本次使用autox.js 完成脚本制作,使用前请看清app版本
一般的app在版本变化时 往往控件的id 越会变化 导致获取控件失败,所以我一般不使用 id去唯一抓取控件
如果你是今天第一次打开app,并且是新号,会有超多弹窗 ,这些弹窗有些能布局分析捕获,有些不能,有些按返回可以关闭。有些不行。
脚本中对部分弹窗另建 子线程2去关闭 ,由于种类多,会有些遗漏,建议下载 李跳跳去辅助关闭
现在autojs的控件真的越来越不好找了。。。且用且珍惜吧,最后脚本可能就是找图找色了。。。麻烦要死
准备工作
AutoX.js 版本不要太低
快手极速版 版本12.0.40.7282 (2024-01-02 最新版)
电脑+VSCode 你需要自己去修改调试,如果APP版本和我不一致,可能导致一些控件无法获取,需要自己去修改条件
脚本开发
功能简介
我将一些常用函数放在工具类模块代码里,在主程序代码和调用就行,需要注意的是 :工具类模块代码需要和主程序代码放一个层级目录
必须修改的参数:
<code>openPhone(password) @password 手机锁屏时的数字密码tools.email(targetEmail)
*@targetEmail 发送目标邮箱exit(is_sendemail, content)
@is_sendemail 是否开启qq邮箱通知 如果没有qq邮箱app 需要写false
功能
8种高金币常用任务:
到点领餐补看广告开宝箱得金币看直播逛街领金币搜索任务刷短视频
早睡早起
统计金币数量💰 : 获取并计算 运行完脚本 共获取了多少金币
熄屏时密码解锁手机:熄屏时也能正常运行
qq邮箱汇报:必须是qq邮箱 微信关联qq邮箱即可在微信上直接查看脚本运行情况
这里直接贴代码吧
有什么问题和建议欢迎留言😁
主程序代码 KSapp.js
/*
* @Descripttion: 用于快手极速版刷金币的脚本
* @Author: 菜鸟黄某
* @AutoXjs版本:6.5.7
* @快手极速版版本:12.0.40.7282 (2024-02-02 最新版)
* @Date: 2024-02-02
*/
//导入模块
var tools = require('Tools2.0.js');
log("快手极速版脚本 启动")
const h = device.height || 2400,
w = device.width || 1280;
//手机 数字类型的锁屏密码
let password = "751953",
//汇报邮箱
targetEmail = "mailto:123456@qq.com",
//完成状况
state = "",
//程序最大重试次数
maxRetryCount = 3,
//脚本运行时间 单位:分钟
maxRuntime = 50,
//脚本启动时的时间
startDate = new Date().getTime() + 8 * 60 * 60 * 1000,
appname = "快手极速版",
packageName = getPackageName(appname),
//获取得金币数量
begin_coinNum,
end_coinNum,
//吃饭没
eated = false,
//任务成功次数
suceeseTaskCount = 0;
//脚本结尾操作 sync() 把里面的函数加上同步锁,使得在同一时刻最多只能有一个线程执行这个函数
//@是否发送【qq邮箱通知】 @邮箱内容
var exitEnd = sync(function (content, is_sendemail) {
log(">>>>>>>>>>>>>>退出脚本准备<<<<<<<<<<<<<<<")
//is_sendemail 默认为false
is_sendemail = !!is_sendemail
content += `已成功任务次数:${ suceeseTaskCount}\n脚本开始时的金币:${ begin_coinNum}\n脚本结束时的金币:${ end_coinNum}\n本次获取金币数量为:${ end_coinNum - begin_coinNum}\n`
log("脚本完成情况:\n" + content)
//qq邮箱汇报 必须是qq邮箱app 微信关联qq邮箱即可在微信上直接查看脚本情况
is_sendemail && tools.email(targetEmail, appname, content)
sleep(3000)
tools.killApp(packageName)
home()
//取消屏幕常亮
device.cancelKeepingAwake()
threads.shutDownAll()//关闭所有子线程
engines.stopAll()//关闭所有脚本
})
//新建线程 专门处理广告倒计时
let thread1 = threads.start(function () {
try {
while (true) {
let ad1 = id("com.kuaishou.nebula.commercial_neo:id/video_countdown").findOne(300)
if (ad1 && ad1.text() == "已成功领取奖励") {
log(`【找到[${ ad1.text()}]并点击】:${ tools.superClick(ad1)}`)
}
let ad2 = id("com.kuaishou.nebula:id/neo_count_down_text").findOne(400) || id("com.kuaishou.nebula.commercial_neo:id/reward_merchant_text").findOne(200)
if (ad2 && (ad2.text().search(/[1-4]秒|00:0[1-4]/) == 0 || ad2.text() == "已领取")) {
log(`[广告线程]-->" ${ ad2.text()}\n`)
sleep(5000);
back()
}
let ad3 = textMatches(/(领取|奖励|立即|任务|退出|仍要|直播间|放弃){2}/).findOne(300) || className("android.widget.TextView").textStartsWith("看内容最高可得").findOne(200) || className("android.widget.Button").textStartsWith("看内容最高可得").findOne(200)
if (ad3) {
if (tools.superClick(ad3)) {
log(`【找到[${ ad3.text()}]并点击】:true`)
} else if (ad3.bounds().centerX() > 0 && ad3.bounds().centerY() > 0) {
click(ad3.bounds().centerX(), ad3.bounds().centerY());
}
}
}
} catch (e) {
if (e.name == "JavaException") {
log(">>>>>>>>>>>>>>>>广告线程退出<<<<<<<<<<<<<<<<<<<<")
} else {
state += `广告线程异常: ${ e}\n`
exitEnd(state, true)
}
}
});
// //新建线程 处理弹窗
let thread2 = threads.start(function () {
try {
while (true) {
//1.泡泡红包体现20元起(zhuanqianye)
//2.龙卡 限时大放送(jika3)
//3.天降神卡 关闭按钮坐标都为(1000,425) 右上角
//4.收到快手的提现红包
let window1 = textMatches(/zhuanqianye.*|jika.*|tianjiang.*|收到快手的提现红包/).findOne(300)
if (window1) {
log("<<<<<<<<<<<<<<【弹窗识别】>>>>>>>>>>>>>>>>>>>")
let close_btn = window1.parent().parent().child(0).child(0) || window1.parent().parent().child(0)
if (close_btn && close_btn.clickable()) {
close_btn.click()
} else if (close_btn) {
click(close_btn.bounds().centerX(), close_btn.bounds().centerY())
} else {
tools.clicks(1000, 425)
}
}
//邀请4个新用户必得 关闭按钮坐标(542, 1738) 弹窗x中心底部
let window2 = textMatches(/邀请\d+个新用户必得/).findOne(300)
if (window2) {
log("<<<<<<<<<<<<<<【弹窗识别】>>>>>>>>>>>>>>>>>>>")
let close_btn = window2.parent().parent().child(1).child(0)
if (close_btn && close_btn.clickable()) {
close_btn.click()
} else if (close_btn) {
click(close_btn.bounds().centerX(), close_btn.bounds().centerY())
} else {
tools.clicks(542, 1738)
}
}
//新人14天签到礼包 --> 立即领取 --> back()会和页面已经返回
//新人14天签到礼包 --> 立即领取 -->看更多内容--》back()
//组队现金无限嫌
let close_btn1 = id("com.kuaishou.nebula:id/close_btn").findOne(300) || id("com.kuaishou.nebula:id/dialog_close").findOne(300);
if (close_btn1) {
log("<<<<<<<<<<<<<<【弹窗识别】>>>>>>>>>>>>>>>>>>>")
tools.superClick(close_btn1)
}
}
} catch (e) {
if (e.name == "JavaException") {
log(">>>>>>>>>>>>>>>>弹窗线程退出<<<<<<<<<<<<<<<<<<<<")
} else {
// log(e)
state += `弹窗线程异常: ${ e}\n`
exitEnd(state, true)
}
}
});
try {
init("begin")
} catch (error) {
//错误类型为 JavaException时 跳过重启任务 因为这是engines.stopAll()抛出异常导致的
if (error.name == "JavaException" || error.name == "脚本运行超时") {
state += `主线程异常: ${ error.name}:${ error.message}\n`
log("程序结束")
} else {
state += `主线程异常: ${ error}\n`
sleep(1500)
//子线程都活着 重启任务才有意义
if (thread1.isAlive()) {
tools.killApp(packageName)
init("end")
}
}
} finally {
log(">>>>>>>>>>>>>>>finally<<<<<<<<<<<<<<<")
exitEnd(state, true)
}
//运行超时处理
function overTime() {
let currentTime = new Date().getTime() + 8 * 60 * 60 * 1000;
let runtime = Math.floor((currentTime - startDate) / (60 * 1000))
let _log = `>>>>>>>脚本已经运行:${ runtime}/${ maxRuntime}分钟<<<<<<<<`
log(_log)
if (runtime > maxRuntime) {
throw new tools.UserErroyInfo("脚本运行超时", _log)
}
}
//初始操作
function init(tag) {
if (!!maxRetryCount) {
log(`>>>>>>>>>>>>>>剩余重试次数${ maxRetryCount}<<<<<<<<<<<<<`);
maxRetryCount--;
//停止其他脚本
tools.stopOtherScript()
//检测是否熄屏并开锁
tools.openPhone(password);
sleep(2000);
//保持屏幕常亮
device.keepScreenOn()
tools.openApp(appname, 5000);
sleep(2000)
//任务中心
if (tools.backTo(text("首页"), 3)) {
let taskcenter = id("float_background").findOne(2000) || text("去赚钱").findOne(2000)
if (taskcenter) {
log(`【找到[${ taskcenter.text()}]并点击】:${ tools.superClick(taskcenter)}`)
sleep(15000)
getCoinNum(tag)
main()
} else {
log("未找到 任务中心")
tools.killApp(packageName)
init("end")
}
}
} else {
exitEnd(state, true)
}
}
function main() {
while (true) {
//返回失败次数
let failcount = 0;
//开宝箱得金币
tools.backTo(text("任务中心"), 3) ? openBox() : failcount++
//餐补任务
tools.backTo(text("任务中心"), 3) ? eatTime() : failcount++
//早睡早起
tools.backTo(text("任务中心"), 3) ? sleepgetup() : failcount++
//看广告
tools.backTo(text("任务中心"), 3) ? lookAD() : failcount++
//看直播
tools.backTo(text("任务中心"), 3) ? lookzbj() : failcount++
//逛街领金币
tools.backTo(text("任务中心"), 3) ? lookProduct() : failcount++
//搜索任务
tools.backTo(text("任务中心"), 3) ? findLook() : failcount++
//看视频
tools.backTo(text("首页"), 3) ? lookvd() : failcount++
if (failcount > 4) {
log(`失败次数过多--> ${ failcount}`)
state += `失败次数过多--> ${ failcount}\n`
break;
}
//回到任务中心
if (tools.backTo(id("android:id/text1").text("首页"), 3)) {
let taskcenter = id("float_background").findOne(2000) || text("去赚钱").findOne(2000)
if (taskcenter) {
log(`【找到[${ taskcenter.text()}]并点击】:${ tools.superClick(taskcenter)}`)
sleep(4000);
tools.backTo(text("任务中心"), 3) ? getCoinNum("end") : log("点击但未进入 任务中心")
} else {
log("未找到 任务中心")
}
}
overTime()
}
tools.killApp(packageName)
//子线程都活着 重启任务才有意义
if (thread1.isAlive()) {
tools.killApp(packageName)
init("end")
}
}
//开宝箱
function openBox() {
log(`\n【开宝箱任务】`)
let coinBoxBtn = text("treasurebox").findOne(2000) || ("开宝箱得金币").findOne(2000) || textStartsWith("点就领").findOne(2000)
if (coinBoxBtn) {
log(`点击宝箱`)
click(coinBoxBtn.bounds().centerX(), coinBoxBtn.bounds().centerY());
tools.waitforUi(text("任务中心"), 30, () => sleep(10000))
} else {
log("暂无宝箱")
}
sleep(2000)
}
//看广告
function lookAD() {
log(`\n【看广告任务】`)
let adtask = className("android.widget.TextView").textStartsWith("看广告得").findOne(2000) || className("android.widget.TextView").textStartsWith("看视频得").findOne(2000)
if (adtask) {
log(`【找到[${ adtask.text()}]并点击】:${ tools.superClick(adtask)}`)
sleep(2500)
if (text("任务中心").exists()) {
log(`广告已看完`)
suceeseTaskCount++
return;
}
//等待
tools.waitforUi(text("任务中心"), 30, () => sleep(10000))
} else {
log("未找到广告任务入口")
}
}
//逛街领金币
function lookProduct() {
log(`\n【逛街领金币】`)
let lookProtask = className("android.widget.TextView").textStartsWith("逛街领金币").findOne(2000)
if (lookProtask) {
if (textStartsWith("今日福利已领取").exists()) {
log("逛街领金币已完成")
suceeseTaskCount++
return;
}
log(`【找到[${ lookProtask.text()}]并点击】:${ tools.superClick(lookProtask)}`)
sleep(3000)
tools.waitforUi(text("任务中心"), 13, () => {
tools.randomSwipe(w, h, "上", 2000, 3200);
tools.randomSwipe(w, h, "上", 2000, 3200)
tools.randomSwipe(w, h, "下", 2000, 3200)
})
} else {
log("未找到点击按钮")
}
}
//看直播
function lookzbj() {
log(`\n【看直播任务】`)
let zbj = className("android.widget.TextView").textEndsWith("次直播领金币").findOne(2000)
if (zbj) {
let result = zbj.parent().child(2).text() //已经完成 2/6
let a = result.match(/(\d*)\/(\d*)/) // 2/6
//已完成情况 6/6
if (result == "今日已成功领取直播奖励金币" || result.search(a[2] + "/" + a[2]) != -1) {
log(result)
suceeseTaskCount++
return;
}
log(`【找到[${ zbj.text()}]并点击】:${ tools.superClick(zbj)}`)
sleep(3000)
tools.randomSwipe(w, h, "上", 0, 0)
tools.randomSwipe(w, h, "上", 1000, 2000)
sleep(1000)
let maxcount = a[2] - a[1]
for (let i = 0; i < maxcount; i++) {
let zbj = id("recycler_view").findOne(2000)
if (zbj && i < zbj.childCount()) {
log(`第${ i + 1}/${ maxcount}次进入直播间`)
tools.superClick(zbj.child(i))
tools.waitforUi(text("看直播领金币"), 12, () => sleep(10000))
} else {
log("未找到直播间控件/已看完")
break;
}
}
} else {
log("未找到 直播控件")
}
}
//下滑看视频
function lookvd() {
log(`\n【看视频任务】`)
let homepage = id("android:id/text1").text("首页").findOne(2000)
if (homepage) {
click(homepage.bounds().centerX(), homepage.bounds().centerY())
sleep(2000)
let i = 0;
while (i < 26) {
log(`浏览视频第 ${ i}次`)
tools.randomSwipe(w, h, "上", 3000, 5000)
tools.randomSwipe(w, h, "上", 3000, 7000)
tools.randomSwipe(w, h, "下", 2000, 8000)
i++;
}
} else {
log("未找到首页")
}
}
//搜素并浏览
function findLook() {
log(`\n【搜索浏览任务】`)
let search = className("android.widget.TextView").textStartsWith("搜索").findOne(2000) || className("android.view.View").textStartsWith("搜索浏览15s").findOne(2000)
if (search) {
let arr = search.text().match("“(.+?)”") || search.text().match("\"(.+?)\"")
let res = search.parent().child(2).text()
let a = res.split("/")[1] // /后边数字
a = a + "/" + a
if (res.search(a) != -1) {
log("搜索浏览任务已完成")
suceeseTaskCount++
return;
}
log(`【找到[${ search.text()}]并点击】:${ tools.superClick(search)}`)
sleep(2500)
let result = text("任务中心").findOne(2000)
if (result) {
log(`倒计时结束后可看`)
return;
}
let btn = className("android.widget.TextView").text("搜索").findOne(2000)
if (btn) {
log("输入:" + arr[1])
setText(arr[1])
sleep(1000)
log(`【找到[${ btn.text()}]并点击】:${ tools.superClick(btn)}`)
sleep(22000)
back()
} else {
log("未找到搜索按钮")
}
} else {
log("未找到 搜索浏览")
}
}
//获取当前金币数量
function getCoinNum(tag) {
if (tag == "pass") {
return;
} else {
log("\n【获取金币数量】")
let mycoin = text("我的金币").findOne(2000)
if (mycoin) {
log(`【找到[${ mycoin.text()}]并点击】:${ tools.superClick(mycoin)}`)
sleep(4000)
if (text("我的收益").exists()) {
let coin = textMatches(/(\d?\.?\d+)w?金币/).findOne(2000)
coin ? (tag == "begin" ? begin_coinNum = end_coinNum = coin.text().match(/(\d?\.?\d+)/)[0] : end_coinNum = coin.text().match(/(\d?\.?\d+)/)[0]) : log("未找到 金币控件");
(begin_coinNum && begin_coinNum.toString().search(/\./) != -1) ? begin_coinNum = Math.ceil(begin_coinNum * 10000) : log("begin_coinNum-->" + begin_coinNum, "end_coinNum-->" + end_coinNum);
(end_coinNum && end_coinNum.toString().search(/\./) != -1) ? end_coinNum = Math.ceil(end_coinNum * 10000) : log("begin_coinNum-->" + begin_coinNum, "end_coinNum-->" + end_coinNum);
} else {
log("未进入 金币详情页面")
}
} else {
log("未找到 -- 我的金币")
}
}
}
//餐补
function eatTime() {
log("\n【餐补任务】")
// 获取当前北京时间的时间戳(单位为毫秒)
var stamp = new Date().getTime() + 8 * 60 * 60 * 1000;
// 格式化北京时间为"YYYY-MM-DD HH:mm:ss"
//replace() -->字符串分割 substring(0, 10); -->取 年月日
var beijingTime = new Date(stamp).toISOString().replace(/T/, ' ').replace(/\..+/, '').substring(0, 10);
//当前小时 Date.parse( )-->转化成时间戳 向下取整
let date = Math.floor((stamp - Date.parse(beijingTime)) / (60 * 60 * 1000))
switch (date) {
case 1:
case 2:
case 3:
case 4:
case 9:
case 10:
case 14:
case 20:
case 0:
log(`未到餐补时间--》目前:${ date}点`)
eated = false;
break
default:
log(`餐补时间--》目前:${ date}点`)
if (eated == false) {
let eattask = className("android.widget.TextView").textStartsWith("到饭点领饭补").findOne(2000)
if (eattask) {
log(`【找到[${ eattask.text()}]并点击】:${ tools.superClick(eattask)}`)
sleep(3000)
//点击领取
let next1 = text("领取饭补").findOne(2000) || textMatches(/(.+?)领取(.+?)补贴/).findOne(2000)
if (next1) {
log(`【找到[${ next1.text()}]并点击】:${ tools.superClick(next1)}`)
eated = true;
} else {
log("未找到 领取控件")
}
sleep(2000)
let next2 = textEndsWith("待补签").findOne(2000)
if (next2) {
log(`【找到[${ next2.text()}]并点击】:${ tools.superClick(next2)}`)
eated = true;
} else {
log("未找到 补签控件")
}
return;
} else {
log("未找到饭补入口");
}
} else {
log("已领取");
suceeseTaskCount++
return;
}
}
}
//睡觉起床
function sleepgetup() {
log("\n【睡觉起床任务】")
// 获取当前北京时间的时间戳(单位为毫秒)
var stamp = new Date().getTime() + 8 * 60 * 60 * 1000;
// 格式化北京时间为"YYYY-MM-DD HH:mm:ss"
//replace() -->字符串分割 substring(0, 10); -->取 年月日
var beijingTime = new Date(stamp).toISOString().replace(/T/, ' ').replace(/\..+/, '').substring(0, 10);
//当前小时 Date.parse( )-->转化成时间戳 向下取整
let date = Math.floor((stamp - Date.parse(beijingTime)) / (60 * 60 * 1000))
switch (date) {
case 5:
case 6:
case 7:
case 8:
case 9:
log(`起床时间--》目前:${ date}点`)
let getup = className("android.widget.TextView").textStartsWith("起床赚金币").findOne(2000)
if (getup) {
sleep(1000)
if (text("已起床").exists()) {
log("已起床")
return;
}
log(`【找到[${ getup.text()}]并点击】:${ tools.superClick(getup)}`)
sleep(2000)
//点击领取
let next = text("开始起床").findOne(2000)
if (next) {
log(`【找到[${ next.text()}]并点击】:${ tools.superClick(next)}`)
} else {
log("未找到 领取控件")
}
} else {
log("未找到饭补入口");
}
break
case 20:
case 21:
case 22:
case 23:
log(`睡觉时间--》目前:${ date}点`)
let toSleep = className("android.widget.TextView").textStartsWith("睡觉赚金币").findOne(2000)
if (toSleep) {
if (text("已睡觉").exists()) {
log("已睡觉")
return;
}
sleep(2000)
log(`【找到[${ toSleep.text()}]并点击】:${ tools.superClick(toSleep)}`)
//点击领取
let next = text("开始睡觉").findOne(2000)
if (next) {
log(`【找到[${ next.text()}]并点击】:${ tools.superClick(next)}`)
} else {
log("未找到 领取控件")
}
} else {
log("未找到饭补入口");
}
break
default:
log("时间未到")
}
}
工具类模块代码 Tools.js
var tools = { };
//手机屏幕唤醒 适合数字密码锁屏
//@密码 [type]:str
tools.openPhone = function (password) {
log("openPhone()----------------->")
sleep(2000)
if (!device.isScreenOn()) {
log("openPhone()-->熄屏状态,尝试唤醒&输入密码")
device.wakeUp()
//让设备一直亮屏
// device.keepScreenOn()
sleep(2000)
swipe(device.width / 2, device.height / 1.3, device.width / 2, device.height / 8, 200)
sleep(1000)
//有密码则
log("openPhone()-->输入密码中")
if (text("1").findOne(2000)) {
for (var i = 0; i <= password.length; i++) {
click(password[i])
sleep(100)
}
} else if (desc("1").findOne(2000)) {
for (var i = 0; i <= password.length; i++) {
var p = desc(password[i]).findOne(1000)
if (p) {
p.click()
}
sleep(100)
}
} else {
log("openPhone()-->未找到密码锁")
}
}
};
//在"Autox.js v6"app页面 打开其他应用成功率高,提高容错
//@app名字 @打开app后休眠时间
tools.openApp = function (name, time) {
log(`openApp()----------------->${ name}`)
home()
sleep(1000)
launchApp("Autox.js v6")
sleep(5000)
if (app.getPackageName(name)) {
launchApp(name)
} else {
log("未安装:" + name)
}
sleep(time)
};
//自动化 杀死app后台
//@app包名
tools.killApp = function (packageName) {
var name = getPackageName(packageName);
if (!name) {
if (getAppName(packageName)) {
name = packageName;
} else {
return false;
}
}
app.openAppSetting(name);
text(app.getAppName(name)).waitFor();
sleep(2000);
let is_sure = textMatches(/(强行|停止|结束|强制|运行){2}/).findOne(2000);
if (is_sure && is_sure.enabled()) {
click(is_sure.text())
sleep(2000);
let next = text("确定").findOne(3000) || textMatches(/(强行|停止|结束|强制|运行){2}/).findOne(2000)
if (next && next.enabled()) {
click(next.text())
log(`killApp()---------->应用已被关闭`);
sleep(2000);
} else {
log(`killApp()---------->应用不能被正常关闭或不在后台运行`);
}
} else {
log(`killApp()---------->应用不能被正常关闭或不在后台运行`);
}
}
//返回到某个页面
//@控件对象 @最大返回/查找次数 return{bool}
tools.backTo = function (selector_obj, maxFind) {
log("backTo()----------------->" + selector_obj)
while (!selector_obj.findOne(2000)) {
if (maxFind > 0) {
back()
maxFind--;
sleep(2000)
} else {
log("backTo()-->失败")
return false;
}
}
log("backTo()-->成功")
return true;
}
//截屏权限获取
tools.getScreenCapture = function () {
log("请求截屏权限");
let Thread = null
if (device.sdkInt > 28) {
//等待截屏权限申请并同意 线程多开
Thread = threads.start(function () {
// sleep(500)
// click(846, 1553) 如果无法自动点击 可用坐标
packageName('com.android.systemui').text(/(允许|立即开始|统一)/).waitFor();
text(/(允许|立即开始|统一)/).click();
});
}
//申请截屏权限
if (!requestScreenCapture()) {
log("请求截图失败");
exit();
return false;
} else {
Thread.interrupt()
log("已获得截图权限");
return true;
}
}
//截屏
tools.ScreenCapture = function () {
log("ScreenCapture()----------------->")
// captureScreen("/sdcard/结果图.png"); -->不会保存到系统相册
takeScreenshot()//模拟电源+音量键 进行截图-->保存到系统相册
sleep(4000)
}
//qq邮箱发送
//@目标邮箱 @标题 @正文
tools.email = function (targetEmail, tag, content) {
if (app.getPackageName("QQ邮箱")) {
log("email()----------------->" + targetEmail)
let intent = new Intent(Intent.ACTION_SENDTO);
intent.setData(android.net.Uri.parse(targetEmail));
intent.putExtra(Intent.EXTRA_SUBJECT, tag);
intent.putExtra(Intent.EXTRA_TEXT, content);
app.startActivity(intent);
sleep(4000)
click("发送")
} else {
log("未安装qq邮箱")
}
}
//随机时间 随机坐标滑动
//@设备宽度 @设备像素高度 @方向 @最小随机时间 @最大随机时间
tools.randomSwipe = function (w, h, dir, sleeptiemMin, sleeptiemMax) {
let _swipe = {
x1: random(w / 3, w / 2),
x2: random(w / 3, w / 2),
y1: random(h / 1.5, h / 1.2),
y2: random(h / 8, h / 9),
time: random(200, 300),
sleep_time: random(sleeptiemMin, sleeptiemMax)
}
log(`${ _swipe.sleep_time / 1000}秒后将向${ dir}滑`)
sleep(_swipe.sleep_time)
if (dir == "上") {
swipe(_swipe.x1, _swipe.y1, _swipe.x2, _swipe.y2, _swipe.time)
} else if (dir == "下") {
swipe(_swipe.x1, _swipe.y2, _swipe.x2, _swipe.y1, _swipe.time)
} else if (dir == "左") {
swipe(w / 8, _swipe.y2, w / 1.3, _swipe.y2, _swipe.time)
} else {
swipe(w / 1.3, _swipe.y2, w / 8, _swipe.y2, _swipe.time)
}
}
//点击 在当前页面的控件
//@uiSelects 控件条件数组 @rangeTop/rangebottom 控件出现得上下范围 有默认值 return{bool}
tools.clickBounds = function (uiSelects, findtime, rangeTop, rangebottom) {
let i = 0
rangeTop = rangeTop || 0
rangebottom = rangebottom || device.height
while (true) {
let click_target = uiSelects[i].findOne(findtime)
if (click_target) {
if (click_target.bounds().centerY() < rangeTop) { //得向下滑动
log(`clickBounds()------->${ uiSelects[i]}控件在屏幕上方`)
swipe(w / 2, h / 2, w / 2, h / 1.2, 300)
} else if (click_target.bounds().centerY() > rangebottom) { //得向上滑动
log(`clickBounds()------->${ uiSelects[i]}控件在屏幕下方`)
swipe(w / 2, h / 1.2, w / 2, h / 2, 300)
} else {
log(`点击--->${ click_target.text()}`)
click(click_target.bounds().centerX(), click_target.bounds().centerY())
return true;
}
} else {
if (i < uiSelects.length - 1) {
i++;
} else {
log(`未找到----->${ uiSelects}`)
return false;
}
}
}
}
//主线程 在一定时间内 执行fn() 直到目标控件出现 或者时间结束
//@uiselector控件条件 @maxWaitCount 最大执行fn()次数
tools.waitforUi = function (uiSelector, maxWaitCount, fn) {
let i = 1
do {
//最大等待次数
if (i > maxWaitCount) {
tools.backTo(uiSelector, 3);
return;
}
log(`主线程第${ i}/${ maxWaitCount}次等待`)
fn()
i++
}
while (!uiSelector.exists())
}
//停止出自己之外的所有脚本
tools.stopOtherScript = function () {
engines.all().map((ScriptEngine) => {
if (engines.myEngine().toString() !== ScriptEngine.toString()) {
ScriptEngine.forceStop();
}
});
}
//超级点击
//@要点击的控件 return{bool}
tools.superClick = function (node) {
try {
if (node) {
if (node.click()) {
return true
} else if (node.parent().click()) {
return true
} else if (node.parent().parent().click()) {
return true
} else if (node.parent().parent().parent().click()) {
return true
} else if (node.parent().parent().parent().parent().click()) {
return true
} else if (node.parent().parent().parent().parent().parent().click()) {
return true
} else if (node.parent().parent().parent().parent().parent().parent().click()) {
return true
}
}
} catch (e) { }
return false
}
//用户信息报错时的构造函数
tools.UserErroyInfo = function (name, message) {
this.message = message;
this.name = name;
}
//适配不同设备的点击方法
//注意,测试机型为1080*2400,
tools.clicks = function (x, y) {
x1 = device.width / 1080
y1 = device.height / 2400
click(x * x1, y * y1)
}
//暴露模块
module.exports = tools;
声明
本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。