Prevent iOS mobile safari from going idle / auto-locking / sleeping? - iphone

In an iOS app you can set application.idleTimerDisabled = YES to prevent the phone from auto locking.
I need to do this in mobile safari for a game like Doodle Jump where the user may not touch the screen for an extended period of time. Is there any documented method or hack to do this?
(Update)
They seem to be doing it somehow in this site http://www.uncoveryourworld.com. Visit from your iphone and when you get to the buildings/street scene with music playing in the background just leave your phone alone. It never goes to sleep.
(Update 2)
I've spent some time taking a closer look at how they might be keeping the phone from going to sleep. I've done a barebones test and it seems that the way they are looping the audio in the street scene is what keeps it from going to sleep. If you'd like to test this just put a simple audio player that loops on your page and click play:
<audio src="loop.mp3" onended="this.play();" controls="controls" autobuffer></audio>
Everywhere I searched it is being said that this isn't possible, so it is nice to see there is at least some way to do it even if a bit of a hack. Otherwise a browser based game with doodle-jump style play would not be possible. So you could have a loop in your game/app if appropriate or just play a silent loop.

NoSleep.js seems to work in iOS 11 and it reportedly works on Android as well.
Old answer
This is a simple HTML-only method to do that: looping inline autoplaying videos (it might also work in Android Chrome 53+)
<video playsinline muted autoplay loop src="https://rawgit.com/bower-media-samples/big-buck-bunny-480p-30s/master/video.mp4" height=60></video>
See the same demo on CodePen (includes a stopwatch)
Notes
Avoid loading a big video just for this. Perhaps make a short, tiny, black-only video or use
To make it fully work, the videos needs to be always in the viewport or you need to start its playback via JS: video.play()

Edit: This work around no longer works. It is not currently possible to prevent the phone from sleeping in safari.
Yes, you can prevent the phone to sleep using an audio loop. The trick won't start automatically, you will have to play it when the visitor touches the screen.
<audio loop src="http://www.sousound.com/music/healing/healing_01.mp3"></audio>
Test page: tap play and the display will stay on but it will dim on some devices, like an iPhone with iOS 7.
Note: be careful using this trick because it will stop any music that the visitors might be using—and it will annoy them.

No, you can't do this, unfortunately. The only way to achieve this is by making a UIWebView-application and setting the variable you provided there.
https://stackoverflow.com/a/7477438/267892

[edit] random bug behavior, sometimes lockscreen media controls showing, sometimes not
Years later, updated my code
Easy steps :
unlock audio context
create silent sound
loop it and play forever
keep tab active
Working on Safari iOs 15.3.1, tab & browser in background, screen off
// unlock audio context
let ctx = null;
// create silent sound
let bufferSize = 2 * ctx.sampleRate,
emptyBuffer = ctx.createBuffer(1, bufferSize, ctx.sampleRate),
output = emptyBuffer.getChannelData(0);
// fill buffer
for(let i = 0; i < bufferSize; i++)
output[i] = 0;
// create source node
let source = ctx.createBufferSource();
source.buffer = emptyBuffer;
source.loop = true;
// create destination node
let node = ctx.createMediaStreamDestination();
source.connect(node);
// dummy audio element
let audio = document.createElement("audio");
audio.style.display = "none";
document.body.appendChild(audio);
// set source and play
audio.srcObject = node.stream;
audio.play();
// background exec enabled

Even if this approach might not be suitable in every case, you can prevent your phone from locking by reloading the page using Javascript.
// This will trigger a reload after 30 seconds
setTimeout(function(){
self.location = self.location
}, 30000);
Please note that I tested this with iOS7 beta 3

You can stop sleeping and screen dimming in iOS Safari by faking a refresh every 20–30 seconds
var stayAwake = setInterval(function () {
location.href = location.href; //try refreshing
window.setTimeout(window.stop, 0); //stop it soon after
}, 30000);
Please use this code responsibly, don't use it "just because". If it's only needed for a bit, disable it.
clearInterval(stayAwake); //allow device sleep again when not needed
Tested in Safari iOS 7, 7.1.2, and 8.1, but it may not work in UIWebView browsers like Chrome for iOS or the Facebook app.
Demo: http://jsbin.com/kozuzuwaya/1

bfred.it's answer works if you replace the audio-tag with a enter code here -tag - but only if the page is open in iOS10+ Safari AND the user has started the video. You can hide the video with CSS.
Also, I suspect that this feature will also be removed at some point.

