Entering background on iOS4 to play audio
Solution 1
The one part missing from the documentation is you need to set your audio session.
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
Add that and you'll be good to go.
Solution 2
You also need to make calls to beginBackgroundTaskWithExpirationHandler: before you start a song (do it all the time whether in foreground or not) and endBackgroundTask when it ends.
This tells iOS that you want to be able to continue processing even if your app gets put in the background. It does not create a new task or thread, it's just a flag to iOS that you want to keep running. The audio will play to completion without this, but when it completes if you want to start another track you must be able to run in the background.
You can use it like this:
// ivar, initialized to UIBackgroundTaskInvalid in awakeFromNib
UIBackgroundTaskIdentifier bgTaskId;
When starting an audio player we save the bg task id:
if ([audioPlayer play]) {
bgTaskId = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:NULL];
}
Now the audioPlayerDidFinishPlaying: callback will still occur because we have told iOS that we are doing a task that needs to continue even if we get put in the background. That way we get the callback and can start the next audio file.
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)success
{
UIBackgroundTaskIdentifier newTaskId = UIBackgroundTaskInvalid;
if (self.haveMoreAudioToPlay) {
newTaskId = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:NULL];
[self playNextAudioFile];
}
if (bgTaskId != UIBackgroundTaskInvalid) {
[[UIApplication sharedApplication] endBackgroundTask: bgTaskId];
}
bgTaskId = newTaskId;
}
iwasrobbed
I work mostly with Swift/Objective-C and I open source a lot, including a video social network built with Ruby on Rails. I also dabble in Photoshop / Sketch. I am a Mechanical Engineer by training. Swift cheat sheet: https://github.com/iwasrobbed/Swift-CheatSheet ObjC cheat sheet: https://github.com/iwasrobbed/Objective-C-CheatSheet
Updated on June 24, 2022Comments
-
iwasrobbed almost 2 years
The documentation is rather poorly written when talking about playing audio in the background. It gives the impression that all you have to do to continue playing the audio that you are currently playing is to just add a key/value pair to the
info.plist
file and wallah, it's magic.However, this is not the case. For instance, if I play an mp3 that is 2 minutes long, obviously the audio is long enough to be able to play after I hit the home button to send my app to the background. The thing is, even though I have that key/value pair in my
info.plist
file, it pauses the audio and then resumes playing once I switch back to the app.Apple states that all frameworks for audio support background and the sound should continue playing up until the point that it ends and then Apple will suspend your app.
So, my question is: What are they doing that I am missing? Do I also have to use their new delegates somehow or call the audio on the
applicationDidEnterBackground
? To me, that wouldn't make sense since I am not saving state (they do for me with fast app switching) or really handling anything in the background other than audio which they say is supposed to be handled automagically. -
Joshua Weinberg almost 14 yearsWhy would you start a background task just to play audio. This is not necessary at all.
-
iwasrobbed almost 14 yearsDo you think this would keep it alive only for the time Apple allots when you request
beginBackgroundTaskWithExpirationHandler
or will it keep playing as long as you are usingaudioDidFinishPlaying
to loop a sound or play a new sound? -
Joshua Weinberg almost 14 yearsAt least someone realizes it! :)
-
iwasrobbed almost 14 years+1 to progrmr for going above and beyond since i will indeed need that as well for what i am doing (not sure why someone downvoted you, but i appreciate your answer)
-
iwasrobbed almost 14 yearsJosh, you were getting the checkmark, don't worry :) It worked like a charm. stackoverflow was screwing up on my slow network so i had to close the browser to correct it
-
Joshua Weinberg almost 14 yearsJust playing around :) You should file a radar about the documentation bug if you feel it wasn't clear that it is dependent on the audio session.
-
iwasrobbed almost 14 yearsGood point, I'll be sure to so we can save others from headaches. Thanks again
-
Joost Schuur almost 14 yearsDo you really need to go through all the trouble with task completion to start background audio? This is contrary to the material in the WWDC 2010 video on the topic ('Session 109 - Adopting Multitasking on iPhone OS, Part 2') at around minute 24, they show their avTouch app being converted for background audio, and they key was to prevent further GPU usage when you're in the background because that's what will kill the app. This was done by registering for a UIApplicationDidEnterBackgroundNotification and preventing GPU usage while in the background.
-
progrmr almost 14 years@IWasRobbed: you need this if you want to switch audio tracks in the background (which wasn't exactly the original question) otherwise your app suspends when the audio finishes playing. See this discussion.
-
progrmr almost 14 years@Joshua: If you started the audio in the foreground and want to suspend when that audio file ends, then you don't need to do this. But you can't play the next audio track because you will never get the audioPlayerDidFinishPlaying callback if you're didn't tell the system that you are doing background processing by using beginBackgroundTaskWithExpirationHandler.
-
Alex1987 almost 13 years@iWasRobbed: I found out that in addition you should use GCD in this case - dispatch_async(dispatch_get_global_queue(0, 0), ^{your audio playing code});
-
Vignesh about 11 years@progrmr. +1. Your answer is a value add. I would have spent more time if you haven't posted your answer. Thanks. Great help.
-
Alex over 10 years@progrmr, seems like you're not the only person who gave this as an answer, but I've implemented a music application on top of the Spotify framework and it works fine (when switching between songs in the background) even without initializing a background task. Either I am doing something wrong that I'm only going to see down the road, or maybe the way background audio works in iOS 6 has changed since 2010 (iOS 4)?
-
progrmr over 10 years@Andrei I haven't work on background audio for a few years so I can't really say what works now. A lot has changed since 2010.