Overlaying the System/Navigation Bar17 Mar 2015 | by cygery
First off, the method described in this post only works on Android versions up to 4.3. The behavior which allowed this was changed in Android 4.4. Still, at time of writing, nearly 50% of all Android devices run Android 4.0-4.3. Thus, especially devices which likely won’t receive a system update can benefit from apps using the method described here.
The System/Navigation Bar
Android 3.0 introduced the system bar. This bar, usually located at the screen bottom, provides navigation controls as so-called software buttons, replacing hardware buttons. Additionally, it holds elements from the status bar, e.g., a clock and access to the notification area.
Starting with Android 4.0, the system bar is replaced by the navigation bar which doesn’t provide functionality of the status bar anymore. Instead, it mainly holds the home, back, and recents buttons. Additionally, a legacy menu button is shown when necessary. Starting with Android 5.0, the navigation bar also provides a button for keyboard/language switching.
Android uses a variety of different Window types (listed in the WindowManager.LayoutParams class) for different purposes. For example, there exist types for normal application Windows, input methods, the keyguard dialog, or the status bar.
Some Window types can be used freely by any app, e.g., normal application Windows. Others require the SYSTEM_ALERT_WINDOW permission, e.g., system alert Windows or system error Windows. Finally, there exist purely internal Window types, e.g., for the navigation bar.
Windows can be added via the WindowManager:
Similarly, a Window can be removed:
There exist a lot of available Window flags, cf. WindowManager.LayoutParams. Some of them control if the Window is (not) focusable or touchable, others when the Window is shown, e.g., FLAG_SECURE and FLAG_SHOW_WHEN_LOCKED, yet others control where the Window is shown or laid out.
In the following two sections, such a flag will be used to put a Window on top of the navigation bar.
Overlaying the Navigation Bar
Generally, overlaying the navigation bar was considered impossible, e.g., in an answer to this question on StackOverflow. However, it is possible (prior to Android 4.4):
Windows a z-ordered depending on their type via the internal windowTypeToLayerLw method. As shown in this method, there exists a single Window type which is laid out on top of the navigation bar type and is available to user apps: TYPE_SYSTEM_ERROR.
A Small Remaining Issue
By default, Windows can’t be laid out anywhere on the screen because the boundaries for screen content exclude the navigation bar. However, via the FLAG_LAYOUT_NO_LIMITS flag it is possible to allow Windows to extend beyond these boundaries.
When this flag is set, a Window can be easily placed on top of the navigation bar, e.g., by setting the Window parameters
Gravity.BOTTOM | Gravity.LEFT and the
y coordinate to the negative navigation bar height.
In Android 4.4 this behavior was changed. Effectively, this change disables FLAG_LAYOUT_NO_LIMITS for TYPE_SYSTEM_ERROR Windows. This makes it impossible for user apps to place a Window over the shown navigation bar anymore.
Yes, “behavior”. I’d call it a bug, but here’s the background:
Shortly after I discovered the issue I contacted the Android Security Team mid-2013 since I considered it to be a security-related bug, making Denial-of-Service attacks possible by user apps blocking the navigation bar. In a reply a few weeks later, they don’t consider it a security vulnerability because the SYSTEM_ALERT_WINDOW permission “gates the behavior”. Also, they gave me a heads-up (thanks!) that “this behavior may change in a future release” - as it did in Android 4.4 that year.