import { RTCViewPipIOS } from "@stream-io/video-react-native-sdk";
<>
<RTCViewPipIOS />
<MyComponent />
</>;
Picture in picture
Picture-in-picture (PiP) mode shrinks the layout in the call into a small window so you can keep watching while using other apps on your mobile device. You can move the small window around your device’s home screen and position it over other apps.
iOS
Setup
If CallContent
component is used, the PiP mode will be activated when the app goes to background when there is an active call. If you do not need PiP mode, you can deactivate it using the disablePictureInPicture
prop of the CallContent
component.
Alternatively, if you do not use the CallContent
component but still want to enter PiP mode automatically. You can use the RTCViewPipIOS
component from the SDK in your component to enable PiP mode as below:
Current user camera
By default, iOS does not allow access to the user’s camera, while in background. To enable it, the multitasking camera access property must be true
. In apps linked against iOS 18 or later, this property is true
if voip
is present in the UIBackgroundModes
. This property also returns true
for iOS applications that have the com.apple.developer.avfoundation.multitasking-camera-access entitlement.
Enabling
If the multitasking camera access
property is true
for your app based on the above conditions, you can enable local camera feed support in our PiP implementation by below:
- By setting
iOSPiPIncludeLocalParticipantVideo
totrue
inCallContent
component. - Or by setting
includeLocalParticipantVideo
totrue
inRTCViewPipIOS
component.
After that, add the following change:
Update AppDelegate
Update AppDelegate.m
or AppDelegate.mm
in Xcode with the following parts for iOS support.
Add headers
At the top of the file, right after ‘#import “AppDelegate.h”’, add the following header to import and invoke the methods for the required library.
#import <WebRTCModuleOptions.h>
Then, add the following code to your existing didFinishLaunchingWithOptions
method,
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
WebRTCModuleOptions *options = [WebRTCModuleOptions sharedInstance];
options.enableMultitaskingCameraAccess = YES;
// the rest
}
In app.json, in the plugins
field, add the iOSEnableMultitaskingCameraAccess
property to the @stream-io/video-react-native-sdk
plugin.
{
"plugins": [
[
"@stream-io/video-react-native-sdk",
{
"iOSEnableMultitaskingCameraAccess": true,
}
],
]
}
If Expo EAS build is not used, please do npx expo prebuild --clean
to generate the native directories again after adding the config plugins.
Android
Setup
Changes to AndroidManifest
Add the following attributes to AndroidManifest.xml
file in MainActivity
:
<activity>
...
android:name=".MainActivity"
android:supportsPictureInPicture="true"
android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"
...
</activity>
Changes to MainActivity
Add the following imports:
import android.content.res.Configuration
import com.streamvideo.reactnative.StreamVideoReactNative
import android.os.Build
import androidx.lifecycle.Lifecycle
import android.content.res.Configuration;
import com.streamvideo.reactnative.StreamVideoReactNative;
import android.os.Build;
import androidx.lifecycle.Lifecycle;
After that, Add the following functions:
fun onPictureInPictureModeChanged(isInPictureInPictureMode: Boolean, newConfig: Configuration) {
super.onPictureInPictureModeChanged(isInPictureInPictureMode)
if (lifecycle.currentState === Lifecycle.State.CREATED) {
// when user clicks on Close button of PIP
finishAndRemoveTask()
} else {
StreamVideoReactNative.onPictureInPictureModeChanged(isInPictureInPictureMode, newConfig)
}
}
override fun onUserLeaveHint() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O &&
Build.VERSION.SDK_INT < Build.VERSION_CODES.S &&
StreamVideoReactNative.canAutoEnterPictureInPictureMode) {
val config = resources.configuration
onPictureInPictureModeChanged(true, config)
}
}
@Override
public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode, Configuration newConfig) {
super.onPictureInPictureModeChanged(isInPictureInPictureMode);
if (getLifecycle().getCurrentState() == Lifecycle.State.CREATED) {
// when user clicks on Close button of PIP
finishAndRemoveTask();
} else {
StreamVideoReactNative.onPictureInPictureModeChanged(isInPictureInPictureMode, newConfig);
}
}
@Override
protected void onUserLeaveHint() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O &&
Build.VERSION.SDK_INT < Build.VERSION_CODES.S &&
StreamVideoReactNative.Companion.getCanAutoEnterPictureInPictureMode()) {
Configuration config = getResources().getConfiguration();
onPictureInPictureModeChanged(true, config);
}
}
In app.json, in the plugins
field, add the androidPictureInPicture
property to the @stream-io/video-react-native-sdk
plugin.
{
"plugins": [
[
"@stream-io/video-react-native-sdk",
{
"androidPictureInPicture": true,
}
],
]
}
If Expo EAS build is not used, please do npx expo prebuild --clean
to edit the native code again after adding the config plugin property.
Keep call alive in the background
When going to PiP mode, the android app enters to background mode. In this mode for the video/audio calls to work properly we need to eep the call alive in the background. For this a foreground service must be added. Please visit our relevant documentation and complete the setup.
Entering PiP mode
If CallContent
component is used, the PiP mode will be activated on home button press. If you do not need PiP mode to be activated, you can deactivate it using the disablePictureInPicture
prop of the CallContent
component.
Alternatively, if you do not use the CallContent
component but still want to enter PiP mode automatically. You can use the useAutoEnterPiPEffect
hook from the SDK in your component to enable PiP mode in your component as below:
import { useAutoEnterPiPEffect } from "@stream-io/video-react-native-sdk";
useAutoEnterPiPEffect();
Choosing what to render on PiP mode
In PiP mode, the window is small. So you should only selectively render the important parts of the call. If you use CallContent
component, this is automatically handled. The CallContent
component shows only the dominant speaker video on PiP mode.
Alternatively, if you do not use the CallContent
component, we expose a hook named useIsInPiPMode
to listen to the state of PiP Mode as shown below:
import { useIsInPiPMode } from "@stream-io/video-react-native-sdk";
const isInPiPMode = useIsInPiPMode();
You can use the state of the boolean from the hook to selectively render whatever is necessary during PiP mode.