Fullscreen Implementation Guide

How immersive mode works with the StreamLayer SDK and what to watch for when implementing fullscreen on Android.

Unlike iOS and Web, Android's native immersive mode does not prevent the StreamLayer SDK from rendering formats like sidebar, L-bar, or PIP. Android's "fullscreen" mode simply hides the system bars (status bar and navigation bar) — it does not take control of the view hierarchy or restrict how the app lays out its views.

This means most Android integrations work in fullscreen without any special handling. This guide covers the setup and the edge cases to watch for.

Why Android Is Different

On iOS, native fullscreen (AVPlayerViewController) takes over the display and prevents the host app from resizing the video. On Web, the Fullscreen API applies forced CSS constraints. Android has neither of these limitations.

Android immersive mode uses WindowInsetsControllerCompat to hide system bars:

// Standard Android immersive mode — this does NOT affect StreamLayer
val controller = WindowCompat.getInsetsController(window, window.decorView)
controller.hide(WindowInsetsCompat.Type.systemBars())
controller.systemBarsBehavior =
    WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE

After this call, the system bars are hidden but your Activity's view hierarchy is unchanged. The StreamLayerFragment and your PlayerView remain siblings in the same ConstraintLayout, and you can resize either one freely.

Standard Fullscreen Setup

Place the StreamLayerFragment alongside your player view in a ConstraintLayout, then enter immersive mode. The SDK's layout system works identically in both windowed and fullscreen states.

<androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.host.app.PlayerView
        android:id="@+id/playerView"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent" />

    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/streamLayerContainer"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintTop_toTopOf="@id/playerView"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

When the SDK triggers a sidebar or L-bar format, it calls your layout listener to adjust the player view constraints. This works the same whether system bars are visible or hidden.

// Listen for layout changes and forward to SDK — works in both modes
binding.playerView.addOnLayoutChangeListener(layoutListener)

See the Layout Guide for the full layout listener implementation.

Edge Cases to Watch For

Third-Party Players With Custom Fullscreen

Some third-party video player libraries implement their own fullscreen by launching a new Activity or Dialog. If the player does this, the StreamLayerFragment will not be part of that new Activity's view hierarchy, so SDK UI will not appear.

If you use a third-party player, verify that its fullscreen mode stays within the same Activity and view hierarchy. If it does not, you have two options: disable the player's built-in fullscreen and implement your own (using immersive mode as shown above), or re-add the StreamLayerFragment to the player's fullscreen Activity.

Multi-Window and Freeform Mode

On tablets and foldables, Android supports multi-window and freeform window modes. The StreamLayer SDK handles these correctly as long as the StreamLayerFragment has accurate layout dimensions. Call overlayHeightSpace to update the SDK when the window size changes:

// Update SDK when window size changes (multi-window, foldable unfold, etc.)
binding.playerView.addOnLayoutChangeListener { _, _, _, _, _, _, _, _, _ ->
    streamLayerFragment.overlayHeightSpace = binding.playerView.height
}

Picture-in-Picture (System PIP)

Android's system PIP mode (enterPictureInPictureMode()) shrinks the entire Activity to a small floating window. The StreamLayer SDK should be hidden during system PIP because the window is too small for interactive content. Use the onPictureInPictureModeChanged callback to hide and restore the SDK:

override fun onPictureInPictureModeChanged(isInPipMode: Boolean) {
    super.onPictureInPictureModeChanged(isInPipMode)
    if (isInPipMode) {
        // Hide StreamLayer UI during system PIP
        binding.streamLayerContainer.visibility = View.GONE
    } else {
        binding.streamLayerContainer.visibility = View.VISIBLE
    }
}

Quick Reference

ScenarioSDK Formats Work?Notes
Immersive mode (system bars hidden)YesStandard approach, no issues
Third-party player fullscreen (same Activity)YesVerify player stays in your Activity
Third-party player fullscreen (new Activity)NoDisable player's fullscreen, use immersive mode instead
System PIP modeNoWindow too small — hide SDK, restore on exit
Multi-window / freeformYesForward layout changes to SDK

Related