# Picture in Picture (PiP)

Picture in picture (PIP) keeps the call running and visible while you navigate to other apps.

### Enable Picture-in-Picture

To enable **Picture-in-Picture (PiP)**, set the `enablePictureInPicture` property to true in the `PictureInPictureConfiguration` provided to the `StreamCallContainer` or `StreamCallContent` widget.
Additionally, you can control whether PiP remains enabled when the local device is screen sharing using the `disablePictureInPictureWhenScreenSharing` parameter (disabled by default).

```dart
StreamCallContainer(
    call: widget.call,
    pictureInPictureConfiguration: const PictureInPictureConfiguration(
        enablePictureInPicture: true,
        disablePictureInPictureWhenScreenSharing: true,
    ),
)
```

#### Keep the Connection Active in Background

For Picture-in-Picture to function properly while the app is in the background, it is important to keep the connection to Stream backend active.
This is controlled by the `keepConnectionsAliveWhenInBackground` property in `StreamVideoOptions`, which must be set to `true`.

Additionally, to ensure the local participant remains visible and audible in PiP mode, ensure `muteVideoWhenInBackground` and `muteAudioWhenInBackground` are set to false (false by default).

```dart
  StreamVideo(
    apiKey,
    user: user,
    token: token,
    options: const StreamVideoOptions(
      muteAudioWhenInBackground: false,
      muteVideoWhenInBackground: false,
      keepConnectionsAliveWhenInBackground: true,
    ),
  );
```

## Android

### Quick Setup with StreamFlutterActivity

The easiest way to add PiP support is to extend `StreamFlutterActivity` instead of `FlutterActivity`:

```kotlin
// MainActivity.kt
import io.getstream.video.flutter.stream_video_flutter.StreamFlutterActivity

class MainActivity : StreamFlutterActivity() {
    // All PiP functionality is automatically handled!
    // Add your custom logic here if needed

    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)

        // Your custom Flutter engine configuration
    }
}
```

### What StreamFlutterActivity Does

`StreamFlutterActivity` automatically handles:

- **PiP Initialization**: Sets up the PictureInPictureHelper with your Flutter engine
- **Automatic Triggers**: Enters PiP mode when:
  - User presses the home button (`onUserLeaveHint`)
  - App is backgrounded during an active call (`onPause`)
- **Mode Change Notifications**: Notifies Flutter when PiP mode changes
- **Optimal Aspect Ratios**: Automatically sets appropriate aspect ratios
- **Android Version Compatibility**: Works across different Android versions

### Advanced: Manual Setup

If you prefer to set up PiP manually or need more control:

```kotlin
class MainActivity : FlutterActivity() {

    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)

        // Initialize PiP helper
        PictureInPictureHelper.initializeWithFlutterEngine(flutterEngine) { this }
    }

    override fun onUserLeaveHint() {
        super.onUserLeaveHint()
        PictureInPictureHelper.handlePipTrigger(this)
    }

    override fun onPause() {
        super.onPause()
        if (!isFinishing) {
            PictureInPictureHelper.handlePipTrigger(this)
        }
    }

    override fun onPictureInPictureModeChanged(
        isInPictureInPictureMode: Boolean,
        newConfig: Configuration
    ) {
        super.onPictureInPictureModeChanged(isInPictureInPictureMode, newConfig)
        PictureInPictureHelper.notifyPictureInPictureModeChanged(this, isInPictureInPictureMode)
    }
}
```

### Configuration Options

#### PictureInPictureConfiguration

```dart
PictureInPictureConfiguration(
  enablePictureInPicture: true,
  disablePictureInPictureWhenScreenSharing: true,
  sort: CallParticipantSortingPresets.speaker, // Custom participant sorting
  androidPiPConfiguration: AndroidPictureInPictureConfiguration(
    callPictureInPictureWidgetBuilder: (context, call) {
      // Custom PiP overlay widget
      return YourCustomPiPWidget(call: call);
    },
  ),
)
```

### Android Permissions

Enable PiP for your activity and update the configChanges in `android/app/src/main/AndroidManifest.xml`:

```xml
<activity
    android:name=".MainActivity"
    android:supportsPictureInPicture="true"
    android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"
    ... >
```

### Troubleshooting

#### PiP Not Working?

