I would like to make my virtual instrument app able to being used (via a MIDI keyboard) when the app is in the background. This works fine by setting UIBackgroundModes to "audio" and setting the AudioSessions's category to AVAudioSessionCategoryPlayback. Furthermore, to allow mixing with the Music player app, I set the property kAudioSessionProperty_OverrideCategoryMixWithOthers.
To save battery energy, it is recommended to let the user switch off the background operation if it is not needed. So there is a switch in my app to toggle between the category AVAudioSessionCategoryAmbient and the category AVAudioSessionCategoryPlayback (with kAudioSessionProperty_OverrideCategoryMixWithOthers). The code is like this (error handling omitted):
NSString *category = supportsBackgroundOperation ? AVAudioSessionCategoryPlayback : AVAudioSessionCategoryAmbient;
[session setCategory:category error:nil];
if (category == AVAudioSessionCategoryPlayback) {
UInt32 allowMixing = true;
AudioSessionSetProperty(kAudioSessionProperty_OverrideCategoryMixWithOthers, sizeof(allowMixing), &allowMixing);
}
Now the problem: Suppose the Music application is playing in the background. The user is playing the virtual instrument in the foreground (via a MIDI keyboard) to accompany the Music player and decides to start yet another app, say a slide show to enjoy why playing the instrument. So he/she goes to the settings view of my app and activates background operation. Then the above code is executed. Boom, the Music application gets silent. As I understand it, the kAudioSessionProperty_OverrideCategoryMixWithOthers property can only be set after setting the category, but when I set the category to AVAudioSessionCategoryPlayback, the Music player is silenced by the system before I have a chance to set kAudioSessionProperty_OverrideCategoryMixWithOthers.
Is this was happens? Can there anything be done? I tried to deactivate/activate the session before/after changing the category, but that lead to other trouble.
Markus
Since iOS 6.0 you can use
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback withOptions:AVAudioSessionCategoryOptionMixWithOthers error:nil];
Swift 5:
try? AVAudioSession.sharedInstance().setCategory(.playback, options: .mixWithOthers)
You can achieve this. The principle is to deactivate your audio session first, setup all the properties of your audio session, and then active audio session. In this way, the music playbacked in other app will not be silenced.
// Initialize audio session
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
// Active your audio session
[audioSession setActive: NO error: nil];
// Set audio session category
[audioSession setCategory:AVAudioSessionCategoryPlayback error:nil];
// Modifying Playback Mixing Behavior, allow playing music in other apps
OSStatus propertySetError = 0;
UInt32 allowMixing = true;
propertySetError = AudioSessionSetProperty (
kAudioSessionProperty_OverrideCategoryMixWithOthers,
sizeof (allowMixing),
&allowMixing);
// Active your audio session
[audioSession setActive: YES error: nil];
This solution works for me. But from your description, You mentioned that you did try activate/deactivate the session before/after changing the category but lead to other problems. Did you do the deactivate/activate in the exact same way as above? If so, provide more information about other troubles and maybe I can help.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With