在Android和iOS浏览器中,是否有可能使用JavaScript检测屏幕关闭的情况?

23
我正在追踪我的应用程序JavaScript报告的一些极高的加载时间,并发现当窗口处于后台或显示关闭时,Android(和iOS)会暂停一些JavaScript执行。
在Android上,我发现我可以使用window.onfocusonblur事件来检测应用程序何时切换到后台(至少对于新脚本,js执行将很快被暂停),但我找不到一种方法来检测屏幕何时打开或关闭。这可能吗?
(在Safari上,我的结果类似,只是onfocusonblur没有可靠地触发。)

3
在 Android 设备上,关闭并重新打开屏幕是否会触发 onbluronfocus 事件?我认为关闭屏幕可能会触发 onblur,而且即使不能触发,唤醒设备后也会触发 onblur,因为 Android 会弹出锁屏界面,然后在通过锁屏界面后,onfocus 将触发,因为您正在从锁屏界面返回到活动应用程序。虽然我不是 Android 专家,但如果你还没有检查过的话,我想提供这个想法。 - ajp15243
我的测试结果没有出现这种情况,但是既然你提到了,我想起来我曾经禁用过我的锁屏。只要我按下电源按钮,它就会回到我最后打开的应用程序。启用锁屏后,焦点和模糊事件得以触发。谢谢! - Nathan Friedly
4个回答

17

有几种选项可以检查它:

  1. 使用 Visibility API

  2. 使用 focusblur 事件来检测浏览器选项卡的可见性:

window.addEventListener("focus", handleBrowserState.bind(context, true));
window.addEventListener("blur", handleBrowserState.bind(context, false));
function handleBrowserState(isActive){ // 做某事 }
  1. 使用计时器,如上所述

哈哈,页面可见性规范的初稿在我发布问题大约一个月后就已经发布了!这似乎是目前为止正确的答案。 - Nathan Friedly
2
三年了,终于得到了正确的答案 :) 我现在正在处理同样的问题,并已经获得了许多新信息... 但是我仍然有一些问题与Android互联网浏览器(基于Chromium 34) - 这个浏览器无法处理可见性更改,上述描述的任何方法都不起作用... - Dmytro Medvid
可见性 API 是我唯一在 iPhone 上可靠工作的 API。 - ummdorian

15

我刚刚找到了一个非常好的解决方案,适用于我的使用情况:

function getTime() {
    return (new Date()).getTime();
}

var lastInterval = getTime();

function intervalHeartbeat() {
    var now = getTime();
    var diff = now - lastInterval;
    var offBy = diff - 1000; // 1000 = the 1 second delay I was expecting
    lastInterval = now;

    if(offBy > 100) { // don't trigger on small stutters less than 100ms
        console.log('interval heartbeat - off by ' + offBy + 'ms');
    }
}

setInterval(intervalHeartbeat, 1000);

当屏幕关闭时(或JS因任何原因暂停),下一个时间间隔将延迟,直到JS执行恢复。在我的代码中,我只需要通过offBy调整定时器即可。在快速测试中,这似乎在Android 4.2.2的浏览器和iOS 6.1.3上的Safari上都很好用。

4

在这里发现了一个不错的函数:

http://rakaz.nl/2009/09/iphone-webapps-101-detecting-essential-information-about-your-iphone.html

该链接提供了一个有关iPhone Web应用程序的函数,可以检测设备的信息。
(function() {
    var timestamp = new Date().getTime();

    function checkResume() {
        var current = new Date().getTime();
        if (current - timestamp > 4000) {
            var event = document.createEvent("Events");
            event.initEvent("resume", true, true);
            document.dispatchEvent(event);
        }
        timestamp = current;
    }

    window.setInterval(checkResume, 1000);
})();   

注册活动:

addEventListener("resume", function() {
    alert('Resuming this webapp');
});

这与 Cordova 一致,它也会触发 resume 事件。

3

虽然这不是我想做的事情,但你得到了一票赞成,因为这是一个很好的回答问题的答案 :) - Nathan Friedly

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接