一、缘起
Auto.js在钉钉打卡,刷视频点击,刷微信朋友圈点赞以及手机网游自动刷怪方面的应用很普遍,类似于按键精灵,不过更加注重代码化,功能也高端不少,
(以上都是胡扯,其实我从来都没用过)实际起因是这次疫情呆家里读了一星期的起点刷了1200分钟铂金级别阅读pk时间,发现对手竟然抱着一本辣鸡书连续看十几个小时,我立马觉得这肯定是挂
作为礼尚往来的新时代读者,立马打开搜索引擎,发现了AutoJS这个有意思的玩意,研究了半个小时AutoJS官方文档,利用我浅薄的代码知识,写了个起点读书pk阅读时间的小脚本,方便大家pk王者,解放双手:
auto.waitFor();//初次运行等待辅助服务启动完成
//亮度模式手动(0),最低亮度(0),如果自动模式则为(1),亮度取值范围(0-255),手机版本差别,一般0-9都是最低亮度
device.setBrightnessMode(0);
device.setBrightness(9);
setScreenMetrics(1440, 2560);
var count = 0;//这是一个计数器,用来触发末尾不定时唤起AutoJS到前台的操作,防止安卓kill
//初次启动寻找书籍并打开
while(1){
launch("com.qidian.QDReader");
waitForPackage("com.qidian.QDReader");
sleep(5000);//老年机用户酌情增加此项时间
var w = id("btnTopSearch").findOne(1000);//留合适的等待时间让脚本查询此控件是否存在
//如果没找到初始启动的搜索按钮则返回null,跳过搜书阶段(适用于已在阅读状态下运行此脚本)
if (w != null){
w.click();
//通过布局范围分析拿到需要的控件id和text属性以及边界范围,指定搜索书名自行修改
id("booksview_activity_search_edittext").findOne().setText("诡秘之主");
sleep(1000);
/*查询得到class:android.widget.TextView id:bookshelf_bookname边界(152,320,981,408),
随意点击x(153-980),y(321,407)范围内即可,此处点击正中央坐标*/
var widget = id("bookshelf_bookname").findOne().bounds();
click(widget.centerX(), widget.centerY());
sleep(1000);
}
break;
}
while(1){
//模拟一段仿生学滑屏曲线手势,当然您也可以直接一段粗暴的swipe滑动替代
var x1 = random (400,500);
var y1 = random (600,800);
var x2 = x1+random (-4,-2);
var y2 = y1+random(-8,-3);
var x3 = x2+random (-15,-10);
var y3 = y2+random(-10,-8);
var x4 = x3+random (-60,-30);
var y4 = y3+random(-5,0);
var x5 = x4+random (-100,-60);
var y5 = y4+random(0,5);
var x6 = x5+random (-150,-80);
var y6 = y5+random(8,15);
//设置一个回滚翻页随机触发器,模拟真实读书情况
var random_back = random (1,50);
var check= 8;
gesture (random(360,500),[x1,y1],[x2,y2],[x3,y3],[x4,y4],[x5,y5],[x6,y6]);
count = count + 1;
sleep(random(20000,25000));
/*30次翻页内随机执行回滚翻页的概率是1-0.98^30≈54.5%,
避免长时间后台闲置,此处做一个|或判断count>=30 */
if(check == random_back|count>=30){
//这是一个优雅的回滚翻页手势,做到了坐标的重复利用亦不失美感。
gesture (random(450,600),[x6,y6],[x5,y5],[x4,y4],[x3,y3],[x2,y2],[x1,y1]);
sleep(1000);
/*模拟切出起点看看时间喝喝茶,顺便将AutoJS唤到前台透透气,最长间隔是(500ms+25000ms)x30,
约为12分45秒,如果你后台死的快,自行调整间隔。 */
launch("org.autojs.autojs");
waitForPackage("org.autojs.autojs")
sleep(2000);
launch("com.qidian.QDReader");
waitForPackage("com.qidian.QDReader")
count =0;
sleep(random(2000,3000));
}
}
二、温馨提示
1.在其他app上执行手势等操作需要开启安卓的辅助功能,自行百度自己机型和安卓版本的开启方式
2.不确定高级版本安卓是否需要root权限执行
3.新版本的AutoJS因为法律原因作者关闭了辅助点击功能(可能),您使用前也请注意账号安全,防刷检测可能随时升级。
4.坐标位置我这是2k屏幕1440x2560竖屏位置匹配,您可能需要自己微调,或者使用固定自动匹配字符,比如w=screen.width之类的语句通用匹配。复杂界面查询控件代码高级用法需要组合布局层次分析找到具体层级深度参数,参考:
className("android.widget.LinearLayout").depth(15).drawingOrder(4).row(3).findOne().click();
5.请适度使用控制难度,避免索然无味
6.怀着敬畏之心,真正的大佬比你想象的要疯狂
7.同上,大佬的王者pk,一天不止1440分钟,1440只是入门,1441-1448分钟/天,才是大佬的竞技场,莫pk上火最后身心俱疲
8.每天2小时,做完1200分钟领完全部积分收益即可,下方示例图只是刷死对面这丫,此篇脚本诞生的万恶之源,切勿模仿
三、学而不厌
想学更多?分享一些大佬的脚本范例供参考学习:
以下代码源于autojs论坛:
auto.waitFor()
setScreenMetrics(1080, 2160);
//设置媒体音量
device.setMusicVolume(0)
threads.start(function(){
while(true){
id("img_close").findOne().click(
}
}
threads.start(function(){
while(true){
text("安全升级").findOne()
click("以后再说")}
})
//五小时之后,运行惠头条视频脚本
threads.start(function()
sleep(5.5*60*60*1000)
text("奇趣").findOne()
engines.execScriptFile("./惠头条视频.js");
exit()
})
threads.start(function(){
sleep(20000)
//设置亮度
//
device.setBrightnessMode(0)
sleep(1000)
device.setBrightness(3)
})
threads.start(function(){
//以下为子线程
//遇到加锁软件自动关
while(true)
id("confirm_lock_pattern_view").findOne()
back()
}
});
//遇到打开软件弹窗,则关闭
threads.start(function(){
while(true){id("img_close").findOne().click()}
})
//遇到忽略,点击忽
threads.start(function(){
while(true){text("忽略").findOne().click()
}
})
//如果遇到时段奖励,则领
threads.start(function(){
while(true){
text("奇趣").findOne()
click(943,139)
sleep(60*60*1000)
}
})
//遇到时段奖励的弹窗则关闭
threads.start(function(){
while(true){id("tv_click_more").findOne().click()
}
})
launchApp("惠头条")
sleep(11000)
while(true){
if(text("奇趣").exists())
sleep(2000)
swipe(611,361,611,953,1000)
sleep(3000)
click(560,1164)
}else
for(var g=0;g<20;g++){
sleep(4500)
swipe(300,900,300,700,500)
}
sleep(4500)
back()
}
sleep(1000)
}
以下趣头条脚本代码来源于autojs论坛
"auto";
//打开趣头条
app.launch("com.jifen.qukan");
//每隔1秒检测趣头条是否打开
waitForActivity("com.jifen.qkbase.main.MainActivity", 1000);
//获取任务按钮的位置
var renwu = id("com.jifen.qukan:id/jz").findOne().bounds();
//点击任务按钮
huqb_click(renwu, "点击任务按钮签到");
//点击头条按钮回到首页
var shouye = id("com.jifen.qukan:id/jv").findOne().bounds();
huqb_click(shouye, "点击首页按钮回到主页面");
for(var index=0;index<100;index++){
//如果时段奖励存在则领取时段奖励
if (className("android.widget.TextView").text("60").exists()) {
var lingqu = className("android.widget.TextView").text("60").findOne().bounds();
huqb_click(lingqu, "领取时段奖励");
}
//查找新闻位置
if (id("com.jifen.qukan:id/z0").findOne(6000) != null) {
var xinwen = id("com.jifen.qukan:id/z0").findOne(6000);
huqb_click(xinwen.bounds(), "查看新闻:" + xinwen.text());
sleep(random(1000, 3000));
//进入新闻开始阅读
if (id("com.jifen.qukan:id/fh").findOne(6000) != null) {
//阅读文章
for (var i = 0; i < 20; i++) {
var width = device.width;
var height = device.height;
var startX = random(100, width - 100);
var startY = random(height - 300, height - 100);
var endX = startX + random(-20, 20);
var endY = startY - random(500, 1000);
var swipeTime = random(1000, 3000);
swipe(startX, startY, endX, endY, swipeTime);
}
//返回首页
for (var i = 0; i < 10; i++) {
back();
sleep(1000);
if (id("com.jifen.qukan:id/jv").findOne(6000) != null) {
log("阅读文章完毕,返回到首页");
break;
}
}
waitForActivity("com.jifen.qkbase.main.MainActivity", 1000);
shouye = id("com.jifen.qukan:id/jv").findOne().bounds();
huqb_click(shouye, "点击刷新按钮刷新新闻");
};
} else {
//没有找到则刷新新闻
var shouye = id("com.jifen.qukan:id/jv").findOne().bounds();
huqb_click(shouye, "点击刷新按钮刷新新闻");
}
}
//自定义点击事件
function huqb_click(pos, msg) {
var x = pos.left;
var y = pos.top;
var width = pos.right - pos.left;
var height = pos.bottom - pos.top;
var tapX = x + random(10, width - 10);
var tapY = y + random(10, height - 10);
click(tapX, tapY);
sleep(random(1000, 3000));
log(msg);
}
沐泠的蚂蚁头条脚本:
"auto";
var max=dialogs.input("大约刷多少分钟",60);
var t=0;
var w=device.width,h=device.height;
waitForActivity("com.weishang.wxrd.activity.MainActivity");
function cha(){if(currentPackage()!="com.ldzs.zhangxin"){toast("结束"); exit();}}
while(t<1.3*max){
sleep(600);
id("tv_home_tab").findOne().click();
sleep(800+800*random());
var list=id("pull_list_view").findOnce();
if(list==null)continue;
for(var i=1;i<list.childCount();i++){
if(list.child(i)==null)continue;
if(list.child(i).find(textContains("广告")).size()!=0)continue;
list.child(i).click();
sleep(500);
if(currentActivity()=="com.bytedance.sdk.openadsdk.activity.TTRewardVideoActivity"){
idContains("tt_video_ad_close").waitFor();
var closebtn=idContains("tt_video_ad_close").findOnce();
sleep(random(500,1500));
closebtn.click();
sleep(random(800,1800));
continue;
}
if(currentActivity()=="com.uniplay.adsdk.InterstitialAdActivity"){
classNameContains("android.widget.ImageButton").waitFor();
var closebtn=classNameContains("android.widget.ImageButton").findOnce();
sleep(random(500,1500));
closebtn.click();
sleep(random(800,1800));
continue;
}
for(var j=0;j<11;j++){
sleep(2400+2400*random());
cha();
var r=random(0,20);
swipe(w/2+r,h*0.6+random(0,20),w/2+r,h*0.3+random(0,15),700+r*10);
}
cha();
back();
t++;
sleep(random(800,1800));
}
sleep(random(500,2000));
}
适用于安卓7.0以上,需打开无障碍模式
auto(); //辅助权限
console.show();
//按键监听
events.observeKey();
events.on("key_down", function(keyCode, events) {
//音量键关闭脚本
if (keyCode == keys.volume_up) {
exit();
}
});
toast("音量上键关闭脚本");
events.on("exit", function() {
device.cancelKeepingAwake();
toast("脚本停止,学习结束," + "时长" + i + "秒");
});
//打开学习强国app
app.launchPackage("cn.xuexi.android");
sleep(1000);
//设置屏幕常亮
device.keepScreenOn();
//点击学习主页
desc("工作").findOne().click();
sleep(500);
//desc("学习积分").findOne().click();
var 按钮位置=desc("学习积分").findOne().bounds();
click(按钮位置.centerX(),按钮位置.centerY());
sleep(500);
//var 任务列表=className("ListView").depth(19);
任务位置=textContains("文章学习时长").findOne().bounds();
console.log(任务位置);
click(任务位置.centerX(),任务位置.centerY());
//开始学习,每5秒显示学习时间
var i = 0;
var 计时 = setInterval(function() {
i = i + 5;
toast("已学习" + i + "秒");
}, 5000);
//设置总学习时长,默认是15分钟
setTimeout(function() {
clearInterval(计时);
device.cancelKeepingAwake();
toast("学习结束," + "时长" + i + "秒");
i = 0;
exit();
}, 15 * 60 * 1000);
四、渐入佳境
既然你耐心看到这了,我就把我琢磨两天的AutoJS常用功能分享一下,希望磕磕绊绊的摸索经历能对你有所启发,让你少走点弯路,如果你有更好的方法,欢迎留言交流!
- 逻辑分析整理
首先我们利用processon在线流程图理清思路
这是我最初的思路 ,也是目前初级版本实现的功能,除了存储我改用AutoJS自带的storages方法,其他基本上都沿着这个流程图走下来的,所以构思是非常重要的,在制作这张图之前,我对JS从未接触过,所以你也不用太过担心
- 模块分割,化整为零,各个击破
思维流程明白之后,我们将功能分离,主体就是两块,一块是自动阅读,一块是领取福利,判断分支依据就是 存储的当前日期记录;
这很简单,我们只需要在进入福利领取功能完毕后添加存储记录即可,而至于存储点具体触发位置,不用心急
这样两大块的功能模块就分离完毕了,我在上面的自动阅读脚本基础上,将自动阅读细分为三部分:
分支判断,自动搜书,自动阅读,预期做三个function,也就是构造函数,或者说方法,都行
而自动领取福利这块,初步定下五个部分:
日常翻倍10个币,再看15s拿20币,抽奖按钮分支,抽奖机抽奖,和广告观看模块
整体思路就比较清晰了
里面的逻辑难点,在于显示的“去抽奖”和抽奖机上的“按钮状态”。
经过反复观察(AutoJS自带的布局范围分析和布局层次分析组合),我发现去抽奖按钮有三个状态:
立即抽奖,机会+1,详情
而抽奖机上按钮也有三个状态:
“立即抽奖”,“看视频喜加一”,“明天再来”。
而困扰我的则是去抽奖>>抽奖机界面判断>>按下抽奖机按钮后>>抽奖或者到达观看广告页面>>广告观看完毕后回来抽奖机按钮状态发生变化,甚至如果“去抽奖”按钮是“机会+1”的时候,直接会与观看广告页面发生逻辑关系
这让我的function定位很是杂乱,加上状态的相互触发,我思考了switch,else分支,也思考了if else组合,也思考了function内做分支逻辑后套if else,或者做两个function一个触发分支,再与另一个含参构造函数搭配,或者考虑粗暴的for循环,是否可以和动态的按钮变化相呼应随机应变,但是考虑到会员卡和特殊活动,每天的抽奖机会是3-5甚至更多变化,for循环可操作性太死板,我首先排除了
而函数和switch以及if else如何组合,我一时没有主意。
在经过不断拆分功能和研究三个模块逻辑关系后,我把每个function需要实现的具体功能准确拆分定位后,使用何种组合和语法反而不重要或者说突然明朗了:
方案一:
if(去抽奖button) != text(详情) 则 去抽奖,else 返回读书;
不管外部从哪种状态来到抽奖机界面,我的抽奖机function内部做状态分支再执行;
方案二:
去抽奖button三个状态都做好,一一对应抽奖机三个状态,传入对应参数
我最后采用了方案二,而且去抽奖只做判断,抽奖机抽奖模式lottery方法内只做点击按钮startLottery功能,将等待抽奖不做函数,直接sleep 8秒,而看广告做成独立function,每一个抽奖结束后再次回到lottery方法后,就可以清楚明白的再次进行分支循环判断了
经验所得就是,循环逻辑关系,先接收拼接好,再内部拆分执行第二步的对应function专属功能,这样模块间关系就趋向简洁,模块独立的功能就能专心执行,算是低耦合,高内聚的思想雏形吧!
功能细化完毕,那么存储点的位置也清楚了,case 3最后说“明天再来”的状态后,保存当前日期记录进storage
- 细化功能逐个实现,开启调试修补完善
功能都确定完毕后,开始逐个命名实现了,具体的缝缝补补过程就不多说,相信你自己摸索体验更佳,这里放出两个半成品示例供参考:
一个是for循环执行抽奖机状态切换遍历的失败品
//立即抽奖模块
var lottery = className("android.view.View").text("立即抽奖").findOne(1000);
if (lottery != null){
click(lottery.bounds().centerX(), lottery.bounds().centerY());
//进入抽奖机页面
sleep(3000);
var lotteryBtn = className("android.view.View").text("抽 奖").findOne(1000);
if (lotteryBtn != null){
for (var num = 1; num < 5;num = num + 1){
click(lotteryBtn.bounds().centerX(), lotteryBtn.bounds().centerY());
sleep(10000);//等待抽奖结果
var viewAD = id("openid_list").findOne(1000);
if (viewAD != null ){
sleep(10000);//如果进入看视频增加抽奖次数页面,则等待视频播放
viewAD.click();
}
}
}
}
//当中途抽奖需要视频加一时
var lotteryAdd = className("android.view.View").text("机会+1").findOne(2000);
click(lotteryAdd.bounds().centerX(), lotteryAdd.bounds().centerY());
//进入抽奖机页面
sleep(3000);
var lotteryBtn2 = className("android.view.View").text("看视频抽奖喜+1").findOne(1000);
if (lotteryBtn2 != null){
for (var num2 = 1; num2 < 5;num2 = num2 + 1){
click(lotteryBtn2.bounds().centerX(), lotteryBtn2.bounds().centerY());
sleep(10000);//等待视频播放
var videoAD2 = id("openid_list").findOne(1000);
if(videoAD2 != null){
//如果没有视频次数则不操作
sleep(10000);
videoAD2.click();
}
}
一个是测试当前日期获取的毛坯状态,感兴趣的可以围观
//当前时间脚本调试
//console.show();
curTime = new Date();
log("当前时间是" + curTime.getFullYear() + "-" + (curTime.getMonth() + 1) + "-" + curTime.getDate() + "(周" + curTime.getDay() + ") " + curTime.getHours() + ":" + curTime.getMinutes() + ":" + curTime.getSeconds());
var dateRecord=curTime.getFullYear() + "-" + (curTime.getMonth() + 1) + "-" + curTime.getDate();
//log(dateRecord);
//files.write("/sdcard/脚本/dateRecord.txt", dateRecord);
- 化零为整,打磨抛光
各个模块实现细化完毕,过程用到java语法结构在线排错,java格式在线美化
基本上功能算是都能运转了
注意storages只能存储能JSON化的value,undefined的值需要先toString转换一下,然后对于Data未存储时偶入“去抽奖”一些分支造成的遗漏,补充一些连接逻辑和存储逻辑,最后优化一下自动搜索和阅读的执行逻辑,去掉自动搜索不必要的while循环,修改自动搜书使用 var widget = id("bookshelf_bookname").findOne().bounds();
搜索重复多个同id的书架书籍造成错误点击,优化为“布局层次查询”找到准确的位于书架上的书所属控件,点击进去就没问题了
最后将这个初代Pro脚本分享如下,虽然 还有定时120分钟读书后自动领取积分和每日推荐那随机出现的5个币我还没做脚本领取,不过至少框架还是非常够用了,再增加7天整除判断周日领取额外70币,差不多就够用了
因为不是主业,纯粹爱好初入Java语言编写脚本,语法还是非常幼稚,时间精力因为apk可能随时变动,短时间不准备再做更多功能了,相信你自己肯定能摸索出来大概,再自学下就能拿去自己升级premium版本了哈哈
//优化了抽奖逻辑,防止页面组件未正常更新;做了自定义挂机书名小功能
"auto"; //系统配置初始化
auto.waitFor();
/*测试正常后注释掉,log不再控制台显示,
从autoJs此脚本设置菜单可查询log.如不需要运行log,将所有log全部注释掉即可*/
//console.show();
//alert("本软件完全免费,请勿上当!")
var bookName = rawInput("请输入挂机的书名", "诡秘之主");
//初始化屏幕亮度
device.setBrightnessMode(0);
device.setBrightness(9);
//存储记录初始化
currentTime = new Date();
var currentDate = currentTime.getFullYear() + "-" + (currentTime.getMonth() + 1) + "-" + currentTime.getDate();
currentDate.toString();
var storage = storages.create("QDReaderCheck");
dateRecord = storage.get("Date");
log("检查当前日期:" + currentDate + "和记录日期:" + dateRecord);
log("初始化完毕");
//启动起点读书开始执行脚本功能
launch("com.qidian.QDReader");
waitForPackage("com.qidian.QDReader");
log("起点读书启动完毕");
sleep(7000);
var btnOk = id("btnOk").findOnce();
if (btnOk != null) {
btnOk.click();
sleep(1000);
}
if (currentDate == dateRecord) { //已有福利领取记录,则直接搜书自动阅读
log("进入读书模式");
searchBook();
autoRead();
} else { //否则执行今日福利领取*/
log("进入领取模式");
fanbei();
log("进入每日20点领取");
bonusPoints();
log("查询每日抽奖领取状态");
entryLottery();
//lottery();
}
//以上为全部执行模块
//以下是每个构造函数清单
//一、翻倍功能模块
function fanbei() {
//每日签到,找到当天的"翻倍"控件边界点击进入看视频界面
log("检查翻倍福利中…");
//var qiandao = className("android.widget.LinearLayout").depth(4).drawingOrder(4).row(-1).findOne(1000);
var qiandao = id("layoutBtn").findOne();
if (qiandao != null) {
click(qiandao.bounds().centerX(), qiandao.bounds().centerY());
sleep(2000);
back();
sleep(4000);
click(qiandao.bounds().centerX(), qiandao.bounds().centerY());
}
/* else{
var fuli = className("android.widget.TextView").text("今日福利").findOne(1000);
click(fuli.bounds().centerX(), fuli.bounds().centerY());
}
*/
sleep(4000);
var fanbei = className("android.view.View").depth(13).drawingOrder(0).row(-1).text("50点").findOnce();
if (fanbei != null) {
click(fanbei.bounds().centerX(), fanbei.bounds().centerY());
//观看视频16秒后关闭页面
closeAD();
}
}
//二、领取20点福利
function bonusPoints() {
//领取每日福利20点
log("检查每日福利20币领取中…");
var fuli20point1 = className("android.view.View").text("看15s视频,再领20点").findOnce();
var fuli20point2 = className("android.view.View").text("本周每天看视频,周日领大礼包").findOnce();
if (fuli20point1 != null) {
click(fuli20point1.bounds().centerX(), fuli20point1.bounds().centerY());
//观看视频16秒后关闭页面
closeAD();
} else if (fuli20point2 != null) {
click(fuli20point2.bounds().centerX(), fuli20point2.bounds().centerY());
//观看视频16秒后关闭页面
closeAD();
}
log("已领过每日福利了")
sleep(2000);
}
//三、进入抽奖机判断
function entryLottery() {
log("判断抽奖模式中…");
var lottery1 = className("android.view.View").text("立即抽奖").findOnce();
if (lottery1 != null) {
log("恭喜,直接前往领奖");
click(lottery1.bounds().centerX(), lottery1.bounds().centerY());
log("进入抽奖机页面");
lottery();
} else {
log("翻倍福利已领过了")
}
var lottery2 = className("android.view.View").text("机会+1").findOnce();
if (lottery2 != null) {
log("先看广告增加次数吧!");
click(lottery2.bounds().centerX(), lottery2.bounds().centerY());
//进入抽奖机页面
lottery();
}
var lottery3 = className("android.view.View").text("详情").findOnce();
if (lottery3 != null && currentDate !== dateRecord) {
log("奖领完了但是还未记录,前往存档…");
click(lottery3.bounds().centerX(), lottery3.bounds().centerY());
//进入抽奖机页面,进行存档
lottery();
} else {
log("没奖你进来干嘛?"); //理论上只有手动领完奖后第一次运行此脚本会进入此选项
storage.put("Date", currentDate);
back();
log("进入读书模式");
searchBook();
autoRead();
}
}
//四、抽奖功能模块
function lottery(choice) {
log("抽奖模式分析中…");
sleep(1000);
var lotteryBtn1 = className("android.view.View").text("抽 奖").findOnce();
var lotteryBtn2 = className("android.view.View").text("看视频抽奖喜+1").findOnce();
var lotteryBtn3 = className("android.view.View").text("明天再来").findOnce();
if (lotteryBtn1 != null) {
choice = 1;
log("设定抽奖模式一");
} else if (lotteryBtn2 != null) {
choice = 2;
log("设定抽奖模式二");
} else if (lotteryBtn3 != null) {
choice = 3;
log("设定抽奖模式三");
} else {
log("抽奖结束,进入自动阅读")
back();
sleep(1000);
searchBook();
autoRead();
}
sleep(1000);
switch (choice) {
case 1:
log("抽奖模式一,正在抽奖");
//var lotteryBtn1 = className("android.view.View").text("抽 奖").findOnce();
startLottery(lotteryBtn1);
sleep(4000);
var lotteryBtn = className("android.view.View").text("javascript:").findOne();
if (lotteryBtn != null) {
//console.show()
log("find btn");
click(lotteryBtn.bounds().centerX(), lotteryBtn.bounds().centerY());
log("clicked");
}
entryLottery();
break;
case 2:
log("抽奖模式二,前往观看广告…");
//var lotteryBtn2 = className("android.view.View").text("看视频抽奖喜+1").findOnce();
startLottery(lotteryBtn2);
closeAD();
sleep(500);
var lotteryBtn = className("android.view.View").text("javascript:").findOne();
if (lotteryBtn != null) {
//console.show()
log("find btn");
click(lotteryBtn.bounds().centerX(), lotteryBtn.bounds().centerY());
log("clicked");
}
entryLottery();
break;
case 3:
log("抽奖结束,保存领取记录…");
storage.put("Date", currentDate);
back();
sleep(1000);
log("准备自动阅读")
searchBook();
autoRead();
break;
}
}
//五、开始抽奖
function startLottery(lotteryBtn) {
//var lotteryBtn = id("btnLottery").findOne(2000);
//var lotteryBtn = className("android.view.View").depth(5).drawingOrder(0).row(-1).findOne(4000);
this.lotteryBtn = lotteryBtn;
if (lotteryBtn != null) {
click(lotteryBtn.bounds().centerX(), lotteryBtn.bounds().centerY());
log("抽奖中…");
}
}
//六、关闭广告
function closeAD() {
log("等待广告加载…");
var a1 = className("android.widget.ImageView").depth(1).drawingOrder(2).row(-1).exists();
var b1 = className("android.widget.ImageView").depth(1).drawingOrder(1).row(-1).exists();
if (a1 || b1) {
log("广告加载完毕,播放中…");
sleep(16000);
}
var a = className("android.widget.ImageView").depth(1).drawingOrder(2).row(-1).findOnce();
var b = className("android.widget.ImageView").depth(1).drawingOrder(1).row(-1).findOnce();
while (a == null && b == null) {
sleep(2000);
closeAD();
break;
}
if (a != null) {
log("发现广告关闭按钮a");
a.click();
} else if (b != null) {
log("发现广告关闭按钮b");
b.click();
}
}
//七、搜书功能
function searchBook() {
var w = id("btnTopSearch").findOne(1000);
if (w != null) {
w.click();
id("booksview_activity_search_edittext").findOne().setText(bookName);
//id("booksview_activity_search_edittext").findOne().setText("诡秘之主");
//var bookshell = className("android.widget.TextView").depth(4).drawingOrder(2).row(-1).findOne().bounds();//如果下方书架id搜索模式出现不兼容,可以用此条替换
var bookshelf = id("bookshelf_bookname").findOne().bounds();
click(bookshelf.centerX(), bookshelf.centerY());
sleep(1000);
}
}
//八、自动阅读模块
function autoRead() {
var count = 0;
while (1) {
var x1 = random(400, 500);
var y1 = random(600, 800);
var x2 = x1 + random(-4, -2);
var y2 = y1 + random(-8, -3);
var x3 = x2 + random(-15, -10);
var y3 = y2 + random(-10, -8);
var x4 = x3 + random(-60, -30);
var y4 = y3 + random(-5, 0);
var x5 = x4 + random(-100, -60);
var y5 = y4 + random(0, 5);
var x6 = x5 + random(-150, -80);
var y6 = y5 + random(8, 15);
var random_back = random(1, 50);
var check = 8;
log("开始自动阅读,请安心休息吧!");
gesture(random(360, 500), [x1, y1], [x2, y2], [x3, y3], [x4, y4], [x5, y5], [x6, y6]);
count = count + 1;
sleep(random(20000, 25000));
if (check == random_back || count >= 30) {
gesture(random(450, 600), [x6, y6], [x5, y5], [x4, y4], [x3, y3], [x2, y2], [x1, y1]);
sleep(1000);
launch("org.autojs.autojs");
waitForPackage("org.autojs.autojs");
sleep(2000);
launch("com.qidian.QDReader");
waitForPackage("com.qidian.QDReader");
count = 0;
sleep(random(2000, 3000));
}
}
}
"auto"; //系统配置初始化
auto.waitFor();
/*测试正常后注释掉,log不再控制台显示,
从autoJs此脚本设置菜单可查询log.如不需要运行log,将所有log全部注释掉即可*/
//console.show();
//alert("本软件完全免费,请勿上当!")
var bookName = rawInput("请输入挂机的书名", "诡秘之主");
//初始化屏幕亮度
device.setBrightnessMode(0);
device.setBrightness(9);
//setScreenMetrics(1440, 2560);
//存储记录初始化
currentTime = new Date();
var currentDate = currentTime.getFullYear() + "-" + (currentTime.getMonth() + 1) + "-" + currentTime.getDate();
currentDate.toString();
var storage = storages.create("QDReaderCheck");
dateRecord = storage.get("Date");
log("检查当前日期:" + currentDate + "和记录日期:" + dateRecord);
log("初始化完毕");
//启动起点读书开始执行脚本功能
launch("com.qidian.QDReader");
waitForPackage("com.qidian.QDReader");
log("起点读书启动完毕");
sleep(7000);
var btnOk = id("btnOk").findOnce();
if (btnOk != null) {
btnOk.click();
sleep(1000);
}
if (currentDate == dateRecord) { //已有福利领取记录,则直接搜书自动阅读
log("进入读书模式");
searchBook();
autoRead();
} else { //否则执行今日福利领取
log("进入领取模式");
fanbei();
log("进入每日20点领取");
bonusPoints();
log("查询每日抽奖领取状态");
entryLottery();
lottery();
}
//以上为全部执行模块
//以下是每个构造函数清单
//一、翻倍功能模块
function fanbei() {
//每日签到,找到当天的"翻倍"控件边界点击进入看视频界面
log("检查翻倍福利中…");
//var qiandao = className("android.widget.LinearLayout").depth(4).drawingOrder(4).row(-1).findOne(1000);
var qiandao=id("layoutBtn").findOne();
if (qiandao != null) {
click(qiandao.bounds().centerX(), qiandao.bounds().centerY());
sleep(2000);
back();
sleep(3000);
click(qiandao.bounds().centerX(), qiandao.bounds().centerY());
}
/* else{
var fuli = className("android.widget.TextView").text("今日福利").findOne(1000);
click(fuli.bounds().centerX(), fuli.bounds().centerY());
}
*/
sleep(4000);
var fanbei = className("android.view.View").depth(13).drawingOrder(0).row(-1).text("翻倍").findOnce();
if (fanbei != null) {
click(fanbei.bounds().centerX(), fanbei.bounds().centerY());
//观看视频16秒后关闭页面
closeAD();
}
}
//二、领取20点福利
function bonusPoints() {
//领取每日福利20点
log("检查每日福利20币领取中…");
var fuli20point = className("android.view.View").text("看15s视频,再领20点").findOnce();
if (fuli20point != null) {
click(fuli20point.bounds().centerX(), fuli20point.bounds().centerY());
//观看视频16秒后关闭页面
closeAD();
}
log("已领过每日福利了")
}
//三、进入抽奖机判断
function entryLottery() {
log("判断抽奖模式中…");
var lottery1 = className("android.view.View").text("立即抽奖").findOnce();
if (lottery1 != null) {
log("恭喜,直接前往领奖");
click(lottery1.bounds().centerX(), lottery1.bounds().centerY());
//进入抽奖机页面
sleep(3000);
lottery();
} else {
log("翻倍福利已领过了")
}
var lottery2 = className("android.view.View").text("机会+1").findOne(1000);
if (lottery2 != null) {
log("先看广告增加次数吧!");
click(lottery2.bounds().centerX(), lottery2.bounds().centerY());
//进入抽奖机页面
sleep(3000);
lottery();
}
var lottery3 = className("android.view.View").text("详情").findOne(1000);
if (lottery3 != null && currentDate !== dateRecord) {
log("奖领完了但是还未记录,前往存档…");
click(lottery3.bounds().centerX(), lottery3.bounds().centerY());
//进入抽奖机页面,进行存档
sleep(3000);
lottery();
} else {
log("没奖你进来干嘛?"); //理论上只有手动领完奖后第一次运行此脚本会进入此选项
storage.put("Date", currentDate);
back();
log("进入读书模式");
searchBook();
autoRead();
}
}
//四、抽奖功能模块
function lottery(choice) {
log("抽奖模式分析中…");
sleep(2000);
var lotteryBtn1 = null;
var lotteryBtn2 = null;
var lotteryBtn3 = null;
var lotteryBtn1 = className("android.view.View").text("抽 奖").findOnce();
var lotteryBtn2 = className("android.view.View").text("看视频抽奖喜+1").findOnce();
var lotteryBtn3 = className("android.view.View").text("明天再来").findOnce();
if (lotteryBtn1 != null) {
choice = 1;
log("设定抽奖模式一");
} else if (lotteryBtn2 != null) {
choice = 2;
log("设定抽奖模式二");
} else if (lotteryBtn3 != null) {
choice = 3;
log("设定抽奖模式三");
} else {
log("抽奖结束,进入自动阅读")
back();
sleep(1000);
searchBook();
autoRead();
}
sleep(1000);
switch (choice) {
case 1:
log("抽奖模式一,正在抽奖");
//var lotteryBtn1 = className("android.view.View").text("抽 奖").findOnce();
startLottery(lotteryBtn1);
sleep(6000);
lottery();
break;
case 2:
log("抽奖模式二,前往观看广告…");
//var lotteryBtn2 = className("android.view.View").text("看视频抽奖喜+1").findOnce();
startLottery(lotteryBtn2);
closeAD();
lottery();
break;
case 3:
log("抽奖结束,保存领取记录…");
storage.put("Date", currentDate);
back();
sleep(1000);
log("准备自动阅读")
searchBook();
autoRead();
break;
}
}
//五、开始抽奖
function startLottery(lotteryBtn) {
//var lotteryBtn = id("btnLottery").findOne(2000);
//var lotteryBtn = className("android.view.View").depth(5).drawingOrder(0).row(-1).findOne(4000);
this.lotteryBtn = lotteryBtn;
if (lotteryBtn != null) {
click(lotteryBtn.bounds().centerX(), lotteryBtn.bounds().centerY());
log("抽奖中…");
}
}
//六、关闭广告
function closeAD() {
log("等待广告加载…");
var a1 = className("android.widget.ImageView").depth(1).drawingOrder(2).row(-1).exists();
var b1 = className("android.widget.ImageView").depth(1).drawingOrder(1).row(-1).exists();
if (a1 || b1) {
log("广告加载完毕,播放中…");
}
var a = className("android.widget.ImageView").depth(1).drawingOrder(2).row(-1).findOnce();
var b = className("android.widget.ImageView").depth(1).drawingOrder(1).row(-1).findOnce();
while (a == null && b == null) {
sleep(2000);
closeAD();
break;
}
if (a != null) {
log("发现广告关闭按钮a");
sleep(16000);
a.click();
} else if (b != null) {
log("发现广告关闭按钮b");
sleep(16000);
b.click();
}
}
//七、搜书功能
function searchBook() {
var w = id("btnTopSearch").findOne(1000);
if (w != null) {
w.click();
id("booksview_activity_search_edittext").findOne().setText(bookName);
//var bookshell = className("android.widget.TextView").depth(4).drawingOrder(2).row(-1).findOne().bounds();
var bookshelf =id("bookshelf_bookname").findOne().bounds();
click(bookshelf.centerX(), bookshelf.centerY());
sleep(1000);
}
}
//八、自动阅读模块
function autoRead() {
var count = 0;
while (1) {
var x1 = random(400, 500);
var y1 = random(600, 800);
var x2 = x1 + random(-4, -2);
var y2 = y1 + random(-8, -3);
var x3 = x2 + random(-15, -10);
var y3 = y2 + random(-10, -8);
var x4 = x3 + random(-60, -30);
var y4 = y3 + random(-5, 0);
var x5 = x4 + random(-100, -60);
var y5 = y4 + random(0, 5);
var x6 = x5 + random(-150, -80);
var y6 = y5 + random(8, 15);
var random_back = random(1, 50);
var check = 8;
log("开始自动阅读,请安心休息吧!");
gesture(random(360, 500), [x1, y1], [x2, y2], [x3, y3], [x4, y4], [x5, y5], [x6, y6]);
count = count + 1;
sleep(random(20000, 25000));
if (check == random_back || count >= 30) {
gesture(random(450, 600), [x6, y6], [x5, y5], [x4, y4], [x3, y3], [x2, y2], [x1, y1]);
sleep(1000);
launch("org.autojs.autojs");
waitForPackage("org.autojs.autojs");
sleep(2000);
launch("com.qidian.QDReader");
waitForPackage("com.qidian.QDReader");
count = 0;
sleep(random(2000, 3000));
}
}
}
"auto" //系统配置初始化
auto.waitFor();
/*测试正常后注释掉,log不再控制台显示,
从autoJs此脚本设置菜单可查询log.如不需要运行log,将所有log全部注释掉即可*/
console.show();
device.setBrightnessMode(0);
device.setBrightness(9);
setScreenMetrics(1440, 2560);//可不设置,理论上自适应各个主流分辨率
//存储记录初始化
currentTime = new Date();
var currentDate = currentTime.getFullYear() + "-" + (currentTime.getMonth() + 1) + "-" + currentTime.getDate();
currentDate.toString();
var storage = storages.create("QDReaderCheck");
dateRecord = storage.get("Date");
log("初始化完毕");
log("检查当前日期:" + currentDate + "和记录日期:" + dateRecord);
//启动起点读书开始执行脚本功能
launch("com.qidian.QDReader");
waitForPackage("com.qidian.QDReader");
log("起点读书启动完毕");
sleep(7000);
var btnOk =id("btnOk").findOnce();
if (btnOk != null){
btnOk.click();
sleep(1000);
}
if (currentDate == dateRecord) { //已有福利领取记录,则直接搜书自动阅读
log("进入读书模式");
searchBook();
autoRead();
} else { //否则执行今日福利领取
log("进入领取模式");
fanbei();
log("进入每日20点领取");
bonusPoints();
log("查询每日抽奖领取状态");
entryLottery();
lottery();
}
//以上为全部执行模块
//以下是每个构造函数清单
//一、翻倍功能模块
function fanbei() {
//每日签到,找到当天的"翻倍"控件边界点击进入看视频界面
log("检查翻倍福利中…");
var qiandao = className("android.widget.LinearLayout").depth(4).drawingOrder(4).row(-1).findOne(1000);
if (qiandao != null) {
click(qiandao.bounds().centerX(), qiandao.bounds().centerY());
sleep(1000);
back();
sleep(3000);
click(qiandao.bounds().centerX(), qiandao.bounds().centerY());
}
/* else{
var fuli = className("android.widget.TextView").text("今日福利").findOne(1000);
click(fuli.bounds().centerX(), fuli.bounds().centerY());
}
*/
sleep(4000);
var fanbei = className("android.view.View").depth(13).drawingOrder(0).row(-1).findOne(1000);
if (fanbei != null) {
click(fanbei.bounds().centerX(), fanbei.bounds().centerY());
//观看视频16秒后关闭页面
closeAD();
}
}
//二、领取20点福利
function bonusPoints() {
//领取每日福利20点
log("检查每日福利20币领取中…");
var fuli20point = className("android.view.View").text("看15s视频,再领20点").findOne(1000);
if (fuli20point != null) {
click(fuli20point.bounds().centerX(), fuli20point.bounds().centerY());
//观看视频16秒后关闭页面
closeAD();
}
}
//三、进入抽奖机判断
function entryLottery() {
log("判断抽奖模式中…");
var lottery1 = className("android.view.View").text("立即抽奖").findOne(1000);
if (lottery1 != null) {
log("恭喜,直接前往领奖");
click(lottery1.bounds().centerX(), lottery1.bounds().centerY());
//进入抽奖机页面
sleep(3000);
lottery(1);
}
var lottery2 = className("android.view.View").text("机会+1").findOne(1000);
if (lottery2 != null) {
log("先看广告增加次数吧!");
click(lottery2.bounds().centerX(), lottery2.bounds().centerY());
//进入抽奖机页面
sleep(3000);
lottery(2);
}
var lottery3 = className("android.view.View").text("详情").findOne(1000);
if (lottery3 != null && currentDate !== dateRecord) {
log("奖领完了但是还未记录,前往存档中…");
click(lottery3.bounds().centerX(), lottery3.bounds().centerY());
//进入抽奖机页面
sleep(3000);
lottery(3);
} else {
log("没奖你进来干嘛?"); //理论上只有手动领完奖后第一次运行此脚本会进入此选项
storage.put("Date", currentDate);
back();
log("进入读书模式");
searchBook();
autoRead();
}
}
//四、抽奖功能模块
function lottery(choice) {
log("抽奖模式分析中…");
var lotteryBtn1 = className("android.view.View").text("抽 奖").findOne(1000);
if (lotteryBtn1 != null) {
choice = 1;
log("设定抽奖模式一");
}
var lotteryBtn2 = className("android.view.View").text("看视频抽奖喜+1").findOne(1000);
if (lotteryBtn2 != null) {
choice = 2;
log("设定抽奖模式二");
}
var lotteryBtn3 = className("android.view.View").text("明天再来").findOne(1000);
if (lotteryBtn3 != null) {
choice = 3;
log("设定抽奖模式三");
}
switch (choice) {
case 1:
log("抽奖模式一,正在抽奖");
var lotteryBtn1 = className("android.view.View").text("抽 奖").findOne(1000);
startLottery(lotteryBtn1);
sleep(8000);
var lotteryBtn1 = null;
sleep(1000);
lottery();
break;
case 2:
log("抽奖模式二,前往观看广告…");
var lotteryBtn2 = className("android.view.View").text("看视频抽奖喜+1").findOne(1000);
startLottery(lotteryBtn2);
var lotteryBtn2 = null;
closeAD();
sleep(1000); //稍等抽奖按钮从喜加一刷新为"抽奖",从而获得准确的抽奖模式
lottery();
break;
case 3:
log("抽奖结束,保存领取记录…");
storage.put("Date", currentDate);
back();
break;
}
}
//五、开始抽奖
function startLottery(lotteryBtn) {
//var lotteryBtn = id("btnLottery").findOne(2000);
//var lotteryBtn = className("android.view.View").depth(5).drawingOrder(0).row(-1).findOne(4000);
this.lotteryBtn = lotteryBtn;
if (lotteryBtn != null) {
click(lotteryBtn.bounds().centerX(), lotteryBtn.bounds().centerY());
log("抽奖中…");
}
}
//六、关闭广告
function closeAD() {
log("等待广告加载…");
var a1 = className("android.widget.ImageView").depth(1).drawingOrder(2).row(-1).exists();
var b1 = className("android.widget.ImageView").depth(1).drawingOrder(1).row(-1).exists();
if (a1 || b1) {
log("广告加载完毕,播放中…");
}
var a = className("android.widget.ImageView").depth(1).drawingOrder(2).row(-1).findOnce();
var b = className("android.widget.ImageView").depth(1).drawingOrder(1).row(-1).findOnce();
while (a == null && b == null) {
sleep(2000);
closeAD();
break;
}
if (a != null) {
log("发现广告关闭按钮a");
sleep(16000);
a.click();
} else if (b != null) {
log("发现广告关闭按钮b");
sleep(16000);
b.click();
}
}
//七、搜书功能
function searchBook() {
var w = id("btnTopSearch").findOne(1000);
if (w != null) {
w.click();
id("booksview_activity_search_edittext").findOne().setText("诡秘之主");
sleep(1000);
var widget = className("android.widget.TextView").depth(4).drawingOrder(2).row(-1).findOne().bounds();
click(widget.centerX(), widget.centerY());
sleep(1000);
}
}
//八、自动阅读模块
function autoRead() {
var count = 0;
while (1) {
var x1 = random(400, 500);
var y1 = random(600, 800);
var x2 = x1 + random(-4, -2);
var y2 = y1 + random(-8, -3);
var x3 = x2 + random(-15, -10);
var y3 = y2 + random(-10, -8);
var x4 = x3 + random(-60, -30);
var y4 = y3 + random(-5, 0);
var x5 = x4 + random(-100, -60);
var y5 = y4 + random(0, 5);
var x6 = x5 + random(-150, -80);
var y6 = y5 + random(8, 15);
var random_back = random(1, 50);
var check = 8;
log("开始自动阅读,请安心休息吧!");
gesture(random(360, 500), [x1, y1], [x2, y2], [x3, y3], [x4, y4], [x5, y5], [x6, y6]);
count = count + 1;
sleep(random(20000, 25000));
if (check == random_back || count >= 30) {
gesture(random(450, 600), [x6, y6], [x5, y5], [x4, y4], [x3, y3], [x2, y2], [x1, y1]);
sleep(1000);
launch("org.autojs.autojs");
waitForPackage("org.autojs.autojs");
sleep(2000);
launch("com.qidian.QDReader");
waitForPackage("com.qidian.QDReader");
count = 0;
sleep(random(2000, 3000));
}
}
}
对了,进阶功能的实现可是费了我两三天的时间,所以不要觉得自己学了半个小时做不出来就灰心,开头那话说半个小时写出来的是装逼的 ,学习新语言很辛苦的,大家都一样,勤能补拙吧,加油~
5 comments
大佬,你这个是在哪里运行的啊
AutoJS,文中官方文档链接那有软件下载地址
好的,感谢
试用了一下作者的脚本,发现在 Android 7.0 以下的版本无法正常使用 click 和 gesture 函数,如果要适配的话最好还是用 RootAutomator 的方法来模拟操作... (蓝绿大厂不会给你升级 Android 系统版本的机会)
click 用 RootAutomator.tap 来替代,gesture 的话可以用 RootAutomator.swipe 来替代(多次调用这个函数就可以了,因为 swipe 这个函数是异步的,最好每调用一次再 sleep 一下)
支持作者!
是的,模拟手势这些操作是需要安卓7以上版本的,脚本主要提供的是框架和逻辑,能帮忙降低入门难度,分享的意义就达到了。rootAutomator似乎必须要root,模拟点击是最简单的,不过对于坐标匹配不普适,适合针对单独一台手机配置。AutoJS我也只是兴趣一时折腾,很多知识点都不太明白,感谢大佬分享!