时隔一年,我们还要每日打卡,一年来肯定有所进步,于是再写一遍,完善一下这个脚本。
文章目录
前言
此版本较第一版速度更快,容错更多,顺便锻炼了自己的多线程运用能力
运行效果:
哔哩哔哩:https://www.bilibili.com/video/BV1544y127SM/
<iframe allowfullscreen="true" data-mediaembed="bilibili" id="Fn39uO7Q-1626494967031" src="https://player.bilibili.com/player.html?aid=974159411"></iframe>autojs之每日上报2.0(多线程版)
一、亮屏解锁线程
auto.waitFor()
检查无障碍服务是否已经启用,如果没有启用则跳转到无障碍服务启用界面,并等待无障碍服务启动;
当无障碍服务启动后脚本会继续运行。
auto.waitFor() //打开无障碍服务后会继续运行脚本
//检测黑屏,亮屏解锁
var 亮屏解锁线程 = threads.start(function () {
while (1) {
console.verbose('子线程亖:亮屏解锁');
/*判断屏幕锁定,解锁屏幕(数字密码)*/
if (!device.isScreenOn()) {//息屏状态将屏幕唤醒
device.wakeUp();//唤醒设备
sleep(500); // 等待屏幕亮起
/*如果晚上有人发消息,上滑不能打开输密码界面,需要返回一次后上滑 */
back()
sleep(1000);
swipe(700, 1900, 700, 450, 300);//上滑
sleep(400);
/*没有到密码界面时,findOne会阻塞,手动到达密码界面后,脚本会继续运行 */
/*findOnce()不会阻塞 */
//解锁 密码123456
if(desc(5).findOnce()) desc(5).findOnce().click();
if(desc(0).findOnce()) desc(0).findOnce().click();
if(desc(5).findOnce()) desc(5).findOnce().click();
if(desc(4).findOnce()) desc(4).findOnce().click();
if(desc(4).findOnce()) desc(4).findOnce().click();
if(desc(3).findOnce()) desc(3).findOnce().click();
//等待解锁完成,返回并退出
sleep(400);
}
else{
break;
}
//不在这里判断,是因为有可能没有正确解锁,然后息屏,故不能终止该线程,要在打开微信后终止
/*并不能很好的判断屏幕是否解锁 orz 如有更好想法的欢迎讨论*/
sleep(10000);
}
})
二、弹窗检测
//子线程三
threads.start(function () {
setInterval(function () {
console.verbose('子线程三:弹窗检测');
if(id("com.android.systemui:id/alertTitle").exists()){
console.verbose('出现弹窗');
click("取消")
}
}, 2000)
});
三、主线程
亮屏解锁线程.waitFor();//等待线程开始执行。
//等待该线程4s,若不加此代码,只要一亮屏,下面代码就会运行,微信打开,此线程就结束了,不能正确解锁
亮屏解锁线程.join(4000);//此后的代码都不运行
console.verbose("此后的代码都不运行,只有当亮屏解锁线程执行4s后,才继续运行")
var myDate = new Date();
console.info(myDate.getMonth() + 1 + '月' + myDate.getDate() + '日' + '-开始打卡');
if (currentPackage().search("com.tencent.mm") == -1) {//当前 APP 不是微信
console.verbose("当前活动:" + currentPackage())
launchApp("微信");
log('正在打开微信');
}
else toastLog("当前活动:微信")
waitForPackage("com.tencent.mm")//等待当前活动是微信后,继续运行
console.show() //控制台
console.setPosition(400, 100);
四、判断当前页面函数
function 判断当前页面() {
//登录页面
登录 = className("android.widget.Button").text("登录").findOnce()
找回密码 = className("android.widget.Button").text("找回密码").findOnce()
//主页面
搜索 = id("f8y").findOnce()//he6
更多 = id("ef9").findOnce()//gdh
//公众号聊天页面
名称 = className("android.widget.TextView").id("gas").findOnce()//className("android.widget.LinearLayout").id("ipv").findOnce()
消息 = className("android.widget.ImageView").desc("消息").findOnce()
服务按钮 = className("android.widget.ImageView").desc("服务按钮").findOnce()
//聊天页面
切换到按住说话 = className("android.widget.ImageButton").desc("切换到按住说话").findOnce()
切换到键盘 = className("android.widget.ImageButton").desc("切换到键盘").findOnce()
//资料页面
发消息 = className("android.widget.LinearLayout").text("发消息").findOnce()
微信号 = className("android.widget.TextView").textContains("微信号").findOnce()//id("bd_")//b2f
//公众号页面
返回 = className("android.widget.ImageView").desc("返回").findOnce()
//jsname= className("android.view.View").id("js_name").findOnce()//找不到
//publishtime= className("android.view.View").id("publish_time").findOnce()//找不到
/*
//不懂为什么 可以分析出控件,但是子控件里找不到
className("android.view.View").findOne().children()
.forEach(function(child){
log(child.id());
});
//不懂为什么用text可以找id,用id找不到控件
var b=className("android.view.View").text("程序员").findOne();
if(b) toastLog(b.id());
*/
//订阅号页面
常读的订阅号 = className("android.widget.TextView").text("常读的订阅号").findOnce()
if (登录 && 找回密码) return "登录页面"
else if (搜索 && 更多) return "主页面"
else if (名称 && (消息 || 服务按钮)) return "公众号聊天页面"
else if (名称 && (切换到按住说话 || 切换到键盘)) return "聊天页面"
else if (发消息 && 微信号) return "资料页面"
else if (返回 && 常读的订阅号) return "订阅号页面"
else if (返回) return "公众号页面"
else {
sleep(1000)
return "其他"
}
}
五、主页面线程
//检测当前页面,回到主页面
var 主页面线程 = threads.start(function () {
while (true) {
console.verbose('子线程一:主页面');
当前页面 = 判断当前页面()
toastLog(当前页面)
if (当前页面 == "登录页面") {
toastLog("登录页面")
input("505443211.")
do { sleep(1000) } while (!click("登录"));
}
else if (当前页面 == "其他") { //黑屏和锁屏页面时会判断为其他
}
else if (当前页面 != "主页面") {
back()
}
else if (当前页面 == "主页面") {
主页面线程.interrupt()
console.verbose("主页面线程停止")
亮屏解锁线程.interrupt()
console.verbose("亮屏解锁线程停止")
}
sleep(1000)
}
})
//等待该线程完成
主页面线程.join();//此后的代码都不运行
//toastLog("主页面线程.join();//此后的代码都不运行,只有当主页面线程wan后,才继续运行")
六、子线程二:后继操作
//子线程二
threads.start(function () {
console.verbose('子线程二:后继操作');
if (!主页面线程.isAlive()) {
while (!click("通讯录"));//因为是while(),所以只要没有点击到文字,就会一直循环
while (!click("中国海大"));
while (!click("每日上报"));
while (!click("每日填报"));
className("android.widget.EditText").depth(9).click()//不能点击,页面会跳转到获取位置的文本框
toastLog('点击获取位置'); sleep(2000);
位置文本框 = className("android.widget.EditText").depth(9).findOnce().bounds() //21
click(位置文本框.centerX(), 位置文本框.centerY());
/*
//定位服务未打开
if (text("获取位置信息失败").findOnce()) {
//text("确定").findOnce().click();
console.error("获取位置信息失败!");
var intent = new Intent();
intent.setAction("android.settings.LOCATION_SOURCE_SETTINGS"); //定位服务设置
app.startActivity(intent);
click(1000, 360)//打开定位服务
while (!className("android.widget.EditText").textContains("定位权限")) {
sleep(500);
}
back();sleep(500);
click(位置文本框.centerX(), 位置文本框.centerY());
toastLog('重新获取位置'); sleep(5000);
}
*/
click(735, 1373); //点击确定,好像授权过,之后就不用再重复授权了
toast('已确定');
while (!className("android.widget.EditText").textContains("河南省") && !className("android.widget.EditText").textContains("山东省")) {
toastLog('等待位置获取完成');
sleep(500);
}
do{
sleep(1500);
while (!click("提交信息")); //点击提交信息
sleep(500);
if (className("android.view.View").textContains("未获取到地理位置").findOnce()) {
console.error("未获取到地理位置")
text("确定").findOnce().click();
}
else {
if (text("每天只能填报一次,请确认信息是否全部正确?").findOnce()) {
text("确认").findOnce().click();
console.info("打卡完成")
//返回主页面
while (currentActivity() != "com.tencent.mm.ui.LauncherUI") {
sleep(500)
back()
}
exit()
}
else if (text("确定").findOnce())
{
if (text("每天只能填报一次,你已提交过").findOnce())
console.error("每天只能填报一次,你已提交过")
else
console.error("未正确提交")
break
}
}
}while(1);
}
})
总结
此脚本较第一版,通过亮屏解锁线程线程,添加了对亮屏失败的容错;
之后通过waitForPackage(“com.tencent.mm”)代替sleep函数使程序不用无必要等待;
添加了打印日期的代码,
var myDate = new Date();
console.info(myDate.getMonth() + 1 + '月' + myDate.getDate() + '日' + '-开始打卡');
通过 判断当前页面()的函数,能更好的对程序进行控制;
通过主页面线程,检测微信是否在主页面,并返回到主页面;
通过弹窗检测线程,检测弹窗;
对提交失败的几种情况进行了容错处理。