Tuesday, May 13, 2014

iOS Audio Session - Hands on

Below was what i had implemented for a test app for a hands on with audio framework.
With this approach, it did not really work well to resume back the audio even though i had placed the interruption handling code and upon resuming after interruption, started the player again.

Below is what is noticed through this exercise

With interruption handling code like in below lines:
- Incoming call comes in, application is pushed to background, after the call interruption, either ignore or accept the call, application doesnt resume playing the sound
- User pushed the app to background and initiates a call, the audio gets paused and after disconnecting the call, the audio doesnt get resumed.
- User is answering the call, and the application is brought to foreground while the app is playing. Now disconnect the call. This doesnt seem to resume the play back again
- Device is locked state playing the sound, and now interruption comes in and other end ignores the call. This also doesnt seem to resume the audio play!
- The only time it seem to be able to resume the play is when the app is foreground, interruption happend and interruption was ended from the caller end.

-(void) startPlayer
{
    if(self.audioPlayer == nil)
    {
        self.audioPlayer = [[AVPlayer alloc]initWithURL:[[NSURL alloc]initWithString:@"http://streamurl"]];
    }
    currentState = ePlayerStatePlaying;
    [self.audioPlayer play];

}

-(void) stopPlayer
{
    if(self.audioPlayer == nil)
    {
        NSLog(@"-- invalid state. Player is already nil");
        return;
    }
    currentState = ePlayerStateStopped;
    [self.audioPlayer pause];
}

For this work, the AVPlayer was used. 

also the AVAudioSession was customized to have the playback category when application is getting loaded 

AVAudioSession* audio = [AVAudioSession sharedInstance];
    [audio setCategory: AVAudioSessionCategoryPlayback error: nil];
    [audio setActive: YES error: nil];

to handle the interruption, NSNotification was added 

[[NSNotificationCenter defaultCenter] addObserver: self
                                             selector:@selector(handleInterruption:)
                                                 name:AVAudioSessionInterruptionNotification
                                               object:[AVAudioSession sharedInstance]];

In the interruption handling code, below was written 

-(void) handleInterruption:(NSNotification*)notification
{
    if (notification.userInfo) {
        int interruptionType = [notification.userInfo[AVAudioSessionInterruptionTypeKey] intValue];
        if (interruptionType == AVAudioSessionInterruptionTypeBegan) {
            [self beginInterruption];
        } else if (interruptionType == AVAudioSessionInterruptionTypeEnded) {
            [self endInterruption];
        }
    }
}

The above code was only resuming the app when app was in foreground and the interruption ended.
This is fixed by few forum searches.

The below statement is added before starting the player

[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];

the interruption handler code is modified like below 

-(void) handleInterruption:(NSNotification*)notification
{
    if (notification.userInfo) {
        int interruptionType = [notification.userInfo[AVAudioSessionInterruptionTypeKey] intValue];
        if (interruptionType == AVAudioSessionInterruptionTypeBegan) {
            [self beginInterruption];
        } else if (interruptionType == AVAudioSessionInterruptionTypeEnded) {
            int interruptionOption = [notification.userInfo[AVAudioSessionInterruptionOptionKey] intValue];
            if(interruptionOption == AVAudioSessionInterruptionOptionShouldResume)
            {
                NSLog(@"--- AVAudioSessionInterruptionOptionShouldResume ---");
                [self endInterruption];
            }
            else
            {
                 NSLog(@"--- AVAudioSessionInterruptionOptionShouldResume after dealy ---");
                 [self performSelector:@selector(endInterruption) withObject:nil afterDelay:1.0];
            }
        }
    }
}

No comments:

Post a Comment