On iOS8 this HTML5 web app does not resume the js timer after the screen is locked and then unlocked if the webapp was active AND launched from the homescreen icon. On iOS7 the timer would continue in this situation. I need the timer to continue after the screen is unlocked - any tips to achieve this?
Note/ Please add the web app to the homescreen first using Safari's "add to home screen" via the sharing button. Running the page inside Safari does not cause the issue described above.
<html>
<head>
<meta name="apple-mobile-web-app-capable" content="yes" />
<title>Test</title>
<script>
var tim;
function go() {
tim = window.setInterval(action, 1000);
}
function action() {
document.getElementById('x').innerHTML = new Date().getTime().toString();
}
</script>
</head>
<body onload="go()">
<div id="x"></div>
</body>
</html>
The solution we ended up does not address all the broken functionality after sleep mode in IOS8, but rather just ajax requests/setTimeout/setInterval/requestAnimationFrame and their respective clear functions.
Other things broken after sleep mode:
- -webkit-transition opacity causes non-selectable areas
- worker.postMessage called while keyboard opening permanently kills all WebWorkers
- window bouncing/panning can kill all WebWorkers.
- overflowchange/resize events no longer work. You need to rework any logic that depends on them`.
To make a semi-working solution:
- Override setTimeout/setInterval/requestAnimationFrame/clearInterval/clearTimeout/cancelAnimationFrame. All of these functions need to postMessage to a webworker, where the webworker will perform setTimeout/setInterval accordingly. You may need to set up a pausing mechinism for these functions as well, but I'm not 100% its necessary.
- Override XMLHttpRequest so that when send is called, the request is actually performed on a webworker.
- Create a pausing mechanism for all webworkers so that the main thread can determine when all webworkers have flushed their messages (Basically need to prevent postMessage from getting called on any worker while the keyboard is up).
- Prevent keyboard popping up on editable elements. After detecting a tap/click event on an editable element, you need to manually call the focus function.
- Override focus function on editable elements that open the keyboard. Focus will now call the pause workers function. After all workers are paused, call the browser implementation of focus.
- Add focusout event listener to editable elements so that resume workers function is called.
I have a semi-abstracted version on my github available for others. We are using the github version in our fairly complex/large and heavily animation+ajax dependent application with very few issues.
https://github.com/TaDaa/IOS8-FIX
Installing iOS 8.1.1 fixes this problem
Here's an example of my working workaround.
Worker Script backgrond.js
setInterval(function () {
postMessage(JSON.stringify({
message: "tiktok",
result: new Date().getTime()
}));
}, 500);
Page Script - edited following comments 2014-10-30
var GUI = {
iOS8: false,
web_worker: null,
tik: new Date().getTime(),
tok: new Date().getTime(),
init: function(){
GUI.web_worker = new Worker("scripts/background.js");
GUI.web_worker.onmessage = function (event) {
var d = JSON.parse(event.data);
if (d.message === 'tiktok') {
GUI.tik = d.result;
if (Math.abs(GUI.tik - GUI.tok) > (15 * 1000) && GUI.iOS8 ) {
GUI.web_worker.terminate();
document.write('Please restart app after locking the screen. Apple are working to prevent this issue.');
}
};
}
setInterval(function () { GUI.tok = new Date().getTime(); }, 1000);
var ua = navigator.userAgent.toLowerCase();
GUI.iOS8 = ua.indexOf("os 8_0") !==-1 || ua.indexOf("os 8_1") !==-1;
}
}
GUI.init();
For another workaround for Ajax requests (involves serverside work) but does work here: iOS 8 Bug - OnUpdateReady never called again when device returns from sleep
I tried the fix, and it does not work on my iphone4s and IOS8.
I found on my version phone an Alert Box crashes the app after you lock and come out of it... Basically I put an alert box up That says PLease close and restart app when the settimeout timer stops updating by using a screen onlclick... SOoo Messy... THis is a terrible bug!
It was fixed on iOS 8.1.3.
I'm using EaselJS library that uses requestAnimationFrame or setTimeout internally for updating tick. It had same problem on iOS 8.0.x, but it have been fixed on iOS 8.1.3.
Presuming that every time the phone is unlocked, the window.onload
event is handled, try this:
window.onload = function() { window.location.reload() }
As I don't currently have a device to test this on, this is only a blind guess. Hope this works for you.