Behavior changes: apps targeting API level 28+

Android 9 (API level 28) introduces a number of changes to the Android system. The following behavior changes apply exclusively to apps that are targeting API level 28 or higher. Apps that set targetSdkVersion to API level 28 or higher must modify their apps to support these behaviors properly, where applicable to the app.

For changes that affect all apps running on Android 9, regardless of which API level they target, see Behavior changes: all apps.

Foreground services

Apps that target Android 9 or higher and use foreground services must request the FOREGROUND_SERVICE permission. This is a normal permission, so the system automatically grants it to the requesting app.

If an app that targets Android 9 or higher attempts to create a foreground service without requesting FOREGROUND_SERVICE, the system throws a SecurityException.

Privacy changes

If your app targets Android 9, you should keep the following behavior changes in mind. These updates to device serial and DNS information enhance user privacy.

Build serial number deprecation

In Android 9, Build.SERIAL is always set to "UNKNOWN" to protect users' privacy.

If your app needs to access a device's hardware serial number, you should instead request the READ_PHONE_STATE permission, then call getSerial().

DNS privacy

Apps targeting Android 9 should honor the private DNS APIs. In particular, apps should ensure that, if the system resolver is doing DNS-over-TLS, any built-in DNS client either uses encrypted DNS to the same hostname as the system, or is disabled in favor of the system resolver.

Framework security changes

Android 9 includes several behavior changes that improve your app's security, but these changes take effect only if your app targets API level 28 or higher.

Network TLS enabled by default

If your app targets Android 9 or higher, the isCleartextTrafficPermitted() method returns false by default. If your app needs to enable cleartext for specific domains, you must explicitly set cleartextTrafficPermitted to true for those domains in your app's Network Security Configuration.

Web-based data directories separated by process

In order to improve app stability and data integrity in Android 9, apps cannot share a single WebView data directory among multiple processes. Typically, such data directories store cookies, HTTP caches, and other persistent and temporary storage related to web browsing.

In most cases, your app should use classes from the android.webkit package, such as WebView and CookieManager, in only one process. For example, you should move all Activity objects that use a WebView into the same process. You can more strictly enforce the "one process only" rule by calling disableWebView() in your app's other processes. This call prevents WebView from being initialized in those other processes by mistake, even if it's being called from a dependent library.

If your app must use instances of WebView in more than one process, you must assign a unique data directory suffix for each process, using the WebView.setDataDirectorySuffix() method, before using a given instance of WebView in that process. This method places web data from each process in its own directory within your app's data directory.

Per-app SELinux domains

Apps that target Android 9 or higher cannot share data with other apps using world-accessible Unix permissions. This change improves the integrity of the Android Application Sandbox, particularly the requirement that an app's private data is accessible only by that app.

To share files with other apps, use a content provider.

Connectivity changes

Connectivity data counting and multipath

Within apps that target Android 9 or higher, the system counts network traffic on networks that aren't the current default—such as cell traffic while the device is on Wi-Fi—and provides methods in the NetworkStatsManager class to query for that traffic.

In particular, getMultipathPreference() now returns a value based on the aforementioned network traffic. Beginning with Android 9, the method returns true for cell data, but when more than a certain amount of traffic accumulates in a day, it starts returning false. Apps running on Android 9 must call the method and honor this hint.

The ConnectivityManager.NetworkCallback class now sends information about VPNs to apps. This change makes it much easier for apps to listen for connectivity events without having to mix synchronous and asynchronous calls and using limited APIs. Additionally, it means that information transfer works as expected when a device is connected to multiple Wi-Fi networks or multiple cell networks simultaneously.

Apache HTTP client deprecation

With Android 6.0, we removed support for the Apache HTTP client. Beginning with Android 9, that library is removed from the bootclasspath and is not available to apps by default.

To continue using the Apache HTTP client, apps that target Android 9 and above can add the following to their AndroidManifest.xml:

<uses-library android:name="org.apache.http.legacy" android:required="false"/>

As an alternative to using the runtime Apache library, apps can bundle their own version of the org.apache.http library in their APK. If you do this, you must repackage the library (with a utility like Jar Jar) to avoid class compatibility issues with the classes provided in the runtime.

UI changes

View focus

Views with 0 area (either a width or a height is 0) are no longer focusable.

Additionally, activities no longer implicitly assign initial focus in touch-mode. Instead, it is up to you to explicitly request initial focus, if desired.

CSS RGBA hex value handling

Apps that target Android 9 or higher must enable the draft CSS Color Module Level 4 behaviour for handling 4 and 8 hex digit CSS colors.

CSS Color Module Level 4 has been supported by Chrome since release 52, but WebView currently disables the feature because existing Android applications were found to contain 32 bit hex colors in the Android ordering (ARGB), which would cause rendering errors.

For example, the color #80ff8080 is currently rendered in WebView as opaque light red (#ff8080) for apps targeting API levels 27 or lower. The leading component (which would be interpreted by Android as the alpha component) is currently ignored. If an app targets API level 28 or higher, #80ff8080 is interpreted as 50% transparent light green (#80ff80).

MIME type sniffing for file: URIs

Android versions earlier than Android 9 could infer MIME types from the file contents. Starting with Android 9 (API level 28) apps must use the correct file extension when loading file: URIs in a WebView.

Using the file contents to infer MIME types can be a source of security bugs, and this is not generally permitted by modern browsers.

If a file has a recognized file extension such as .html, .txt, .js, or .css the MIME type will be determined by the extension. If a file has no extension or an unrecognized one, the MIME type will be plain text.

For example, a URI like file:///sdcard/test.html will be rendered as HTML, but a URI like file:///sdcard/test will render as plain text, even if the file contains HTML data.

Document scrolling element

Android 9 properly handles the case where a document's root element is the scrolling element. On earlier versions, scrolling position was set on the body element, and the root element had zero scroll values. Android 9 enables the standards-compliant behaviour where the scrolling element is the root element.

Furthermore, directly accessing document.body.scrollTop, document.body.scrollLeft, document.documentElement.scrollTop or document.documentElement.scrollLeft will behave differently depending on target SDK. To access viewport scroll values, use document.scrollingElement, if available.

Notifications from suspended apps

Prior to Android 9, notifications from suspended apps were canceled. Beginning with Android 9, notifications from suspended apps are hidden until the app is resumed.

Content and code samples on this page are subject to the licenses described in the Content License. Java and OpenJDK are trademarks or registered trademarks of Oracle and/or its affiliates.

Last updated 2021-03-11 UTC.