Enable Picture-in-Picture (PiP) mode to allow users to continue their call in a floating window while using other apps. PiP provides a seamless multitasking experience during calls.
Picture-in-Picture implementation is handled at the app level using iOS’s PiP APIs. The Calls SDK only adjusts the call UI layout to fit the PiP window - it does not manage the PiP window itself.
How It Works
- Your app enters PiP mode using iOS’s AVPictureInPictureController API
- You notify the Calls SDK by calling
enablePictureInPictureLayout()
- The SDK adjusts the call UI to fit the smaller PiP window (hides controls, optimizes layout)
- When exiting PiP, call
disablePictureInPictureLayout() to restore the full UI
Enable Picture-in-Picture
Enter PiP mode programmatically using the enablePictureInPictureLayout() action:
CallSession.shared.enablePictureInPictureLayout()
[[CallSession shared] enablePictureInPictureLayout];
Disable Picture-in-Picture
Exit PiP mode and return to the full-screen call interface:
CallSession.shared.disablePictureInPictureLayout()
[[CallSession shared] disablePictureInPictureLayout];
Listen for PiP Events
Monitor PiP mode transitions using LayoutListener to update your UI accordingly:
class CallViewController: UIViewController, LayoutListener {
override func viewDidLoad() {
super.viewDidLoad()
CallSession.shared.addLayoutListener(self)
}
deinit {
CallSession.shared.removeLayoutListener(self)
}
func onPictureInPictureLayoutEnabled() {
print("Entered PiP mode")
// Hide custom overlays or controls
hideCustomControls()
}
func onPictureInPictureLayoutDisabled() {
print("Exited PiP mode")
// Show custom overlays or controls
showCustomControls()
}
func onCallLayoutChanged(layoutType: LayoutType) {}
func onParticipantListVisible() {}
func onParticipantListHidden() {}
}
@interface CallViewController () <LayoutListener>
@end
@implementation CallViewController
- (void)viewDidLoad {
[super viewDidLoad];
[[CallSession shared] addLayoutListener:self];
}
- (void)dealloc {
[[CallSession shared] removeLayoutListener:self];
}
- (void)onPictureInPictureLayoutEnabled {
NSLog(@"Entered PiP mode");
// Hide custom overlays or controls
[self hideCustomControls];
}
- (void)onPictureInPictureLayoutDisabled {
NSLog(@"Exited PiP mode");
// Show custom overlays or controls
[self showCustomControls];
}
- (void)onCallLayoutChangedWithLayoutType:(LayoutType)layoutType {}
- (void)onParticipantListVisible {}
- (void)onParticipantListHidden {}
@end
iOS PiP Setup
To enable PiP in your iOS app:
1. Enable Background Modes
In your project’s Signing & Capabilities, add the Background Modes capability and enable:
- Audio, AirPlay, and Picture in Picture
2. Configure AVAudioSession
import AVFoundation
func configureAudioSession() {
do {
try AVAudioSession.sharedInstance().setCategory(
.playAndRecord,
mode: .videoChat,
options: [.allowBluetooth, .defaultToSpeaker]
)
try AVAudioSession.sharedInstance().setActive(true)
} catch {
print("Failed to configure audio session: \(error)")
}
}
#import <AVFoundation/AVFoundation.h>
- (void)configureAudioSession {
NSError *error = nil;
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord
mode:AVAudioSessionModeVideoChat
options:AVAudioSessionCategoryOptionAllowBluetooth | AVAudioSessionCategoryOptionDefaultToSpeaker
error:&error];
[[AVAudioSession sharedInstance] setActive:YES error:&error];
}
PiP mode is available on iOS 14.0 and later for iPhones, and iOS 9.0 and later for iPads.