Image by Gus Winkelman

Jetpack WindowManager Updates

Kenneth Ford
Android Developers
5 min readFeb 16, 2021

--

Posted by Kenneth Ford and Pietro Maggi

We are excited to announce the alpha02 release of the Jetpack WindowManager library. The Jetpack WindowManager library helps you build apps that are aware of new device features such as folds and hinges, so you can take advantage of new possibilities that didn’t exist before. As we develop this library we have taken your feedback into consideration, and we continue iterating on the API while in alpha to provide a cleaner and more complete API surface. We have also been looking at different areas in the WindowManager space where we can provide more functionality, and we are happy to announce that we are introducing WindowMetrics to allow you to use these new Android 11 APIs starting from Android 4.1 (API level 16).

We spent a lot of time reviewing your feedback after the initial release and we’ve made many changes in this release. Read on to learn more about these updates!

Creating a WindowManager

There is now a simple constructor with a single argument pointing to the context of a visual entity (like the current activity):

The original constructor is still available but it is now deprecated.

This original constructor can be used in your tests, when you want to use a custom WindowBackend to simulate a foldable device on a regular device or emulator. You can find a reference implementation in the updated sample.

While your application can still pass a null reference as WindowBackend in this version, we plan to make the WindowBackend reference a required parameter in the future, removing the deprecation, to promote it for testing purpose.

DisplayFeature added, DeviceState deprecated

Another major change is the deprecation of the DeviceState class along with the callbacks that use it to notify your applications. This deprecation was done to move towards a more generic API that allows the system to return information about all the DisplayFeature instances that are available for your app rather than defining an overall device state. We plan to remove the DeviceState class in a future release of the library.

The alpha02 release introduces a new DisplayFeature class with an updated callback contract to notify your application when a DisplayFeature changes. You can register/unregister the callback using these methods:

The WindowLayoutInfo contains a list of the instances of DisplayFeature that are located within the window.

The FoldingFeature class implements the DisplayFeature interface, which includes information about these types of features:

TYPE_FOLDTYPE_HINGE

And their possible folding states:

The possible Display Feature states: Flat, Half-opened, and Flipped respectively

Note that there is no equivalent state for the DeviceState postures POSTURE_UNKNOWN and POSTURE_CLOSED.

To access the new state you can use the FoldingFeature information returned to the registered callback:

You can find an example on how to use this information in the sample.

Better callback registration

We have also improved the robustness of the callback APIs shown above. In the previous version of the library if the application was registering a callback before the window was available this operation would throw an exception.

In Alpha02 we have changed this behavior. You can register these callbacks whenever it makes sense for your architecture; the library will send the initial WindowLayoutInfo when the window becomes available.

R8 rules

We added `keep` rules to the library R8 configuration to maintain the methods and classes that could have been stripped due to the internal module organization structure. The rules are automatically merged into the final app R8 configuration to avoid crashes seen with alpha01.

WindowMetrics

Due to the historical naming conventions and different possible window manager states, it can be difficult to get information about your current window size in Android. The deprecation of some methods in Android 11, such as Display#getSize and Display#getMetrics, along with the use of window size in the new APIs, highlights the rising trend of moving from fullscreen to multi-window and adaptive interfaces on foldable devices. To ease this transition, we added the WindowMetrics APIs in Android 11.

WindowMetrics lets you easily query information about your current window state and the maximum window size for the current state of the system, all before the first layout pass. For example, a device like the Surface Duo has a default configuration where apps launch on one screen but can be expanded to span both screens as well as through the hinge. In the default state, `getMaximumWindowMetrics` reports the bounds of the screen the app is on. When the app moves to the spanned state, The API returns the bounds reflecting the new state. Providing this as early as during onCreate, it provides information your activities might need to perform calculations or make decisions early enough so you can choose the right layouts the first time.

The API results don’t include information about the system insets such as the status bar or navigation bar, since those values aren’t available before the first layout pass for all versions of Android that we support. This blog post by Chris Banes is a great resource on using ViewCompat to get information on system insets when they are available. These bounds also don’t react to any changes in layout params that might occur when your layout is inflated.

To access these APIs, you need to get an instance of the WindowManager object as we showed earlier.

From here you now have access to the WindowMetrics APIs and can easily access the information for both the current window size as well as the maximum.

An example of where this information could be used to make layout choices before inflation is if your app has drastically different layouts or navigation patterns for phones versus tablets. You may want to choose parts of those to be constant regardless of the current window size, if you think your users may be confused by a jarring change. You can use the maximum window metrics here before you are choosing which layout to inflate.

While the Android 11 platform API’s include an API to get insets during onCreate, we haven’t brought this to the Jetpack WindowManager library as we’d like to understand what developers would find useful in this space. Please let us know if there are values you’d like to have before the first layout pass, or abstractions that would make programming layout easier.

We hope that having these APIs available to you for older versions of Android allows you all to build apps that respond to window size changes and helps you migrate away from some of the deprecated APIs mentioned above.

Keep in touch

We would love your feedback on these APIs, especially on anything that you feel is missing or would make your life as a developer easier. We know there are some use-cases that we may not have thought about so please file bugs or feature requests on the public tracker.

--

--