Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Changing AVAudioSession modes in app

Is it possible to change the session category and options when a specific behavior is needed in app? For example setting:

[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord error:&sessionError];

according to apple docs will not honor the silent switch.

The app records and plays audio. On audio playback, the app needs to honor the silent switch. Question is: Can I set the category like so:

[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:&sessionError];

when playback begins so that the app honors the silent switch. And if I do so, how will this affect routing? Apple Docs state:

The session's category and mode together define how the application intends to use audio. Typically, you should set the category and mode before activating the session. You may also set the category or mode while the session is active, but this will result in an immediate route change.

like image 534
Chris Avatar asked Mar 23 '14 15:03

Chris


1 Answers

It is possible to change, quoting the docs:

Each app running in iOS has a single audio session, which in turn has a single category. You can change your audio session’s category while your app is running.

https://developer.apple.com/library/ios/documentation/AVFoundation/Reference/AVAudioSession_ClassReference/#//apple_ref/doc/constant_group/Audio_Session_Categories

So it is just a matter of calling the setCategory: method when you want the app to change mode.

For example, you start your app while allowing sound to play from other apps:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient error:nil]
    (...)
}

And when a user presses a play button on your UI, change to Playback mode:

- (void)playAudio {
    if ([AVAudioSession sharedInstance].otherAudioPlaying) {
        // you can check and play only if there is no other audio playing
        // maybe use another category, or enable mixing or duck option
        [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback withOptions:AVAudioSessionCategoryOptionDuckOthers error:nil];
    } else {
        [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
    }
    [[AVAudioSession sharedInstance] setActive:YES error:nil];
}

If you want to resume the other app audio after your playback you can do a notification, or just close the session to have the other app audio to continue stopped:

- (void)stopAudio {
    if (self.otherAudioShouldResume) {
        [[AVAudioSession sharedInstance] setActive:NO withOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation error:nil];
    } else {
        [[AVAudioSession sharedInstance] setActive:NO error:nil];
}

This code is an overview only, you might need to perform more functions to achieve a working example, also remember to check the return of these functions (BOOL) and log the errors for debugging.

like image 169
lkraider Avatar answered Nov 16 '22 23:11

lkraider