Enabling Picture in Picture mode

In order to make use of the Picture in Picture functionality provided by the player, it is first necessary to configure your native application to properly support PiP.

The steps required for each platform are described below.

Android

Declare Picture in Picture support on AndroidManifest.xml

Open android/app/src/main/AndroidManifest.xml and set android:supportsPictureInPicture to true on your main activity's manifest. Also, specify that your activity handles layout configuration changes so that your activity doesn't relaunch when layout changes occur during PiP mode transitions:

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

iOS

Set background modes capability

Make sure to add the UIBackgroundModes key to the dict section of your Info.plist:

<key>UIBackgroundModes</key>
<array>
  <string>audio</string>
</array>

This step can also be performed from Xcode.

Configure audio session on app startup

Configure your app's AudioSession category to playback during the main component's initialization:

import { AudioSession } from 'bitmovin-player-react-native';

// App's root component
const App = () => {
  useEffect(() => {
    // Set your app's `AudioSession` category to `playback` on initialization.
    // Please, note even though this step is required for iOS it won't take any effect on Android.
    AudioSession.setCategory('playback').catch((error) => {
      // Handle any native error that might occur during this process.
      handleError(error);
    });
  });
  // ...
  return /* ... */;
};

This step is required in order to properly enable background playback on iOS. Without it, the Picture in Picture option appears on the player UI, but has no effect when used.

You can read more about it in Apple's documentation.

Showing the Picture in Picture UI option

Now that your native application is properly configured to support PiP, the player instance in your JavaScript code can be configured to show the Picture in Picture option in the Player UI.

Simply create aPictureInPictureConfig and set it to the PlayerView instance via a PlayerViewConfig:

const playerViewConfig: PlayerViewConfig = {
  pictureInPictureConfig: {
    isEnabled: true,
  },
};

<PlayerView
  player={player}
  config={playerViewConfig}
/>

Adjust the UI for Picture in Picture mode on Android

Since PiP mode on Android is just a whole Activity displayed in a small floating window this usually means hiding all the UI elements except for the PlayerView. You can do this by listening to onPictureInPictureEnter and onPictureInPictureExit events to track the current PiP state and use it to adjust the UI.

const onPictureInPictureEnterEvent = useCallback(() => {
  setIsInPictureInPicture(true);
}, []);
const onPictureInPictureExitEvent = useCallback(() => {
  setIsInPictureInPicture(false);
}, []);

// Since PiP on Android is basically just the whole activity fitted in a small
// floating window, we only want to render the player and hide any other UI.
let renderOnlyPlayerView = Platform.OS === 'android' && isInPictureInPicture;

return (
    <>
      {renderOnlyPlayerView ? null : <Toolbar/>}
      <PlayerView
          player={player}
          config={playerViewConfig}
          onPictureInPictureEnter={onPictureInPictureEnterEvent}
          onPictureInPictureExit={onPictureInPictureExitEvent}
      />
    </>
)

You can read more about PiP on Android here.

Supported Picture in Picture events

The supported Picture in Picture events on PlayerView are:

  • onPictureInPictureEnter
  • onPictureInPictureExit

iOS only:

  • onPictureInPictureEntered
  • onPictureInPictureExited

Android only

  • onPictureInPictureAvailabilityChanged

Refer to events.ts for more details.