最近在写脚本的时候,发现定时脚本会发生auto.js在后台运行,导致手机无法自动熄屏的问题(毕竟大家写定时脚本都是为了方便,比如在不需要使用手机的时候完成一些重复性操作...)。但是我们又不能直接停止运行auto.js,那你第一个脚本爽完了,其他的脚本兄弟咋办。

        众所周知,“用安卓手机的男人都是好男人,因为每天晚上都要回家充电”(bushi)。安卓手机的电量可是很宝贵的,所以为了解决这个问题。我就去网上查阅了一些资料,发现大部分自动熄屏操作在不对手机进行root的前提下都非常繁琐。可是大家写脚本不就是为了偷懒嘛,这么麻烦的操作有违初衷啊。

        机智的我想到了一个以前上课偷摸玩手机时候喜欢用的一个小部件——“一键锁屏”,用最简单的方式实现这一功能

开始尝试

        首先,我在华为手机上进行了测试。发现只要“一键锁屏”这个小部件,位于桌面的第一层,那么Auto.js就可以直接通过text,识别出这个小部件,并且进行点击。

        因此,我们只需要在脚本运行结束后,使用home()返回桌面,便可以直接实现 “脚本结束,对手机屏幕进行熄屏” 的操作。

        需要注意的是,以下方法的实现,都需要将“一键锁屏”小部件放置在手机桌面的第一层,不能将其摆放至文件夹收纳起来。

        有趣的是,在这台华为手机上进行测试的时候。不管屏幕内是否存在“一键锁屏”小部件,auto.js都可以对“一键锁屏”的文本进行识别点击,达到熄屏的效果,可以说是非常方便给力了。下面是多次测试成功的代码:

/**
 * 结束脚本后,是否需要一键锁屏
 * 请填入"yes"或"no"(默认为"yes")
 * 此功能需要在手机桌面第一层放置“一键锁屏”部件或应用
 */
var need_lock = "yes";

// 屏幕是否为锁定状态
function isDeviceLocked() {
    importClass(android.app.KeyguardManager);
    importClass(android.content.Context);
    var km = context.getSystemService(Context.KEYGUARD_SERVICE);
    return km.isKeyguardLocked();
}

/**
 * 熄灭屏幕
 * 自动熄屏功能需要在手机桌面第一层放置“一键锁屏”部件或应用
 */
function lockScreen() {
    log("亮度模式:自动");
    log("取消设备常亮...");
    device.setBrightnessMode(1); // 自动亮度模式
    device.cancelKeepingAwake(); // 取消设备常亮

    // 震动一秒
    toast('脚本运行完毕!');
    device.vibrate(1000);
    sleep(1000);

    if (need_lock == "yes" && !isDeviceLocked()) {
        text("一键锁屏").waitFor();
        click("一键锁屏");
        sleep(1000);
    }
}

发现问题,进行优化

        而正当我以为大功告成的时候,手贱用了另一台vivo手机进行测试。哦吼,寄!

        在这部vivo手机上,出现了一个问题——auto.js虽然可以识别到 “一键锁屏” 的text文本,但却无法对其进行点击。

        所以我们改变思路:既然这个控件我们无法正常对其点击,那么我们是否可以利用坐标的形式对其进行操作呢?于是乎,优化版本的锁屏函数便出现了:

        在这个版本中,首先尝试是否可以像之前的华为手机一样,直接无视页面识别出“一键锁屏” 的text文本并进行点击;如果识别到第一种锁屏方案失败了,屏幕仍未处于锁屏状态,就切换到第二种方案——


        首先,判断桌面上“一键锁屏”的坐标。


        之后,根据坐标的大小,判断“一键锁屏”是位于当前页面的左侧还是右侧,并进行滑动操作


        最后,若“一键锁屏”处于当前页面,则直接根据坐标进行点击操作,实现熄屏操作。

        需要注意的是, 这里原本我使用的是识别出“一键锁屏”的控件后,通过它的上下左右属性随机出一个点击坐标进行点击(毕竟是脚本操作,习惯性的想偏移坐标了)。但是我发现,如果使用控件内随机坐标,会出现点击失败的情况,并且概率非常大

        又因为这里并不会有被识别脚本的风险,所以最后我没有花精力去找合适的偏移坐标,而是直接使用了它的中心坐标。

        我猜测,在vivo手机这里的点击范围仅限于它的图标范围,感兴趣的同学可以用不同的手机去尝试(虽然好像也没什么很大的必要)。

