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
<meta-data
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.
Multi-window
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.
Multi-resume
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:
<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.
protected void onTopResumedActivityChanged(boolean topResumed) {
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
.
Multi-display
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. To get the current display metrics and resources use the activity context. 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.windowManager.defaultDisplay
To get the current activity window metrics use:
val windowMetrics = DisplayMetrics()
activityDisplay.getMetrics(windowMetrics)
or:
val windowMetrics = activity.resources.displayMetrics
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:
- Display metrics give you information about the size, resolution and density of the screen.
- Check the flags to see if a display is secure.
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.
Wallpaper
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.
Launchers
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.
<activity>
...
<intent-filter>
<category android:name="android.intent.category.SECONDARY_HOME" />
...
</intent-filter>
</activity>
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.
Postures
Foldable devices can support some or all of the postures shown below, which correspond to the DeviceState posture constants.
![]() |
![]() |
![]() |
![]() |
Apps can use the Jetpack
Window Manager
library to retrieve the
device posture by calling
DeviceStage.getPosture()
.
Alternatively, your app can call registerDeviceStateChangeCallback()
to be informed when the DeviceState
changes and react when the posture changes.
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.
Testing
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.