Question

In order to keep an eye, on an earphone possibly plugged or unplugged, in my iPhone app and react properly; I use the following kind of code, in a few of my classes:

- (void)viewDidLoad
{
    [super viewDidLoad];
    …..
    routeChangeID=kAudioSessionProperty_AudioRouteChange;
    AudioSessionAddPropertyListener(routeChangeID,rvcHandleRouteChange,(__bridge void *)(self));
}

…….

void rvcHandleRouteChange(void *inUserData,AudioSessionPropertyID inPropertyID,
                          UInt32 inPropertyValueSize,const void *inPropertyValue)
{
    NSLog(@"Hi rvcHandleRouteChange has been called.");
    if (inPropertyID!=kAudioSessionProperty_AudioRouteChange) NSLog(@"WRONG CALL!!!");
    // Do some useful work ….
}

That seems to work rather well, except in one case where the rvcHandleRouteChange call back function gets called with no apparent reason. Even with the test to filter the wrong calls, none of them appear to be "WRONG CALLs". I mean it gets called without me to plug or unplug any earphone. As a consequence this gives me a lot of trouble.

Anyone has an idea of why this could happen?

Was it helpful?

Solution

1: A route change call can happen even twice. For example if you plug in your headphones (same route change reason code).

2: RouteChange gets called once you set your audio session active. That means at least once.

Maybe you are implementing your own audio interruptions where you activate/deactivate audio sessions?

Here is mine route change listener for any use (I use playAndRecord category) [updated to iOS7]:

#pragma mark Route change listener
// *********************************************************************************************************
// *********** Route change listener ***********************************************************************
// *********************************************************************************************************
-(void)routeChanged:(NSNotification*)notification {

    NSLog(@"]-----------------[ Audio Route Change ]--------------------[");

    AVAudioSession *session = [AVAudioSession sharedInstance];

    //AVAudioSessionRouteDescription* prevRoute = [[notification userInfo] objectForKey:AVAudioSessionRouteChangePreviousRouteKey];

    // Reason
    NSInteger reason = [[[notification userInfo] objectForKey:AVAudioSessionRouteChangeReasonKey] integerValue];
    switch (reason) {
        case AVAudioSessionRouteChangeReasonNoSuitableRouteForCategory:
            NSLog(@"] Audio Route: The route changed because no suitable route is now available for the specified category.");
            break;
        case AVAudioSessionRouteChangeReasonWakeFromSleep:
            NSLog(@"] Audio Route: The route changed when the device woke up from sleep.");
            break;
        case AVAudioSessionRouteChangeReasonOverride:
            NSLog(@"] Audio Route: The output route was overridden by the app.");
            break;
        case AVAudioSessionRouteChangeReasonCategoryChange:
            NSLog(@"] Audio Route: The category of the session object changed.");
            break;
        case AVAudioSessionRouteChangeReasonOldDeviceUnavailable:
            NSLog(@"] Audio Route: The previous audio output path is no longer available.");
            break;
        case AVAudioSessionRouteChangeReasonNewDeviceAvailable:
            NSLog(@"] Audio Route: A preferred new audio output path is now available.");
            break;
        case AVAudioSessionRouteChangeReasonUnknown:
            NSLog(@"] Audio Route: The reason for the change is unknown.");
            break;
        default:
            NSLog(@"] Audio Route: The reason for the change is very unknown.");
            break;
    }

    // Output
    AVAudioSessionPortDescription *output = [[session.currentRoute.outputs count]?session.currentRoute.outputs:nil objectAtIndex:0];
    if ([output.portType isEqualToString:AVAudioSessionPortLineOut]) {
        NSLog(@"] Audio Route: Output Port: LineOut");
    }
    else if ([output.portType isEqualToString:AVAudioSessionPortHeadphones]) {
        NSLog(@"] Audio Route: Output Port: Headphones");
    }
    else if ([output.portType isEqualToString:AVAudioSessionPortBluetoothA2DP]) {
        NSLog(@"] Audio Route: Output Port: BluetoothA2DP");
    }
    else if ([output.portType isEqualToString:AVAudioSessionPortBuiltInReceiver]) {
        NSLog(@"] Audio Route: Output Port: BuiltInReceiver");
    }
    else if ([output.portType isEqualToString:AVAudioSessionPortBuiltInSpeaker]) {
        NSLog(@"] Audio Route: Output Port: BuiltInSpeaker");
    }
    else if ([output.portType isEqualToString:AVAudioSessionPortHDMI]) {
        NSLog(@"] Audio Route: Output Port: HDMI");
    }
    else if ([output.portType isEqualToString:AVAudioSessionPortAirPlay]) {
        NSLog(@"] Audio Route: Output Port: AirPlay");
    }
    else if ([output.portType isEqualToString:AVAudioSessionPortBluetoothLE]) {
        NSLog(@"] Audio Route: Output Port: BluetoothLE");
    }
    else {
        NSLog(@"] Audio Route: Output Port: Unknown: %@",output.portType);
    }

    // Input
    AVAudioSessionPortDescription *input = [[session.currentRoute.inputs count] ? session.currentRoute.inputs:nil objectAtIndex:0];

    if ([input.portType isEqualToString:AVAudioSessionPortLineIn]) {
        NSLog(@"] Audio Route: Input Port: LineIn");
    }
    else if ([input.portType isEqualToString:AVAudioSessionPortBuiltInMic]) {
        NSLog(@"] Audio Route: Input Port: BuiltInMic");
    }
    else if ([input.portType isEqualToString:AVAudioSessionPortHeadsetMic]) {
        NSLog(@"] Audio Route: Input Port: HeadsetMic");
    }
    else if ([input.portType isEqualToString:AVAudioSessionPortBluetoothHFP]) {
        NSLog(@"] Audio Route: Input Port: BluetoothHFP");
    }
    else if ([input.portType isEqualToString:AVAudioSessionPortUSBAudio]) {
        NSLog(@"] Audio Route: Input Port: USBAudio");
    }
    else if ([input.portType isEqualToString:AVAudioSessionPortCarAudio]) {
        NSLog(@"] Audio Route: Input Port: CarAudio");
    }
    else {
        NSLog(@"] Audio Input Port: Unknown: %@",input.portType);
    }

    NSLog(@"]--------------------------[  ]-----------------------------[");

}

Remember to add observer since the audio session's delegate is deprecated too:

[[NSNotificationCenter defaultCenter] addObserver: self
                                                 selector: @selector(audioInterruption:)
                                                     name: AVAudioSessionInterruptionNotification
                                                   object: nil];
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top