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; 
    } 
}