I’m experiencing a problem whereby my application works fine when the screen is active, but, when the screen is locked or asleep, a certain bit of the code seems to pause the app indefinitely, without actually crashing.
The app uses AVAudioPlayers and boost::threads to play some music tracks. When a track ends, lots of setup has to be called in order for the new track to be prepared. At the same time, the app has to pause for a few seconds. This parallel activity is achieved with boost::threads.
When the screen is active, this all works fine. However, when the screen is inactive, the new track is never played. There is no crash, and, using breakpoints to debug, it seems that the app simply hangs on a certain line – the line changes from debug session to debug session – and gets stuck. Never have I so hoped for an EXC_BAD_ACCESS – but there’s nothing. No hint of why the code is hanging.
Could it be that my main thread is blocked? I use a few performSelectorOnMainThread calls, but I’ve deactivated them when the screen is locked using applicationWillResignActive. However, this hasn’t solved the problem.
The boost::thread in which it seems to hang is as follows:
void MyClass::loopThread(int waitSeconds)
{
loopScheduled = true;
sleep(waitSeconds);
if ( loopScheduled == true ) {
if (engine_isRunning()) {
joinEngineThread();
}
startEngineThread();
((CPlusPlus*)m_obj)->markAsPlaying();
}
}
It seems to hang around the
if ( loopScheduled == true ) {
line.
What’s going on in this thread is that other parallel threads can set loopScheduled to false during the sleep() call, and if loopScheduled is false, the later methods aren’t called.
However, in terms of the problem I’m having, loopScheduled should be irrelevant – it’s not being set to false by any other method, and is still true after the sleep() call.
Does anyone have any idea what could be going on?
I found the problem. The Audio session was ending while the app was paused between tracks.
It turns out that, when the screen is locked or asleep or the application is in the background, when the last AVAudioPlayer finishes playing the audio session finishes. This means that new AVAudioPlayers can no longer be prepared or played – so the new track cannot be played.
In order to get around this problem, I am now playing a silent file during the pause between tracks. This keeps the audio session going, which means that the new track plays when it is instructed to play.