Building apps for Foldables

Android Q 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 Q preview 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 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 Q 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 the new Android Q 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 Q 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 Q, this behavior is changing 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 new Android Q method CameraManager.AvailabilityCallback#onCameraAccessPrioritiesChanged() as a hint that it might be a good time to try to get access to the camera.

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 Q 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 Q, 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.

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.