Illustration by Ocupop

Unbundling the stable WindowManager

Pietro Maggi
Android Developers

--

Jetpack WindowManager 1.0.0 is stable!

To support developers building applications for foldable devices we launched our first alpha release of Jetpack WindowManager in February 2019. Since then, the library has evolved to include WindowMetrics information and experimental support for activity embedding.

This is just the start! We have great plans for this library as the foundation for amazing experiences on all types of large screen devices.

Stable support for foldable devices

To support foldable devices, Jetpack WindowManager provides the DisplayFeature interface and its FoldingFeature implementation which provides information like the hinge’s orientation and state:

Sample state for FoldingFeature instances

An application can register to receive updated status information through a WindowInfoLayout object. This can be collected in different ways depending on the application’s architecture:

  • Kotlin’s coroutine Flow
  • Callbacks
  • RxJava Observable or Flowable

Library artifacts

The base library is built with Kotlin and provides out-of-the-box support for Kotlin’s coroutine Flow using a WindowInfoTracker associated with the current activity:

Sample collection of WindowInfoLayout events

For a step by step guide on how to set up the right dependencies for Jetpack WindowManager you can take a look at the Support foldable and dual-screen devices with Jetpack WindowManager codelab.

As an alternative, WindowInfoTrackerCallbackAdapter can be used if you need to use the library from a Java-based project. In this case, WindowInfoLayout events are received through a callback:

Setup WindowLayoutInfo collection through callbacks — onCreate

We can then use the lifecycle callbacks onStart and onStop to register our WindowLayoutInfo listener:

Setup WindowLayoutInfo collection through callbacks — onStart and onStop

A sample implementation of the callback can be an inner class implementing the Consumer<WindowLayoutInfo> interface:

Setup WindowLayoutInfo collection through callbacks

The article Make your app fold aware covers how you can use these APIs. Once you’ve added support for foldable devices, you can test your UI using the androidx.window.testing artifact as described in the article Test your app on foldables.

Support for responsive UIs

Since screen size can vary so frequently on Android, it’s important to start designing fully responsive and adaptive UIs. Another feature included in the WindowManager library is the ability to retrieve the current and maximum window metrics information. This is similar to the information provided by the framework WindowMetrics API included in API level 30, but it is backward compatible down to API level 14.

Jetpack WindowManager includes the WindowMetricsCalculator class to retrieve this information:

WindowMetricsCalculator — current and maximum

Note: If you used the library in the past (up to beta02), you may have used the WindowMetrics flow to collect window size changes events. We have removed this API because we encountered some reliability issues. We will revisit this decision in the future.

If your application needs to monitor the window size for all changes, the best approach is to use a View.onConfigurationChanged listener. We can’t use Activity.onConfigurationChanged, since there are situations where that won’t be called when the configuration changes.

You can also add a utility view to the container and attach to it this listener in your Activity.onCreate method:

WindowMetrics — View.onConfigurationChanged workaround

Note: Even if your activity doesn’t handle configuration changes, if you are interested in having the correct window dimensions, we recommend registering a View.onConfigurationChanged listener as there are situations where the window size can change without your activity restarting.

Jetpack WindowManager as a foundation for responsive UIs

Jetpack WindowManager can be integrated directly in your application, but it is also great as a building block for higher level components and libraries.

In Jetpack, we already have three libraries that include WindowManager, and with today’s first stable release, we are releasing the stable version for all of them:

As a refresher, the SlidingPaneLayout component supports showing two panes side by side on larger devices and foldables, while automatically adapting to show only one pane at a time on smaller devices such as phones.

SlidingPaneLayout sample

Support for activity-based applications

During last year, we collected a lot of feedback from developers about the challenges in adapting existing applications for large screen devices, with the biggest concerns coming from developers working on codebases still heavily relying on multiple activities. In this case, adopting a solution that works with fragments (like SlidingPaneLayout), or migrating to Compose, can require a lot of work.

For this reason, we investigated the possibility of having two activities side by side on the screen. This study culminated in a new feature provided with the 12L feature drop for Android 12, exposed through a new Jetpack WindowManager experimental API that allows developers to show two activities on the screen side by side.

The main requirement in this case is a new XML configuration that — in the simplest case — specifies a primary and a secondary activity to put together on the screen if the window size is big enough:

Split configuration

The minimum width of 600dp is Material Design’s recommended value to ensure that there is enough space for both activities across common device sizes.

The other required step is to initialize Jetpack WindowManager’s SplitController.

For this we can use Jetpack Startup to perform initialization before other components of the app load and activities start.

To enable initialization, do the following:

  1. Add the library dependency
Activity embedding — dependencies

2. Inform the library about our initializer in the AndroidManifest.xml

Activity embedding — Initialization provider

3. Implement the SplitController initializer

Activity embedding — SplitController initialization

You can take a look at the Activity embedding guide for all the available features.

Activity embedding is an Android 12L (API level 32) feature, but it will be available on some devices with earlier platform versions. To check at runtime for the availability of the feature, use the SplitController.isSplitSupported() method:

Check for activity embedding availability

See it in action: code sample

An up-to-date sample on GitHub shows how to use the Jetpack WindowManager library to:

  • Retrieve display posture information
  • Collect information from the WindowLayoutInfo flow
  • Register a callback through the WindowInfoTrackerCallbackAdapter
  • Experiment with the activity embedding API

The sample also includes a few tests that can be run on any device or emulator.

Adopt WindowManager in your app

Jetpack WindowManager is now stable, and we have a great road map for what to build next, including evolving the activity embedding API based on your feedback, adding the window size classes API to standardize responsive UIs breakpoints, and more.

We are also thrilled to see the Android community adopting Jetpack WindowManager as the foundation for other libraries like Microsoft’s WindowState or Stream’s Butterfly.

But now it’s your turn to build amazing fold-aware, responsive Android applications!

Visit Responsive layouts for large screen development to learn more about optimizing for foldables and other large screen devices.

--

--