This is based on nicopowa's answer, which saves a PWA from being suspended by iOS. (Playing an infinite loop of nothing keeps the app running - even with the screen turned off.)
In order to also make sure that it's triggered by user interaction,
the only thing to change is instead of
let ctx = null
put
let ctx = new AudioContext()

Related

iphone html 5 video - how to start from different time

What is the correct way to begin playback of a video from a specific time?
Currently, the approach we use is to check at an interval whether it's possible to seek via currentTime and then seek. The problem with this is, when the video fullscreen view pops up, it begins playback from the beginning for up to a second before seeking.
I've tried events such as onloadmetadata and canplay, but those seem to happen too early.
Added information:
It seems the very best I can do is to set a timer that tries to set currentTime repeatedly as soon as play() is called, however, this is not immediate enough. The video loads from the beginning, and after about a second, depending on the device, jumps. This is a problem for me as it provides an unsatisfactory experience to the user.
It seems like there can be no solution which does better, but I'm trying to see if there is either:
a) something clever/undocumented which I have missed which allows you to either seek before loading or otherwise indicate that the video needs to start not from 00:00 but from an arbitrary point
b) something clever which allows you to hide the video while it's playing and not display it until it has seeked (So you would see a longer delay on the phone before the fullscreen video window pops up, but it would start immediately where I need it to instead of seeking)
do something like this;
var video = document.getElementsById("video");
video.currentTime = starttimeoffset;
more Information can be found on this page dedicated to video time offset howtos
For desktop browser Chrome/Safari, you can append #t=starttimeoffsetinseconds to your video src url to make it start from certain position.
For iOS device, the best we can do is to listen for the timeupdated event, and do the seek in there. I guess this is the same as your original approach of using a timer.
-R

iOS idleTimerDisabled behavior

