In the activity tag of your AndroidManifest.xml file, do the following:
- Add
supportsPictureInPictureand set it totrueto declare you'll be using PiP in your app. Add
configChangesand set it toorientation|screenLayout|screenSize|smallestScreenSizeto specify that your activity handles layout configuration changes. This way, your activity doesn't relaunch when layout changes occur during PiP mode transitions.<activity android:name=".SnippetsActivity" android:exported="true" android:supportsPictureInPicture="true" android:configChanges="orientation|screenLayout|screenSize|smallestScreenSize" android:theme="@style/Theme.Snippets">
In your Compose code, do the following:
- Add this extension on
Context. You'll use this extension multiple times throughout the guide to access the activity.internal fun Context.findActivity(): ComponentActivity { var context = this while (context is ContextWrapper) { if (context is ComponentActivity) return context context = context.baseContext } throw IllegalStateException("Picture in picture should be called in the context of an Activity") }
Add PiP on leave app for pre-Android 12
To add PiP for pre-Android 12, use addOnUserLeaveHintProvider. Follow
these steps to add PiP for pre-Android 12:
- Add a version gate so that this code is only accessed in versions O until R.
- Use a
DisposableEffectwithContextas the key. - Inside the
DisposableEffect, define the behavior for when theonUserLeaveHintProvideris triggered using a lambda. In the lambda, callenterPictureInPictureMode()onfindActivity()and pass inPictureInPictureParams.Builder().build(). - Add
addOnUserLeaveHintListenerusingfindActivity()and pass in the lambda. - In
onDispose, addremoveOnUserLeaveHintListenerusingfindActivity()and pass in the lambda.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && Build.VERSION.SDK_INT < Build.VERSION_CODES.S ) { val context = LocalContext.current DisposableEffect(context) { val onUserLeaveBehavior = Runnable { context.findActivity() .enterPictureInPictureMode(PictureInPictureParams.Builder().build()) } context.findActivity().addOnUserLeaveHintListener( onUserLeaveBehavior ) onDispose { context.findActivity().removeOnUserLeaveHintListener( onUserLeaveBehavior ) } } } else { Log.i("PiP info", "API does not support PiP") }
Add PiP on leave app for post-Android 12
Post-Android 12, the PictureInPictureParams.Builder is added through a
modifier that is passed to the app's video player.
- Create a
modifierand callonGloballyPositionedon it. The layout coordinates will be used in a later step. - Create a variable for the
PictureInPictureParams.Builder(). - Add an
ifstatement to check if the SDK is S or above. If so, addsetAutoEnterEnabledto the builder and set it totrueto enter PiP mode upon swipe. This provides a smoother animation than going throughenterPictureInPictureMode. - Use
findActivity()to callsetPictureInPictureParams(). Callbuild()on thebuilderand pass it in.
val pipModifier = modifier.onGloballyPositioned { layoutCoordinates -> val builder = PictureInPictureParams.Builder() if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { builder.setAutoEnterEnabled(true) } context.findActivity().setPictureInPictureParams(builder.build()) } VideoPlayer(pipModifier)
Use setAspectRatio to set PiP window's aspect ratio
To set the aspect ratio of the PiP window, you can either choose a specific
aspect ratio or use the width and height of the player's video size. If you are
using a media3 player, check that the player is not null and that the player's
video size is not equal to [VideoSize.UNKNOWN][6] before setting the aspect
ratio.
val context = LocalContext.current val pipModifier = modifier.onGloballyPositioned { layoutCoordinates -> val builder = PictureInPictureParams.Builder() if (shouldEnterPipMode && player != null && player.videoSize != VideoSize.UNKNOWN) { val sourceRect = layoutCoordinates.boundsInWindow().toAndroidRectF().toRect() builder.setSourceRectHint(sourceRect) builder.setAspectRatio( Rational(player.videoSize.width, player.videoSize.height) ) } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { builder.setAutoEnterEnabled(shouldEnterPipMode) } context.findActivity().setPictureInPictureParams(builder.build()) } VideoPlayer(pipModifier)
If you are using a custom player, set the aspect ratio on the player's height and width using the syntax specific to your player. Be aware that if your player resizes during initialization, if it falls outside of the valid bounds of what the aspect ratio can be, your app will crash. You may need to add checks around when the aspect ratio can be calculated, similar to how it is done for a media3 player.