当屏幕超时时,setInterval 在 Android 浏览器/移动 Safari 中暂停

发布于 2024-09-03 07:21:12 字数 452 浏览 2 评论 0原文

我为移动网络应用程序构建了一个简单的基于 JavaScript 的计时器;举个例子:

var a = 0;
setInterval(function() {
    console.log('a', a);
    a++;
}, 1000);

这在 Mobile Safari 和 Android 浏览器中都运行得很好。它将每秒记录到控制台并相应地增加 a 的值。 (好吧,Android 浏览器不支持 console.log,但我们假设它支持。)

问题: 如果屏幕超时(即用户停止与页面交互),setInterval 函数就会暂停。当用户再次打开屏幕时,它会恢复。这对我不起作用,因为我需要计时器来继续运行。

问题:有没有办法防止 setInterval 函数在屏幕超时时暂停?如果没有,是否可以防止屏幕超时?还有其他选择吗?

提前致谢!

I've built a simple JavaScript-based timer for a mobile webapp; for the sake of example:

var a = 0;
setInterval(function() {
    console.log('a', a);
    a++;
}, 1000);

This runs just fine in both Mobile Safari and Android Browser. It will log to console every second and increment the value of a accordingly. (Okay, Android Browser doesn't have console.log support, but let's assume it does.)

The issue: if the screen times out (i.e. user stopped interacting with the page), the setInterval function pauses. It resumes when the user turns on their screen again. This won't work for me as I need timer to keep running.

The questions: Is there a way to prevent the setInterval function from pausing when the screen times out? If not, is it possible to prevent the screen from timing out? Any other alternatives?

Thanks in advance!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

戈亓 2024-09-10 07:21:12

基本上,没有。当屏幕超时时,手机会进入睡眠状态以节省电量。由于无论如何都看不到任何东西,因此大量处理任务被停止。当您更改选项卡/窗口时,会发生类似的情况(页面从内存中卸载)。目前无法通过 Web 应用程序请求设备保持开启状态。 Android 未来对访问硬件的支持可能会提供此功能,但我个人对此表示怀疑。

如果您需要始终运行的支持,则需要为两个系统编写本机应用程序(而且在 Android 上它可以始终运行)。

Basically, no. The phone enters a sleep state to save battery when the screen times out. Since you can't see anything anyway, a large number of processing tasks are stopped. Similar things will occur when you change tabs/windows (the page is unloaded from memory). Right now there is no way to request that the device stays on from a web application. Future support in Android for accessing hardware may provide this functionality, but personally I doubt it.

If you need always running support, you'll need to write native applications for both systems (plus on Android it can always run).

风蛊 2024-09-10 07:21:12

您可以使用页面可见性 API 来检测页面何时隐藏或可见。例如,如果用户离开浏览器然后再次返回,或者屏幕关闭然后打开。

我使用此答案来帮助通过解决方案进行创建。
您需要存储您设置的间隔时间。然后,当visibilityChange事件侦听器指示文档再次可见时,您可以计算自第一次开始间隔以来已经过去的时间量,并根据需要更新数据。

就我而言,我在 Angular2 项目中创建了一个倒计时器。我的页面在 iPad 上运行,每当屏幕关闭时计时器就会暂停。因此,我在 ngOnInit() 中添加了事件监听器。然后,当屏幕重新打开时,我可以更新计时器以显示自启动以来剩余的正确时间。

我正在使用 moment npm 包来处理我的日期时间。
timerInfo 对象是一个类变量,通过间隔回调进行更新。 self.zone.run() 用于将更改传播到 DOM,以便显示更新的时间。

用打字稿写成:

private timerInfo:{
    days?:number,
    hours?:number,
    minutes:number,
    seconds:number
};
private startTime:Moment = moment();
private timerDuration:number = 20;  // in minutes
private timerHandle:any;

ngOnInit() {
    this.setVisibilityListener();
}

private setVisibilityListener():void {
    var self = this;
    var hidden, visibilityState, visibilityChange;

    if (typeof document.hidden !== "undefined") {
        hidden = "hidden";
        visibilityChange = "visibilitychange";
        visibilityState = "visibilityState";
    }

    var document_hidden = document[hidden];

    document.addEventListener(visibilityChange, function () {
        if (document_hidden != document[hidden]) {
            if (document[hidden]) {
                // Document hidden
                console.log("document hidden");
            } else {
                // Document shown
                console.log("document shown; setCountDownTimer()");
                self.setCountDownTimer();
            }

            document_hidden = document[hidden];
        }
    });
}

