Building apps for foldables

Android 10 (API level 29) adds more support for foldable devices and different folding patterns.

Unfolding the device to provide a larger screen can have a positive impact on users:

  • A larger screen usually means a more immersive experience.
  • With multi-windows the user can perform multiple tasks at the same time.

Folding and unfolding can change the screen size, density, or ratio. This is not a new problem in Android development. It already happens in these non-folding cases:

  • Phones: switching between portrait and landscape mode.
  • Chrome OS running in desktop mode: resizing Android apps.
  • Devices with multiple or additional screens.

This page describes best practices to make sure your app works well with foldable form factors.

You may also want to read the Android 10 summary of changes that involve foldable support.

App continuity

When running on a foldable device, an app can transition from one screen to another automatically. To provide a great user experience, it is very important that the current task continue seamlessly after the transition. The app should resume in the same state and location. Note that foldable devices can fold in many ways, such as in or out:

Since the system will trigger a configuration change during the transition, an app should save the UI state and support configuration changes gracefully.

Make your app resizable

You should ensure that your app works in multi-window mode and with dynamic resizing. Do this by setting resizeableActivity=true. This provides maximum compatibility with whatever form factors and environments your app might encounter (like foldables, desktop mode, or freeform windows). Test your app's behavior in split-screen or with a Foldable emulator.

If your app sets resizeableActivity=false, this tells the platform it doesn't support multi-window. The system may still resize your app or put it in multi- window mode, but compatibility is implemented by applying the same configuration to all the components in the app (including all of its Activities, Services, and more). In some cases, major changes (like a display size change) might restart the process rather than change the configuration.

For example, the activity below has set resizableActivity=false along with a maxAspectRatio. When the device is unfolded, the activity configuration, size, and aspect ratio are maintained by putting the app in compatibility mode.

If you set resizeableActivity=false to disable multi-window mode but still want to support app continuity, add the following meta-data to the manifest of your element:

    android:name="android.supports_size_changes" android:value="true" />

If the value is true and the user attempts to fold or unfold a device, the activity will apply any changed configurations in a way that supports changes in window sizes.

If you do not set resizeableActivity, or set it to true, the system assumes the app fully supports multi-window and is resizable.

Note that some OEMs might implement a feature that adds a small restart icon on the screen each time the activity's display area changes. This gives the user the chance to restart the activity in the new configuration.

New screen ratios

Android 10 (API level 29) and higher supports a wider range of aspect ratios. With Foldables, form factors can vary from super high long and thin screens (such as 21:9 for a folded device) all the way down to 1:1.

To be compatible with as many devices as possible, you should test your apps for as many of these screen ratios as you can:

If you cannot support some of those ratios, you can use the maxAspectRatio (as before), as well as minAspectRatio to indicate the highest and lowest ratios your app can handle. In cases with screens that exceed these limits, your app might be put in compatibility mode.

When there are five icons in the bottom navigation view devices running Android 10 (API level 29) and higher are guaranteed a minimum touch target size of 2 inches. See the Compatibility Definition Document.


Being able to run multiple windows is one of the benefits of large screens. In the past, having two apps side by side was common in some devices. The technology has improved to the point where three or more apps can run on the screen at the same time, and also share content between themselves:

If an app doesn't properly support multi-window, it can set resizeableActivity=false. For more information, read the Multi-Window guide.

With multi-window becoming more common, consider supporting drag and drop in your app.


When running on Android 9.0 and earlier, only the app in focus is in the resumed state. Any other visible Activities are paused. This can create problems if apps close resources or stop playing content when they pause.

In Android 10, this behavior changed so that all Activities remain in the resumed state when the device is in multi-window mode. This is called multi-resume. Note that an activity can be paused if there’s a transparent activity on top, or the Activity is not focusable (e.g. picture-in-picture mode). It’s also possible that no activities have focus at a given time, for example, if the Notification drawer is opened. OnStop keeps working as usual. It will be called any time the activity is taken off the screen.

Multi-resume is also available on select devices running Android 9.0. To opt-in to multi-resume on those devices, you can add the following manifest meta-data:

    android:name="android.allow_multiple_resumed_activities" android:value="true" />

To verify that a given device supports this manifest meta-data, refer to the device specifications.

Exclusive resources access

To help support the multi-resume feature, there’s a new lifecycle callback, Activity#onTopResumedActivityChanged().

This method is invoked when an activity gains or loses the top resumed Activity position. This is important to know when an activity uses a shared single-user resource, such as the microphone or camera.

