autojs之每日上报2.0-超繁版(多线程实现)

时隔一年,我们还要每日打卡,一年来肯定有所进步,于是再写一遍,完善一下这个脚本。

文章目录


前言

此版本较第一版速度更快,容错更多,顺便锻炼了自己的多线程运用能力


运行效果:

哔哩哔哩: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(多线程版)

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);
        }
})

完整代码在gitee,点击跳转

总结

此脚本较第一版,通过亮屏解锁线程线程,添加了对亮屏失败的容错;
之后通过waitForPackage(“com.tencent.mm”)代替sleep函数使程序不用无必要等待;
添加了打印日期的代码,

var myDate = new Date();
console.info(myDate.getMonth() + 1 + '月' + myDate.getDate() + '日' + '-开始打卡');

通过 判断当前页面()的函数,能更好的对程序进行控制;
通过主页面线程,检测微信是否在主页面,并返回到主页面;
通过弹窗检测线程,检测弹窗;
对提交失败的几种情况进行了容错处理。

上一篇:事件委托版留言板


下一篇:叒Exception了嗷: java.lang.ClassNotFoundException com.Xxxx.Xxxx