Skip to content

Latest commit

 

History

History
60 lines (50 loc) · 8.36 KB

managing-audio-interruptions.md

File metadata and controls

60 lines (50 loc) · 8.36 KB

Managing Audio Interruptions

Different versions of iOS deal with AVAudioSession interruptions sightly differently. This section documents how the Programmable Voice iOS SDK manages audio interruptions and resumes call audio after the interruption ends. There are currently some cases that the SDK cannot resume call audio automatically because iOS does not provide the necessary notifications to indicate that the interruption has ended.

How Programmable Voice iOS SDK handles audio interruption

  • The TVOCall object registers itself as an observer of AVAudioSessionInterruptionNotification when it's created.
  • When the notification is fired and the interruption type is AVAudioSessionInterruptionTypeBegan, the TVOCall object automatically disables both the local and remote audio tracks.
  • When the SDK receives the notification with AVAudioSessionInterruptionTypeEnded, it re-enables the local and remote audio tracks and resumes the audio of active Calls.
    • We have noticed that on iOS 8 and 9, the interruption notification with AVAudioSessionInterruptionTypeEnded is not always fired therefore the SDK is not able to resume call audio automatically. This is a known issue and an alternative way is to use the UIApplicationDidBecomeActiveNotification and resume audio when the app is active again after the interruption.

Notifications in different iOS versions

Below is a table listing the system notifications received with different steps to trigger audio interruptions and resume during an active Voice SDK call. (Assume the app is in an active Voice SDK call)

Scenario Notification of interruption-begins Notification of interruption-ends Call audio resumes? Note
PSTN Interruption
A.
PSTN interruption
Accept the PSTN incoming call
Remote party of PSTN call hangs up
✅ iOS 9
✅ iOS 10
✅ iOS 11
✅ iOS 9
✅ iOS 10
✅ iOS 11
✅ iOS 9
✅ iOS 10
✅ iOS 11
B.
PSTN interruption
Accept the PSTN incoming call
Local party of PSTN call hangs up
✅ iOS 9
✅ iOS 10
✅ iOS 11
✅ iOS 9
✅ iOS 10
✅ iOS 11
✅ iOS 9
✅ iOS 10
✅ iOS 11
C.
PSTN interruption
Reject PSTN
✅ iOS 9
✅ iOS 10
✅ iOS 11
✅ iOS 9
✅ iOS 10
✅ iOS 11
✅ iOS 9
✅ iOS 10
✅ iOS 11
D.
PSTN interruption
Ignore PSTN
✅ iOS 9
✅ iOS 10
✅ iOS 11
✅ iOS 9
✅ iOS 10
✅ iOS 11
✅ iOS 9
✅ iOS 10
✅ iOS 11
E.
PSTN interruption
Remote party of PSTN call hangs up before local party can answer
✅ iOS 9
✅ iOS 10
✅ iOS 11
✅ iOS 9
✅ iOS 10
✅ iOS 11
✅ iOS 9
✅ iOS 10
✅ iOS 11
Other Types of Audio Interruption
(YouTube app as example)
F.
Switch to YouTube app and play video
Stop the video
Switch back to Voice app
✅ iOS 9
✅ iOS 10
✅ iOS 11
❌ iOS 9
✅ iOS 10
✅ iOS 11
❌ iOS 9
✅ iOS 10
✅ iOS 11
Interruption-ended notification is not fired on iOS 9.
Interruption-ended notification is not fired until few seconds after switching back to the Voice app on iOS 10/11.
The AVAudioSessionInterruptionOptionShouldResume flag is false.
G.
Switch to YouTube app and play video
Switch back to Voice app without stopping the video
✅ iOS 9
✅ iOS 10
✅ iOS 11
❌ iOS 9
✅ iOS 10
✅ iOS 11
❌ iOS 9
✅ iOS 10
✅ iOS 11
Interruption-ended notification is not fired on iOS 9.
Interruption-ended notification is not fired until few seconds after switching back to the Voice app on iOS 10/11.
The AVAudioSessionInterruptionOptionShouldResume flag is false.
H.
Switch to YouTube app and play video
Double-press Home button and terminate YouTube app
Back to Voice app
✅ iOS 9
✅ iOS 10
✅ iOS 11
✅ iOS 9
✅ iOS 10
✅ iOS 11
✅ iOS 9
✅ iOS 10
✅ iOS 11
Interruption-ended notification is not fired until the Voice app is back to the active state.
The AVAudioSessionInterruptionOptionShouldResume flag is false.

CallKit

On iOS 10 and later, CallKit (if integrated) takes care of the interruption by providing a set of delegate methods so that the application can respond with proper audio device handling and state transitioning in order to ensure call audio works after the interruption has ended.

Notifications & Callbacks during Interruption

By enabling the supportsHolding flag of the CXCallUpdate object when reporting a call to the CallKit framework, you will see the "Hold & Accept" option when there is another PSTN or CallKit-enabled call. By pressing the "Hold & Accept" option, a series of things and callbacks will happen:

  1. The provider:performSetHeldCallAction: delegate method is called with CXSetHeldCallAction.isOnHold = YES. Put the Voice call on-hold here and fulfill the action.
  2. The AVAudioSessionInterruptionNotification notification is fired to indicate the AVAudioSession interruption has started.
  3. CallKit will deactivate the AVAudioSession of your app and fire the provider:didDeactivateAudioSession: callback.
  4. When the interrupting call ends, instead of getting the AVAudioSessionInterruptionNotification notification, the system will notify that you can resume the call audio that was put on-hold when the interruption began by calling the provider:performSetHeldCallAction: method again. Note that this callback is not fired if the interrupting call is disconnected by the remote party.
  5. The AVAudioSession of the app will be activated again and you should re-enable the audio device of the SDK TwilioVoice.audioDevice.enabled = YES in the provider:didActivateAudioSession: method.
Scenario Audio resumes after interrupion? Note
A.
Hold & Accept
Hang up PSTN interruption on the local end
✅ iOS 10
✅ iOS 11
B.
Hold & Accept
Remote party hangs up PSTN interruption
❌ iOS 10
❌ iOS 11
provider:performSetHeldCallAction: not called after the interruption ends.
C.
Hold & Accept
Switch back to the Voice Call on system UI
✅ iOS 10
✅ iOS 11
D.
Reject
✅ iOS 10
✅ iOS 11
No actual audio interruption happened since the interrupting call is not answered
E.
Ignore
✅ iOS 10
✅ iOS 11
No actual audio interruption happened since the interrupting call is not answered

In case 2, CallKit does not automatically resume call audio by calling provider:performSetHeldCallAction: method, but the system UI will show that the Voice call is still on-hold. You can resume the call using the "Hold" button, or use the CXSetHeldCallAction to lift the on-hold state programmatically. The app is also responsible of updating UI state to indicate the "hold" state of the call to avoid user confusion.

// Resume call audio programmatically after interruption
CXSetHeldCallAction *setHeldCallAction = [[CXSetHeldCallAction alloc] initWithCallUUID:self.call.uuid onHold:holdSwitch.on];
CXTransaction *transaction = [[CXTransaction alloc] initWithAction:setHeldCallAction];
[self.callKitCallController requestTransaction:transaction completion:^(NSError *error) {
    if (error) {
        NSLog(@"Failed to submit set-call-held transaction request");
    } else {
        NSLog(@"Set-call-held transaction successfully done");
    }
}];