1. **Check Permissions**: Ensure `supportsPictureInPicture="true"` is set in AndroidManifest.xml
2. **Check Flutter Configuration**: Ensure `enablePictureInPicture: true` in your Flutter code
3. **Check Android Version**: PiP requires Android 7.0 (API level 24) or higher
4. **Check Device Support**: Some devices/manufacturers may disable PiP

#### PiP Overlay Not Showing?

1. **Widget Tree**: Ensure `StreamCallContent` or `StreamPictureInPictureAndroidView` is in your widget tree
2. **Call State**: PiP only activates during active calls (connected state)
3. **Screen Sharing**: PiP is disabled during screen sharing by default

### Migration from Old API

If you're migrating from the old PiP API:

#### ❌ Remove These (Deprecated)

```dart
// Remove manual PiP calls
await StreamVideoFlutterBackground.setPictureInPictureEnabled(enable: true);
```

```kotlin
// Remove manual PiP triggers
override fun onUserLeaveHint() {
    super.onUserLeaveHint()
    PictureInPictureHelper.enterPictureInPictureIfInCall(this) // Deprecated
}
```

#### ✅ Use This Instead

```kotlin
// Simply extend StreamFlutterActivity
class MainActivity : StreamFlutterActivity()
```

```dart
// Configure in Flutter
StreamCallContent(
  call: call,
  pictureInPictureConfiguration: PictureInPictureConfiguration(
    enablePictureInPicture: true,
  ),
)
```

## iOS

### Local camera feed in Picture-in-Picture mode

By default, iOS does not allow access to the user's camera while the app is in the background. To enable it, the **multitasking camera access** property must be set to true.

For apps linked against **iOS 18 or later**, this property is [automatically true](https://developer.apple.com/documentation/AVFoundation/AVCaptureSession/isMultitaskingCameraAccessSupported) if _voip_ is included in `UIBackgroundModes`. Additionally, apps with the `com.apple.developer.avfoundation.multitasking-camera-access` [entitlement](https://developer.apple.com/documentation/bundleresources/entitlements/com_apple_developer_avfoundation_multitasking-camera-access) will also have multitasking camera access enabled.

If the multitasking camera access property is true for your app based on the above conditions, the local camera feed will be visible in PiP mode. However, if you prefer to disable the local feed in PiP mode, set `includeLocalParticipantVideo` to false:

```dart
  StreamCallContainer(
    call: widget.call,
    callContentWidgetBuilder: (
        BuildContext context,
        Call call,
        ) {
      return StreamCallContent(
        call: call,
        callState: callState,
        pictureInPictureConfiguration: const PictureInPictureConfiguration(
          enablePictureInPicture: true,
          iOSPiPConfiguration: IOSPictureInPictureConfiguration(
            includeLocalParticipantVideo: false,
          )
        ),
      );
    },
  );
```

### Enabling PiP support with custom call content widget

If you are not using our `StreamCallContent` and instead building custom call content widget you can still enable Picture in Picture mode by adding `StreamPictureInPictureUiKitView` anywhere in the widget tree. This widget will handle the Picture in Picture mode in iOS for you.

```dart
  StreamCallContainer(
    call: widget.call,
    callContentWidgetBuilder: (
        BuildContext context,
        Call call,
        ) {
      return Stack(
        children: [
          StreamPictureInPictureUiKitView(call: call),
          // YOUR CUSTOM WIDGET
        ],
      );
    },
  );
```

Done. Now after leaving the app, you'll see that the call will be still alive in the background like the one below:

![Picture in Picture example](@video/flutter/_assets/advanced_assets/pip_example.png)

## In-App Picture in Picture

The system-level Picture in Picture described above only works when users navigate away from your app to other applications. It does not provide a floating video view within your own app when users navigate between different screens.

If you want to keep the call visible while users navigate within your app (for example, when browsing content, accessing chat, or using other features), you'll need to implement **in-app picture-in-picture**.

For a complete implementation guide with code examples, see our [In-App Picture in Picture cookbook](/video/docs/flutter/ui-cookbook/in-app-picture-in-picture/).


---

This page was last updated at 2026-05-22T16:32:24.509Z.

For the most recent version of this documentation, visit [https://getstream.io/video/docs/flutter/advanced/picture-in-picture/](https://getstream.io/video/docs/flutter/advanced/picture-in-picture/).