override fun onTopResumedActivityChanged(topResumed: Boolean) {
    if (topResumed) {
        // Top resumed activity
        // Can be a signal to re-acquire exclusive resources
    } else {
        // No longer the top resumed activity

Note that an app can lose resources for several other reasons, such as removing a shared piece of hardware.

In any case, an app should gracefully handle resource loss events and state changes that affect available resources.

For apps that use a camera it’s recommended to use the method CameraManager.AvailabilityCallback#onCameraAccessPrioritiesChanged() as a hint that it might be a good time to try to get access to the camera. This method is available in Android 10 (API level 29) and higher.

Remember that resizeableActivity=false is not a guarantee of exclusive camera access, since other camera-using apps can be opened on other displays.

Camera in multi-window mode.

Your app does not necessary have to release the camera when it loses focus. For example, you might want to continue camera preview while the user interacts with the newly focused topmost resumed app. It's fine for your app to keep running the camera when it’s not the topmost resumed app but it has to handle the disconnect case properly. When the topmost resumed app wants to use the camera it can open it, and your app will lose access. Your app can re-open the camera when it gets the focus back.

After an app receives a CameraDevice.StateCallback#onDisconnected() callback, subsequent calls on the camera device will throw a CameraAccessException.


In the future, you might see foldable phones that support more than one screen or display at a time. Handling this configuration is similar to how developers work with projected screens today on Chrome OS.

Android 10 (API level 29) and higher supports activities on secondary displays. If an activity is running on a device with multiple displays, users can move the activity from one display to another. Multi-resume applies to multi-screen scenarios as well. Several activities can receive user input at the same time.

An app can specify which display it should run on when it launches, or when it creates another activity. This behavior depends on the activity launch mode defined in the manifest file, and in the intent flags and options set by the entity launching the activity. See ActivityOptions for more details.

As with folding transitions, when an activity moves to a secondary display, it can go through a context update, window resize, and configuration and resource changes. If the activity handles the configuration change, it will be notified in onConfigurationChanged(). If not, it will be relaunched.

An activity should check the current display in onCreate and onConfigurationChanged if handled. Make sure to update the resources and layouts when the display changes.

If the selected launch mode for an activity allows multiple instances, remember that launching on a secondary screen can create a new instance of the activity. Both activities will be resumed at the same time.

Multiple instances of an Activity in multiple displays.

You may also want to read about the existing multi-display APIs that were introduced in Android 8.0.

Display cutouts

Foldable devices might have different cutout geometry when folded and unfolded. To avoid cutout issues read Best practices for display cutout.

Activity vs application context

Using the right context is crucial in multi-display. When accessing resources, the activity context (which is displayed) is different from the application context (which is not).

The activity context contains information about the display and is always adjusted for the display area on which it appears. This allows you to get the correct information about the density or window metrics your app currently has. You should always be using the activity context (or another UI-based context) to get information about the current window or display. This also affects some system APIs that use information from the context (like Toast).

The activity window configuration and parent display define resources and context. To get the current display use:

val activityDisplay = activity.display

To get the current activity window metrics use:

val windowMetrics = activity.windowManager.getCurrentWindowMetrics()

To get the maximum window metrics for the current system configuration use:

val maximumWindowMetrics = activity.windowManager.getMaximumWindowMetrics()

The maximum window metrics is great information for making calculations, layout choices, or determining the size of resources to fetch ahead of time. Having this available in onCreate() allows you to make these decisions before the first layout pass. These should not be used for laying out specific layout elements and instead should use information from the Configuration object.

Using secondary screens

You can get the available displays from the DisplayManager system service:

val dm = getSystemService(Context.DISPLAY_SERVICE) as DisplayManager
val displays = dm.displays

Use the Display class to get information about a particular display, such as checking the flags to see if a display is secure.

However, do not assume that the display size is going to be the constant size your application will be placed in. Remember that in multi-window mode, your application will be on a subset of the display.

To determine if an activity can launch on a display:

activityManager.isActivityStartAllowedOnDisplay(context, displayId, intent)

And to launch an activity on a display:

val options = ActivityOptions.makeBasic()
options.launchDisplayId = targetDisplay.displayId
startActivity(intent, options.toBundle())

Multi-display support

Android already supports Software keyboards, Wallpapers, and Launchers.

Software keyboard

A keyboard can be shown on a secondary screen if the display is configured to support system decorations. The input method editor will automatically show up if a text field requests input on that display.

Keyboard on a secondary display.


In Android 10 (API level 29) and higher, secondary screens can have wallpaper. The framework creates a separate instance of WallpaperService.Engine for each display. Make sure the surface of each engine is drawn independently. Developers can load assets using the display context in WallpaperService.Engine#getDisplayContext(). Also, make sure your WallpaperInfo.xml file sets android:supportsMultipleDisplays="true".

Wallpapers on phone and secondary display.


There is a new intent filter category SECONDARY_HOME to provide a dedicated activity for secondary screens. Instances of this activity are used on all displays that support system decorations, one per each display.

        <category android:name="android.intent.category.SECONDARY_HOME" />

The activity must have a launch mode that does not prevent multiple instances and can adapt to different screen sizes. The launch mode cannot be singleInstance or singleTask.

As example, the AOSP implementation of Launcher3 supports a SECONDARY_HOME activity.

Material Design Launcher on phone.

Material Design Launcher on a secondary display.

Foldable Modes

Foldable devices have either a fold in the display or a hinge of some width that separates two displays. Devices with a hinge might have the ability to span content behind the hinge such as the Microsoft Surface Duo in its spanned mode. Some devices may be able to be placed in a half-folded configuration, or other postures such as Samsung's Flex Mode.

The Jetpack Window Manager library gives you as the developer a device-agnostic way of reacting to these modes and other device configuration changes as well as display features on the device. Read the blog post to learn more about using the library.


A foldable device can support some or all of the postures shown below, which correspond to the FoldingFeature state constants. Currently we have support for a FoldingFeature that represents both devices that have a hinge as well devices with a fold. We have built in the ability to add more DisplayFeatures as the device ecosystem continues to grow.

half-opened (laptop)
Half-opened (Laptop/Tabletop)

Apps can use the Jetpack Window Manager library to retrieve the postures in your app window(s). You can check directly for these two states:

or you can use a few convenience methods that abstracts the type and the state of a folding device:

This can be used to recognize different postures like Laptop/Tabletop or Book mode, where the hinge is vertical:

private fun isTableTopPosture(foldFeature: FoldingFeature) =
        foldFeature.isSeparating &&
        foldFeature.orientation == FoldingFeature.ORIENTATION_HORIZONTAL

private fun isBookPosture(foldFeature: FoldingFeature) =
        foldFeature.isSeparating &&
        foldFeature.orientation == FoldingFeature.ORIENTATION_VERTICAL

You can be notified of any changes in the FoldingFeatures state by registering a callback with the registerLayoutChangeCallback method. To stop receiving updates, you can unsubscribe the callback using unregisterLayoutChangeCallback.

This callback is going to receive the information in a WindowLayoutInfo object that contains the list of DisplayFeatures located within the window. To access the data returned you can use the getDisplayFeatures as shown:

class LayoutStateChangeCallback : Consumer<WindowLayoutInfo> {
    override fun accept(newLayoutInfo: WindowLayoutInfo) {
        // Check newLayoutInfo. getDisplayFeatures()
        // to see if it is a FoldingFeature and retrieve the information

Hinge angle

Starting with Android 11, apps running on devices with hinge-based screen configurations can determine the angle of the hinge if the device has a sensor with the type TYPE_HINGE_ANGLE and reports a SensorEvent which monitors the hinge angle and provides a measurement in degrees between two integral parts of the device. You can use these raw measurements to perform granular animations as the user manipulates the device.

Even though some kinds of apps (such as launchers and wallpapers) may find it useful to know the exact hinge angle, most apps should use the Window Manager Jetpack Library to retrieve the posture.

Responding to the device posture is safer and more reliable, due to the many different window and device configurations currently in the market and coming in the future.


To get your app ready for Foldables, you should test how your app reacts to:

  • Configuration changes
  • Multi-window and multi-resume
  • Resizing and new screen ratios

Foldable emulators

The AOSP emulator supports folding devices. This allows developers to test their apps in folding scenarios.

7.3’’ foldable emulator

7.3" Display Resolution Logical Display
Size X Y densityDpi Size
Unfolded 7.3 1536 2152 420 large
Folded 4.6 840 1960 420 normal

8’’ foldable emulator

8" Display Resolution Logical Display
Size X Y densityDpi Size
Unfolded 8.03 2200 2480 420 large
Folded 6.62 1148 2480 420 normal

AOSP folding emulator.

Multiple foldable emulators are available in Android Studio 3.5:

Android Studio 3.5 foldable emulators.

Testing multi-display

The new Dev Option called Force desktop mode lets the developer turn on system decoration support on all secondary displays and displays a mouse pointer there instead of on the default display. When used with Enable Freeform windows, Force desktop simulates a desktop experience with multi-window and the ability to resize windows.

On Pixel you can try it using Simulated display. Or, if you have a device that supports HDMI or displayport-over-USB-C, you can test it using a wired connection.

Simulated display.