2

我为移动Web应用程序构建了一个简单的基于JavaScript的计时器;例如:当屏幕超时时,Android Browser/Mobile Safari中的setInterval暂停

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

这在移动Safari和Android浏览器中运行得很好。它将记录到每秒钟的控制台并相应地增加a的值。 (好的,Android Browser没有console.log支持,但我们假设它是这样的)。

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

问题:有没有办法来防止setInterval函数在屏幕超时时暂停?如果没有,是否有可能防止屏幕超时?任何其他的选择?

在此先感谢!

回答

5

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

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

+0

这就是我想通。感谢你的回答。 – mjangda 2010-06-01 00:29:58

0

您可以使用页面可见性API来检测页面何时隐藏或可见。例如,如果用户从浏览器导航并返回,或者屏幕关闭和打开。

我用这个answer来帮助创建解决方案。 您需要存储设置间隔的时间。然后,当visibilityChange事件侦听器指示文档再次可见时,您可以计算自首次启动间隔以来已经过的时间量,并根据需要更新数据。

在我的情况下,我在我的Angular2项目中创建了倒数计时器。我的网页在iPad上运行,计时器在屏幕关闭时暂停。所以我在我的ngOnInit()中添加了事件监听器。然后,当屏幕重新开启时,我可以更新计时器以显示自启动以来的正确时间。

我正在使用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; 
    } 
}