One of the most frequent requests I get for my AudioStretch for iOS app is the ability to continue playing when the phone is locked. For some users it’s because their phone auto-locks after a minute or two; if you’re playing along with a slowed down guitar solo, perhaps looping indefinitely, it’s really annoying if it suddenly stops. Other users want to manually lock their phone and listen to slowed down music with the phone in their pocket. I’ve finally figured out how to do it!
Apple’s Audio Session Cookbook provides some, but not all, of the steps. In particular, it mentions that “If you want to ensure that your audio continues when the screen locks and when the Silent switch is in the ‘silent’ position (on iPhone, this switch is called the Ring/Silent switch), you need to assign an appropriate category to your audio session.” Specifically, you need to so create an AudioSession and use the
kAudioSessionCategory_MediaPlayback category. All pretty well explained in the Apple docs.
OSStatus err = err = AudioSessionInitialize(NULL, kCFRunLoopDefaultMode, NULL, NULL); assert(err == noErr); UInt32 sessionCategory = kAudioSessionCategory_MediaPlayback; err = AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof(sessionCategory), &sessionCategory); assert(err == noErr);
But even if you follow those steps, you’ll find that your app will go silent as soon as it goes into the background. The other essential step is for your app to register itself as a background audio app so it will continue running in the background. To do this include the
UIBackgroundModes key (with the value
audio) in your app’s
Info.plist file. An explanation can be found in Apple’s documentation on App States and Multitasking, in the section “Playing Background Audio”.
Note that the calls to
assert() in the above code should normally be replaced with proper error handlers. Also, in order to properly handle inevitable interruptions to the audio output due to phone calls and alarms, in the call to
AudioSessionInitialize() you should specify an
AudioSessionInterruptionListener function as the third argument. In my listener, I call
AudioOutputUnitStart(), with the audio output tone unit as the argument, for interruption states