Implementing Multi-Window for Android Applications
Multi-Window is a split-screen mode on Android 7.0+ (API 24) and Picture-in-Picture for Android 8.0+ (API 26). Starting with Android 12, split-screen mode is enabled by default for all applications unless explicitly disabled via android:resizeableActivity="false". This means your application may already be in split-screen for users, and if it's not prepared for this, the UI breaks.
What "Multi-Window Ready" Means
An application running in split-screen receives changed window dimensions several times per second when the divider moves. Each change triggers either onConfigurationChanged() or Activity recreation (if android:configChanges is not specified). If the Activity is recreated with each divider movement, users experience flickering and state loss.
The correct approach is to declare in the manifest that the Activity handles configuration changes itself:
<activity
android:name=".MainActivity"
android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"
android:resizeableActivity="true" />
In onConfigurationChanged(), recalculate the layout without recreation—use WindowMetrics API (API 30+) or DisplayMetrics for older versions.
Responsive UI. With Jetpack Compose: use BoxWithConstraints or WindowSizeClass from androidx.window:window to determine the current window class (Compact, Medium, Expanded). Don't hardcode a "tablet layout" based on isTablet()—check the actual available window size, which in split-screen on a tablet may be as small as on a phone.
Picture-in-Picture
PiP is activated via enterPictureInPictureMode(PictureInPictureParams). A typical use case is a video player. When transitioning to PiP:
val params = PictureInPictureParams.Builder()
.setAspectRatio(Rational(16, 9))
.setActions(listOf(
RemoteAction(/* pause/play */),
RemoteAction(/* next track */)
))
.build()
enterPictureInPictureMode(params)
RemoteAction represents buttons visible in the PiP window. Clicks send a PendingIntent—typically to a BroadcastReceiver within the Activity.
Issue: onStop() is called when entering PiP. If the video player stops in onStop(), playback is interrupted. Solution: check isInPictureInPictureMode in onStop() and skip stopping the player.
override fun onStop() {
super.onStop()
if (!isInPictureInPictureMode) {
player.pause()
}
}
onPictureInPictureModeChanged() is a callback for updating the UI: hide control buttons in PiP mode, showing only the video content.
Drag and Drop Between Windows
Starting with API 24, drag-and-drop between applications in split-screen is supported. To receive: use View.setOnDragListener() and handle DragEvent.ACTION_DROP. To initiate: use View.startDragAndDrop() with ClipData. From API 33 onwards, an improved DropHelper from androidx.draganddrop simplifies handling various MIME types.
Freeform Mode
On ChromeOS and some Android devices, applications run in freeform mode—arbitrary window sizing. android:resizeableActivity="true" plus correct onConfigurationChanged handling are prerequisites. Testing: Developer Options → Force desktop mode (on supported devices) or ChromeOS emulator.
WindowManager library (androidx.window:window:1.3.x) provides WindowInfoTracker with Flow<WindowLayoutInfo>—for foldable devices (Fold, Flip), this allows you to react to hinge state (half-opened, tabletop mode). For applications that must support Galaxy Z Fold devices, proper adaptation is impossible without this library.
Implementing full Multi-Window support with PiP, responsive UI, and testing takes 3–5 days. Cost is calculated individually after evaluating the current state of the UI code.







