Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cordova/PhoneGap: setInterval() / setTimeout() not working correctly

I implemented a simple countdown timer using window.setInterval. It works perfectly in my desktop browser but it does not work correctly on my smartphone (Fairphone 2) as a PhoneGap/Cordova app. According to my examinations and my research on the internet the interval/timeout is interrupted when the phone is sent to sleep/standby. That's why it does not work.

Astonishingly the interval/timeout is not interrupted when my phone is connected via usb cable to my computer. So probably it's an energy-saving feature that's causing the bad behaviour.

So, I'm lost. I don't know how to implement my simple countdown timer which of course should also work when the phone sleeps (=display turned off). Is there an alternative for window.setInterval() / window.setTimeout() ?

Here is my simple code (as stated: window.setTimeout does not work, either):

...
<script type="text/javascript" src="cordova.js"></script>
<script type="text/javascript" src="js/libs/jquery.js"></script>
<script>
    var min = 25;
    $(document).ready(function(){
        intervalID = window.setInterval(function () {
            --min;
            if (min > 0) {
                $("#countdown").text(min);
            }
        }, 6000);
    });
</script>
...
<p id="countdown">0m</p>
like image 747
Falco Preiseni Avatar asked Feb 07 '23 21:02

Falco Preiseni


2 Answers

Use the interval timer only for updating the display. Use the system time to decide what to display.

Then, if your interval doesn't get called when the display is not visible, this is no problem. The next time it does get called (when the display is turned on again), it will calculate the correct elapsed time from the system time and it will display correctly.

For this reason (and several others), you should never assume that setInterval() is going to keep perfect time. In Javascript, it just means you want to be called every once in a while and you get to set an approximate time to specify the frequency, but the interval may be shut off for long periods of time.

Get the time when your interval starts with Date.now() and then each time the interval fires, get the new system time and subtract from the start time to see how much time has elapsed and then calculate what you want to display.

If you want to show minutes remaining on a 25 minute timer, you could do this:

function showTimer(selector, minutes) {
  var startTime = Date.now();
  var interval;

  function showRemaining() {
    var delta = Date.now() - startTime;     // milliseconds
    var deltaMinutes = delta / (1000 * 60);
    if (deltaMinutes < minutes) {
      // display minutes remaining
      $(selector).text(Math.round(minutes - deltaMinutes));
    } else {
      $(selector).text(0);
      clearInterval(interval);
    }
  }

  interval = setInterval(showRemaining, 15 * 1000);
  showRemaining();
}

$(document).ready(function(){
  showTimer("#countdown", 25);
});

Working demo: https://jsfiddle.net/jfriend00/807z860p/

like image 64
jfriend00 Avatar answered Feb 10 '23 12:02

jfriend00


I found a cordova plugin which executes timeouts/intervals even when the display is turned off:

cordova-plugin-timers (on github)

The answer of jfriend00 was also helpful.

like image 35
Falco Preiseni Avatar answered Feb 10 '23 13:02

Falco Preiseni