My iPhone application has two states: UI and Game.
Game is played using device tilting only so I switched auto-sleep off on game start:
[[UIApplication sharedApplication].idleTimerDisabled = TRUE;
But as soon as I return to UI, I want auto-sleep to be active again. So on game finish I restore it:
[[UIApplication sharedApplication].idleTimerDisabled = FALSE;
After a long game playing, it resulted in immediate darkening of the first UI screen that I go after the game.
So it seems that when idle timer was disabled it was still calculating time. And it had fired immediately after "enabling". How can I fix this problem?
I don't know if the idleTimer can be reset programmatically, but an option is to require the user to touch the screen before it goes back.
Another option is set your own timeout once you are back and wait for it to complete before you set idleTimerDisabled = NO. Remember to clear this timeout if you start the game again.
This answer may be usefull.
I also had problems when using Music/Audio players, which seemed to reactivate the timer.
ps: in ObjectiveC you should use YES/NO instead of FALSE/TRUE

applicationMusicPlayer stops when user locks the screen on iOS 5

I set the audio session category to kAudioSessionCategory_MediaPlayback, I active the session, which returns no errors, and still the iPod music stops when I lock the device. This happens on iOS 5 GM, so I guess this will happen in the final version. On iOS 4+ the current code works fine. Any ideas how to fix this? Huge thanks :)
It's not a bug. To save power locking the phone is now treated as if the user pressed the home button. The fact that applicationMusicPlayer stops now when locking is just a side effect of this change.
To work around this problem you should switch to AVPlayer and make use iOS 4's audio in background mode.
Fixed this issue for my particular problem - how to detect the difference between OS4 and OS5 behavior when device gets to the Lock screen.
In OS4 app does 'applicationWillResignActive' but on OS5 it goes all the way to 'applicationDidEnterBackground' which looks exactly the same as the user hitting the Home button.
It turns out that if you check the UIApplicationState of the application given in '- (void)applicationDidEnterBackground:(UIApplication *)application', it has 3 possible values:
typedef enum {
UIApplicationStateActive,
UIApplicationStateInactive,
UIApplicationStateBackground
} UIApplicationState;
When the user hits home on OS5, you get UIApplicationStateBackground, but when the user hits Lock, you get UIApplicationStateInactive.
Hope that helps.
Happy Holidays everyone.

Play a video whose URL is not known in advance - without reload - without extra tab

I have lots of buttons on a web page. Depending on which one is clicked, I want to play a different video.
A large number of <video> elements doesn't seem to work particularly quickly or reliably.
So far, I have tried to:
Create and play() the video element dynamically, after an image is clicked:
var video = document.createElement('video');
video.src = 'video.mp4';
document.body.appendChild(video.play);
video.play();
This works on iOS 4, but not on iOS 3.
Create the video element before, and just change the src.
Doesn't work either.
It seems like the video object must have already done "it's thing", before it can be played.
Use window.open() to open the video URL.
This will cause an annoying new tab to open, which will remain open after playback has completed.
Set window.location
This will cause the current page to be reloaded after playback has completed, which I'm trying to avoid.
Any more ideas?

idleTimerDisabled not working since iPhone 3.0

I have used:
[UIApplication sharedApplication].idleTimerDisabled = YES;
in a number of Apps developed and running under iPhone OS 2.x and never had any problems with it. They were clock apps so needed to run constantly and ignore the iPhone's idle Timer setting.
However, trying to achieve the same with a new App running OS 3.0 (and which needs to be deployed under 3.0 as it uses some 3.0 APIs) I've found the idle Timer to be either ignored or inconsistent.
My App plays music from the iPod library and when the music is playing it auto-locks regardless of the above setting. But once you unlock it, it then doesn't auto-lock again unless you play music again, in which case it locks again after the iPhone auto-lock time setting.
I'm amazed no-one else has come across this as I imagine it would affect a large number of Apps.
Just to clarify:
1. The above code is in ApplicationDidFinishLaunching
2. I know that the phone won't auto-lock when testing from xCode regardless of settings
If anyone has any thoughts I'd be very grateful...
Our app uses the MPMediaPLayer. We also had the idleTimerDisabled=YES code in the ApplicationFinishedLaunching, which works EXCEPT if untethered, and there is already a current nowPlayingItem which is left playing (or unpaused, if paused at app startup). Obviously this is all with the Settings -> General -> Autolock set to some timed value.
By adding idleTimerDisabled=NO, immedately followed by idleTimerDisabled=YES in one of the other bits of code AFTER we had figured out what bit of music we would get playing seemed to solve the problem. Just setting it to YES was insufficient.. and subsequent queries had always indicated the correct value (YES).. so it appears the Apple code ignores the setting of the value IF there is a current piece of music and that is not changed by your code.. but does notice a change of value.
This is all under iOS 3.0.
Even in 2015, using iOS 8.2, this bug is still alive and kicking.
Here's my solution, using XCode 6.2.
iPhone - phone goes to sleep even if idleTimerDisabled is YES
Basically, even now, in 2015, the only way to safely make sure that the device doesn't go to sleep is to repeatedly call a piece of code to keep the device awake.
-(void)callEveryTwentySeconds
{
// DON'T let the device go to sleep during our sync
[[UIApplication sharedApplication] setIdleTimerDisabled:NO];
[[UIApplication sharedApplication] setIdleTimerDisabled:YES];
}
Sounds like a bug, file with Radar - I am not too surprised this has not been seen much as there are probably not a lot of apps that try to lock the screen open and play music.
Having same issue. It does work when the device is plugged in. You can press lock button on top, and my NSTimer fires later and causes a vibrate. However if the device is not plugged in pressing the lock button puts the device to sleep. Any solution would be greatly appreciated.
iCodeblog posted about the idletimer, I said it didn't work, and the person who develops 'cute clock' was nice enough to reply. You have to do a hack, play a 1 second or longer silent sound every 10 or so seconds with NSTimer. This keeps the device awake even if the user hits the lock button.
I develop Seconds - Interval Timer for iPhone and iPod touch and I've had no end of trouble with this. The idea of my app is that people create timers based on a number of intervals where each interval can have it's own playlist or track played.
In iOS3 I had the problem that I couldn't disable the idle timer by just setting idleTimerDisabled = YES. In the end I came up with the same solution as Neil whereby I would periodically set it to NO, then immediately to YES again. This seemed to work.
I'm now updating the app to iOS4 (I know, iOS5 is just around the corner...) and now I have the opposite problem. If the MPMediaPlayer changes track before the idle timer reaches it's limit it gets reset. I've just tested this by creating an interval in my app that was 55 seconds, my auto-lock was set to a minute. At 50 seconds the screen dimmed as it prepared to lock, but at 55 seconds when the music changed it went back to full brightness and then didn't lock as it should.
Overall, the implementation of this seems flakey at best.