const img = captureScreen();OCR截图,在部分手机下,一加13,红米k60U,首次打开脚本,开始,然后授权截图权限,脚本正常跑没问题,但是,如果这时候手机锁屏,在解锁,那么就会导致截图拿不到,导致脚本卡死,这是什么问题,正常跑不锁屏就不会有这个问题

L-PPMT · 12 小时前

回答

Hamibot AI
1
· 12 小时前

这个问题通常是因为锁屏后系统回收了截图权限(MediaProjection 服务被暂停),导致 captureScreen() 阻塞或永远无法返回截图,从而脚本卡死。

原因分析

  • 当你首次调用 requestScreenCapture() 授权后,系统会启动一个屏幕捕捉会话(MediaProjection)。在部分机型(如一加13、红米K60U)上,锁屏会触发该会话被暂停或终止。
  • 解锁后,虽然应用仍在运行,但截图链路已经中断,captureScreen() 会一直等待新的帧数据,如果底层不抛异常也不返回,就会造成死等,即你看到的“卡死”。

解决办法

  1. 在解锁后重新请求截图权限
    可以在脚本中定期检测屏幕是否解锁,解锁后重新调用 requestScreenCapture() 并再次授权。例如:

    // 文档地址 https://docs.hamibot.com/
    function ensureScreenCapture() {
        if (!requestScreenCapture()) {
            toastLog('截图权限获取失败');
            hamibot.exit();
        }
        // 等待截图服务就绪
        sleep(500);
    }
    
    // 监听解锁事件(需要设备支持)
    if (device.isScreenOn && device.isScreenOn()) {
        events.onKeyDown('power', function() {
            sleep(1000);
            if (device.isScreenOn()) {
                ensureScreenCapture();
            }
        });
    }
    

    如果设备没有可靠的解锁广播,可以改为在每次截图前检查并重试:

    function safeCapture() {
        try {
            var img = captureScreen();
            return img;
        } catch (e) {
            // 截图失败,重新请求权限
            ensureScreenCapture();
            return captureScreen();
        }
    }
    
  2. 保持屏幕常亮,避免锁屏
    在脚本开始时设置:

    device.keepScreenOn(3600 * 1000); // 保持1小时
    

    这样在脚本运行期间不会自动锁屏。

  3. 使用超时机制避免死等
    如果可以,给 captureScreen() 加一个超时判断,但该函数本身不支持超时参数。你可以通过threads启动一个定时器,如果超时则强制重新请求权限或重启脚本。例如:

    function captureWithTimeout(timeout) {
        var result = null;
        var done = false;
        var captureThread = threads.start(function() {
            result = captureScreen();
            done = true;
        });
        var start = new Date().getTime();
        while (!done && (new Date().getTime() - start) < timeout) {
            sleep(100);
        }
        if (!done) {
            captureThread.interrupt();
            toastLog('截图超时,重新请求权限');
            ensureScreenCapture();
            return captureScreen();
        }
        return result;
    }
    

最佳实践

  • requestScreenCapture() 后立即调用一次 captureScreen() 并丢弃结果,确保底层链路完全建立,避免首帧延迟。
  • 如果脚本需要长时间运行且可能被锁屏,建议在每次截图前判断 device.isScreenOn(),屏幕关闭时主动等待或唤醒屏幕后再截图。

这些方法可以有效避免锁屏导致的截图卡死问题。如果你使用的是开发脚本,请参考 Hamibot 文档 了解 captureScreendevice 模块的更多细节。

ℹ️ 内容由 AI 生成,可能不准确,请注意核实