37

As AudioSessionSetProperty may become deprecated, I'm trying to find an code example of how to route audio to the speaker using other means.

Previously I did the following:

-(void)setSpeakerEnabled
{
    debugLog(@"%s",__FUNCTION__);
    UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_Speaker;

    AudioSessionSetProperty (
                         kAudioSessionProperty_OverrideAudioRoute,
                         sizeof (audioRouteOverride),
                         &audioRouteOverride
                         );
}

Trying to get same result but without call to AudioSessionSetProperty.

P.J.Radadiya
  • 1,493
  • 1
  • 12
  • 21
Jim Hankins
  • 1,055
  • 1
  • 11
  • 27
  • This question appears to be off-topic because it is about iOS 7 which is under NDA. – Cole Tobin Sep 14 '13 at 22:51
  • Wrong. You say `AudioSessionGetProperty` is deprecated, but it is available in iOS 6. It's deprecated in iOS 7. That's breaking the NDA. – Cole Tobin Sep 14 '13 at 23:31
  • 13
    @ColeJohnson, IMHO it is not the place of Stack Overflow to police NDAs. – foundry Sep 15 '13 at 01:41
  • [footnote to previous comment](http://meta.stackexchange.com/a/94488) – foundry Sep 15 '13 at 01:55
  • 2
    @ColeJohnson, I was viewing the 2012 WWDC which states it is deprecated at 13:58 Session 505 Audio Services Deprecated. I will not discuss why I was watching it however. – Jim Hankins Sep 15 '13 at 03:22
  • 1
    @Jim hmm. Well, my mistake then. I looked up the method on ADC (iOS 6 docs) and it doesn't say it's deprecated as far as I could tell. – Cole Tobin Sep 15 '13 at 03:39

4 Answers4

60

On each release of iOS, more of the audioSession properties are migrated to AVFoundation, so you should use those in preference whenever available.

Since iOS 6 kAudioSessionProperty_OverrideAudioRoute is represented in AVAudioSession by the method

- (BOOL)overrideOutputAudioPort:error:

Available values are AVAudioSessionPortOverrideNone and AVAudioSessionPortOverrideSpeaker

Here is an example audio session configured entirely via AVFoundation:

 - (void)configureAVAudioSession
{
   // Get your app's audioSession singleton object
    AVAudioSession *session = [AVAudioSession sharedInstance];

    // Error handling
    BOOL success;
    NSError *error;

    // set the audioSession category. 
    // Needs to be Record or PlayAndRecord to use audioRouteOverride:  

    success = [session setCategory:AVAudioSessionCategoryPlayAndRecord
                             error:&error];

   if (!success) {
       NSLog(@"AVAudioSession error setting category:%@",error);
   }

    // Set the audioSession override
    success = [session overrideOutputAudioPort:AVAudioSessionPortOverrideSpeaker
                                          error:&error];
    if (!success) {
        NSLog(@"AVAudioSession error overrideOutputAudioPort:%@",error);
    }

    // Activate the audio session
    success = [session setActive:YES error:&error];
    if (!success) {
        NSLog(@"AVAudioSession error activating: %@",error);
    }
    else {
         NSLog(@"AudioSession active");
    }

}

UPDATE

Since iOS 7.0, the Audio Session Services C API is now fully deprecated in favour of AVAudioSession.

UPDATE 2

- (BOOL)overrideOutputAudioPort:error:  

is a method, not a property, and it sets an underlying write-only UInt32 value. You can't get the current value, and you should treat the method as setting a temporary state. If the audio route changes or is interrupted, the property resets to its default (AVAudioSessionPortOverrideNone). You can get interruption notifications via AVAudioSessionDelegate.

Alex Zavatone
  • 4,106
  • 36
  • 54
foundry
  • 31,615
  • 9
  • 90
  • 125
  • How would this work for kAudioSessionProperty_OverrideCategoryEnableBluetoothInput in iOS 7 ? – Sjoerd Perfors Oct 02 '13 at 10:17
  • @SjoerdPerfors - You would use the AVAudioSession method `- (BOOL)setCategory:(NSString *)category withOptions:(AVAudioSessionCategoryOptions)options error:(NSError **)outError` with `category` as `AVAudioSessionCategoryPlayAndRecord` or `AVAudioSessionCategoryRecord` and `options` as `AVAudioSessionCategoryOptionAllowBluetooth` – foundry Oct 02 '13 at 11:26
  • Thanks Foundry but that is not the same because that would allow A2DP bluetooth only. And this wouldn't force using it either. See also: http://stackoverflow.com/questions/19134912/how-to-route-to-kaudiosessionproperty-overridecategoryenablebluetoothinput-witho – Sjoerd Perfors Oct 02 '13 at 15:14
  • not work for me! my code: AVAudioSessionPortOverride port = (onOff ? AVAudioSessionPortOverrideSpeaker : AVAudioSessionPortOverrideNone); success = [session overrideOutputAudioPort:port error:&error]; – hungbm06 Apr 16 '14 at 03:24
  • @hungbm06 - perhaps you can make a new question showing more of your code... if it's returning an error, show the error – foundry Apr 16 '14 at 11:22
  • How to get current value of overrideOutputAudioPort? – asavartsov Jul 25 '14 at 13:55
  • 1
    If anyone else is wondering why this doesn't work for them. You need to call it immediately before playing something. So `[[AVAudioSession] sharedInstance] overrideOutputAudioPort:AVAudioSessionPortOverrideSpeaker error:&overrideError]; [_player play];` – Joseph Dec 14 '14 at 07:21
  • @foundry, even if my app is only playing back a buffer for live audio synthesis will audioSession category still have to be set to AVAudioSessionCategoryPlayAndRecord to use audioRouteOverride ? why not AVAudioSessionCategoryPlayback ? – Greg Feb 13 '16 at 07:55
  • @Greg: Yes - because Apple says so. The `AVAudioSessionPortOverrideSpeaker` option only works when the audioSession is set to `AVAudioSessionCategoryPlayAndRecord`. Documented [here](https://developer.apple.com/library/prerelease/ios/documentation/AVFoundation/Reference/AVAudioSession_ClassReference/index.html#//apple_ref/c/tdef/AVAudioSessionPortOverride) – foundry Feb 13 '16 at 11:24
  • @foundry, I eventually got audio synthesis working again once I added AVFoundation.framework. – Greg Jun 03 '16 at 02:03
7
NSError *error;
[[AVAudioSession sharedInstance] overrideOutputAudioPort:AVAudioSessionPortOverrideSpeaker 
                                                   error:&error];    
if(error)
{ 
    NSLog(@"Error: AudioSession cannot use speakers");
}
Yunus Nedim Mehel
  • 12,089
  • 4
  • 50
  • 56
2
let audioSession = AVAudioSession.sharedInstance()

    do {
        try audioSession.setCategory(AVAudioSession.Category.playAndRecord, mode: .spokenAudio, options: .defaultToSpeaker)
        try audioSession.setActive(true, options: .notifyOthersOnDeactivation)
    } catch {
        print("error.")
    }  

// paste this code in your viewLoad region

Robert
  • 5,278
  • 43
  • 65
  • 115
Mirac Bektas
  • 115
  • 1
  • 2
0

Foundry’s solution together with this blog by Mario Diana has also allowed me to upgrade audio session set up code deprecated in iOS 7. My old code was based on AudioBufferPlayer by Matthijs Hollemans. Remember to add the AVFoundation.framework.

Greg
  • 1,750
  • 2
  • 29
  • 56