/**
 * 熄灭屏幕
 * 自动熄屏功能需要在手机桌面第一层放置“一键锁屏”部件或应用
 */
function lockScreen() {
    log("亮度模式:自动");
    log("取消设备常亮...");
    device.setBrightnessMode(1); // 自动亮度模式
    device.cancelKeepingAwake(); // 取消设备常亮

    // 震动一秒
    toast('脚本运行完毕!');
    device.vibrate(1000);
    sleep(1000);

    if (need_lock == "yes" && !isDeviceLocked()) {
        text("一键锁屏").waitFor();
        click("一键锁屏");
        sleep(1000);

        if (!isDeviceLocked()) {
            log('快捷锁屏失败,切换方案...')

            // 获取 “一键锁屏” 小部件的坐标
            var lockBtn_X, lockBtn_Y;
            function get_btnxy() {
                text("一键锁屏").waitFor();
                let lockBtn = text("一键锁屏").findOne().bounds();
                lockBtn_X = (lockBtn.left + lockBtn.right) / 2;
                lockBtn_Y = (lockBtn.top + lockBtn.bottom) / 2;
            }

            get_btnxy();
            // 根据坐标判断 “一键锁屏” 小部件在当前页面的左侧还是右侧
            while (lockBtn_X < 0 || lockBtn_X > device.width) {
                get_btnxy();

                if (lockBtn_X < 0) {
                    swipe(device.width * 1 / 4, device.height * 5 / 6, device.width * 3 / 4, device.height * 5 / 6, 200);
                    continue;
                }
                else if (lockBtn_X > device.width) {
                    swipe(device.width * 3 / 4, device.height * 5 / 6, device.width * 1 / 4, device.height * 5 / 6, 200);
                    continue;
                }
            }
            get_btnxy();
            click(lockBtn_X, lockBtn_Y);
        }
    }
}

一些思路

        当然,我仅仅只是测试了两部不同品牌的手机,更别说还要同品牌不同型号,或者更多不同品牌的手机。或许也会出现下面这些情况,我也给大家提供一些思路,抛砖引玉:

        “一键锁屏”不在当前页面就无法识别 的情况:


        可以直接把“一键锁屏”放在主页面,使用home()回到主页面进行识别点击;


        亦或者,为函数加上一个page_num参数,代表桌面存在page_num张页面。左滑动page_num次,右滑动page_num次。来回两趟,对全部页面遍历进行识别。

        手机没有“一键锁屏”小部件,或是不想在桌面放置“一键锁屏”小部件:


        我的解决思路还是一如既往的暴力(嘿嘿),如果是没有“一键锁屏”这个小部件 或者 为了美观不想将其摆放在桌面第一层。我们可以直接从应用商店下载一个“一键锁屏”的应用啊,直接使用别人打包好的功能不香嘛(狗头)。


        之后的思路就很清晰啦,脚本运行完毕后直接launchApp就可以了。

        (也有可能是我想当然了,毕竟没有实际进行过操作测试,仅仅只是提供一个思路哦)

        我也是才接触auto.js不久,希望这篇文章可以给大家提供一些思路或是帮助。

        如果觉得这篇文章对你有帮助的话,希望可以点赞关注支持一下,也希望大家在评论区给我留言,互相交流学习(当然也可能是我单方面向大佬学习orz)。