Reputation: 685
I have an audio player which has an option of switching the Audio Output from Speaker to Receiver/Earpiece (irrespective of whether headset is connected) when proximity sensor notifies 1. The following is my code for doing so.
- (void) switchAudioOutput:(NSString*)output{
AVAudioSession* audioSession = [AVAudioSession sharedInstance];
BOOL success;
NSError* error;
if([output isEqualToString:keAudioOutputReciever]){
//Force current audio out through reciever
//set the audioSession override
success = [audioSession overrideOutputAudioPort:AVAudioSessionPortOverrideNone
error:&error];
if (!success)
NSLog(@"AVAudioSession error overrideOutputAudioPort:%@",error);
//activate the audio session
success = [audioSession setActive:YES error:&error];
if (!success)
NSLog(@"AVAudioSession error activating: %@",error);
else
NSLog(@"AVAudioSession active with override: AVAudioSessionPortOverrideNone");
}else if([output isEqualToString:keAudioOutputSpeaker]){
//set the audioSession override
success = [audioSession overrideOutputAudioPort:AVAudioSessionPortOverrideSpeaker
error:&error];
if (!success)
NSLog(@"AVAudioSession error overrideOutputAudioPort:%@",error);
//activate the audio session
success = [audioSession setActive:YES error:&error];
if (!success)
NSLog(@"AVAudioSession error activating: %@",error);
else
NSLog(@"AVAudioSession active with override: AVAudioSessionPortOverrideSpeaker");
}
}
This was based on the answer Toggle Button route audio to speaker and receiver and enter link description here. I noticed that this only forces the Audio to Speaker alone but does not ensure that the route goes to receiver alone. Moreover while shifting to speaker I get the following error:
AVAudioSession error overrideOutputAudioPort:Error Domain=NSOSStatusErrorDomain Code=-50 "The operation couldn’t be completed. (OSStatus error -50.)"
Upvotes: 6
Views: 5281
Reputation: 2168
I was struggling with this too and was trying to set the mode
parameter so something potentially appropriate, e.g.
try AVAudioSession.sharedInstance().setCategory(.playAndRecord,
mode: .voicePrompt,
options: .defaultToSpeaker)
And that would just throw me an error:
Error Domain=NSOSStatusErrorDomain Code=2003329396 "(null)"
The audio was routing to the receiver rather than speaker with just the category
parameter and with the mode
, but when I randomly decided to try without the mode
parameter but with the options
parameter it worked fine!
So give this code a try if you struggle:
try AVAudioSession.sharedInstance().setCategory(.playAndRecord,
options: .defaultToSpeaker)
Upvotes: 1
Reputation: 685
I figured out the answer by avoiding overrides for Receiver
- (void) setAudioSession:(NSString*)audioOutput{
NSError* error;
if([audioOutput isEqualToString:audioOutputSpeaker.lowercaseString]){
//set the audioSession override
if(![self setCategory:AVAudioSessionCategoryPlayAndRecord
withOptions:AVAudioSessionCategoryOptionDefaultToSpeaker|AVAudioSessionCategoryOptionAllowBluetooth
error:&error])
NSLog(@"AVAudioSession error AVAudioSessionCategoryPlayAndRecord:%@",error);
//activate the audio session
if (![self setActive:YES error:&error])
NSLog(@"AVAudioSession error activating: %@",error);
else
NSLog(@"AVAudioSession active with override: AVAudioSessionPortOverrideNone");
}else if ([audioOutput isEqualToString:audioOutputReciever.lowercaseString]){
//Force current audio out through reciever
//set the audioSession override
if(![self setCategory:AVAudioSessionCategoryPlayAndRecord
withOptions:AVAudioSessionCategoryOptionAllowBluetooth
error:&error])
NSLog(@"AVAudioSession error AVAudioSessionCategoryPlayAndRecord:%@",error);
if (![self overrideOutputAudioPort:AVAudioSessionPortOverrideNone error:&error])
NSLog(@"AVAudioSession error overrideOutputAudioPort to Reciever:%@",error);
//activate the audio session
if (![self setActive:YES error:&error])
NSLog(@"AVAudioSession error activating: %@",error);
else
NSLog(@"AVAudioSession active with override: AVAudioSessionPortOverrideNone");
}
}
Upvotes: 9