I have an AVAudioPlayer that needs to continue in the background.
Audio is set as the background mode in the plist & this runs on launch:
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
[[RootController shared].view becomeFirstResponder];
AVAudioSession* session = [AVAudioSession sharedInstance];
[session setDelegate: self];
[session setActive:YES error:nil];
[session setCategory: AVAudioSessionCategoryPlayback error:nil];
- (BOOL)canBecomeFirstResponder { return YES; }
The Problem
Occasionally the AVAudioPlayer gets in this strange state where:
- It’s playing, but the play icon in the status bar disappears
- If I pause then play, the icon shows up for maybe a second, then disappears
- Here’s the kicker – if I call
setCurrentTimewhile playing, the play icon shows & stays
I’ve sunk about 20 hours into this & would love any ideas.
Description of the Bug
If you are playing an
AVAudioPlayerthen you create anAVPlayer, the playing icon will disappear. ApparentlyAVPlayerimmediately takes precedence & since it is not playing yet the play icon disappears from the status bar.This causes some serious issues:
The Workaround
First off, if you don’t have to use
AVPlayer, then don’t. I use it because I need to play a remote MP3 without downloading it first. I used to use this AudioStreamer class but gave up because it pops up an alert when the stream becomes disconnected along with a few other bugs that I couldn’t fix.So if you’re stuck with AVPlayer, there’s only one way to re-connect playing status with your
AVAudioPlayer. If you callsetCurrentTimeon theAVAudioPlayerthen it will magically re-associate itself as the current player for the app. So you’ll need to call it after anyAVPlayeris initialized and anytime you resume playback on yourAVAudioPlayer.I decided to subclass AVAudioPlayer so I could register it in a global list (when it is initialized) and unregister it when it is deallocated. I also overrode the play method so that any calls to resume playback would also call setCurrentTime. Then I subclassed AVPlayer so that any time one is initialized, all active AVAudioPlayers call setCurrentTime on themselves. Last thing – you’ll have to call
setCurrentTimeafter a short, maybe 1 second, delay or else it will have no effect.No kidding, this is the result of nearly 40 hours of troubleshooting.