private setCountDownTimer():void {
    var self = this;
    if (self.startTime) {
        var startMoment = moment(self.startTime);
        var endMoment = startMoment.add(self.timerDuration, "minutes");
        console.log("endMoment: ", endMoment.toISOString());

        self.clearTimer();

        var eventTime = endMoment.unix();
        var currentTime = moment().unix();
        var diffTime = eventTime - currentTime;
        var duration = moment.duration(diffTime * 1000, 'milliseconds');
        var interval = 1000;

        // if time to countdown
        if (diffTime > 0) {
            self.timerHandle = setInterval(() => {
                self.zone.run(() => {
                    var diff = duration.asMilliseconds() - interval;
                    if (diff < 0) {
                        self.clearTimer();
                        self.timerComplete();
                    } else {
                        duration = moment.duration(duration.asMilliseconds() - interval, 'milliseconds');

                        self.timerInfo = {
                            days: moment.duration(duration).days(),
                            hours: moment.duration(duration).hours(),
                            minutes: moment.duration(duration).minutes(),
                            seconds: moment.duration(duration).seconds()
                        };
                        // console.log("timerInfo: ", JSON.stringify(self.timerInfo));
                    }
                });
            }, 1000);
        } else {
            self.timerComplete();
        }
    }
}

private clearTimer():void {
    if (this.timerHandle) {
        clearInterval(this.timerHandle);
        this.timerHandle = null;
    }
}

You can use the Page Visibility API to detect when the page is hidden or visible. For example, if the user navigates away from the browser and back again or the screen turns off and on.

I used this answer to help create by solution.
You will need to store the time you set your interval. Then when the visibilityChange event listener indicates the document is visible again, you can calculate the amount of time that has passed since you first started the interval and update your data as needed.

In my case I was creating a count down timer in my Angular2 project. My page was running on an iPad and the timer was pausing whenever the screen turned off. So I added the event listener in my ngOnInit(). Then when the screen turned back on I could update my timer to show the correct time left since it was started.

I am using the moment npm package to handle my date time.
The timerInfo object is a class variable that gets updated by the interval callback. self.zone.run() is used to propagate the changes to the DOM so that the updated time gets displayed.

Written in typescript:

private timerInfo:{
    days?:number,
    hours?:number,
    minutes:number,
    seconds:number
};
private startTime:Moment = moment();
private timerDuration:number = 20;  // in minutes
private timerHandle:any;

ngOnInit() {
    this.setVisibilityListener();
}

private setVisibilityListener():void {
    var self = this;
    var hidden, visibilityState, visibilityChange;

    if (typeof document.hidden !== "undefined") {
        hidden = "hidden";
        visibilityChange = "visibilitychange";
        visibilityState = "visibilityState";
    }

    var document_hidden = document[hidden];

    document.addEventListener(visibilityChange, function () {
        if (document_hidden != document[hidden]) {
            if (document[hidden]) {
                // Document hidden
                console.log("document hidden");
            } else {
                // Document shown
                console.log("document shown; setCountDownTimer()");
                self.setCountDownTimer();
            }

            document_hidden = document[hidden];
        }
    });
}

private setCountDownTimer():void {
    var self = this;
    if (self.startTime) {
        var startMoment = moment(self.startTime);
        var endMoment = startMoment.add(self.timerDuration, "minutes");
        console.log("endMoment: ", endMoment.toISOString());

        self.clearTimer();

        var eventTime = endMoment.unix();
        var currentTime = moment().unix();
        var diffTime = eventTime - currentTime;
        var duration = moment.duration(diffTime * 1000, 'milliseconds');
        var interval = 1000;

        // if time to countdown
        if (diffTime > 0) {
            self.timerHandle = setInterval(() => {
                self.zone.run(() => {
                    var diff = duration.asMilliseconds() - interval;
                    if (diff < 0) {
                        self.clearTimer();
                        self.timerComplete();
                    } else {
                        duration = moment.duration(duration.asMilliseconds() - interval, 'milliseconds');

                        self.timerInfo = {
                            days: moment.duration(duration).days(),
                            hours: moment.duration(duration).hours(),
                            minutes: moment.duration(duration).minutes(),
                            seconds: moment.duration(duration).seconds()
                        };
                        // console.log("timerInfo: ", JSON.stringify(self.timerInfo));
                    }
                });
            }, 1000);
        } else {
            self.timerComplete();
        }
    }
}

private clearTimer():void {
    if (this.timerHandle) {
        clearInterval(this.timerHandle);
        this.timerHandle = null;
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文