Flathead Games





How To: Handle background music in iOS(iPod/iPhone/iPad)
July 1st, 2012
Hi,

After scouring the web and finding different fragments of incomplete information about playing background music in my game, I decided to write this quick article. If you want to see this code in action, go grab a copy of my game from the App Store.

So, Here's a quick rundown of what it takes to play background music in an iphone/ipad game. This code hopefully contains everything needed to allow your app to keep the users choice of music playing in the background while your game runs. I'll also show how to handle the same checks if the user tabs away from your game, starts music and comes back.

To start, these are the frameworks you'll need to add to your project:
AVFoundation.framework AudioToolbox.framework
Here are some includes you'll need in your AppDelegate class
#import <AVFoundation/AVFoundation.h> #include <AudioToolbox/AudioServices.h>
Next, you'll need to add an AVAudioPlayer pointer to your class, so drop this property in your header
@property (strong, nonatomic) AVAudioPlayer* avAudioPlayer;
and "synthesize" it in your .mm file
@synthesize avAudioPlayer = m_avAudioPlayer;
When the app starts, we want to set the audio category to "AVAudioSessionCategoryAmbient" which allows us to keep the users music in the background, this needs to be done before any other audio initialization. In my case I use OpenAL for sound effects, so I initialize that later in the code(not shown). Once the category is set, you can call "AudioSessionGetProperty" to see if other music is playing and do what you want with it. For this sample I started the music, but it's probably best to skip the play call until after you load your user's preferences, so you can only start the music if they previously didn't turn it off.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // init audio stuff { [[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryAmbient error: nil]; // check if another app is already playing audio. UInt32 otherAudioIsPlaying = 0; UInt32 propertySize = sizeof( otherAudioIsPlaying ); AudioSessionGetProperty( kAudioSessionProperty_OtherAudioIsPlaying, &propertySize, &otherAudioIsPlaying ); // Initialize your music, even if you don't end up playing it, to reduce memory usage you can always do this only if no other music is playing. NSString* musicfile = [[NSBundle mainBundle] pathForResource:@"Data/Audio/musicfilename" ofType:@"mp3"]; m_avAudioPlayer = [[AVAudioPlayer alloc]initWithContentsOfURL:[NSURL fileURLWithPath:musicfile] error:NULL]; m_avAudioPlayer.numberOfLoops = -1; m_avAudioPlayer.volume = 1.0; // You might want to take this "play" call out and put something like it after // you load your save file to see if the user turned off your music. if( otherAudioIsPlaying == false ) [m_avAudioPlayer play]; } ... }
Finally, when the app reactivates from any kind of pause, whether it was a phone call, the user went back to the ios dashboard or just double-tapped the "home" button and potentially started music, we can handle that here, by stopping our in-game music:
- (void)applicationDidBecomeActive:(UIApplication *)application { UInt32 otherAudioIsPlaying = 0; UInt32 propertySize = sizeof( otherAudioIsPlaying ); AudioSessionGetProperty( kAudioSessionProperty_OtherAudioIsPlaying, &propertySize, &otherAudioIsPlaying ); if( otherAudioIsPlaying ) [m_avAudioPlayer stop]; }

That's it!

I hope this works for you, if you have any questions or comments, leave them below and I can update this if needed.

Jimmy
Hi - thanks for this its very useful. I have a slightly different problem I am trying to resolve. I want to be able to play a video and if user chooses to listed to Ipod music then mute the sound from the video - do you know if that possible?
Hi, glad you liked it.

I've never tried playing video, but if it doesn't cut off the system music, you should be able to easily set the video's volume to zero if "otherAudioIsPlaying". You'd, of course, need to store that value somewhere it can be checked each time you play video. Better yet, write a function to query it from the system, for cases where the system music ended and you'd like to set any future video's volume to a normal level.

But if simply playing video even with volume at zero cuts off system music, then it's a more complicated issue that I don't have an answer to.
Login to comment on news