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](https://developer.android.com/about/versions/pie/android-9.0-changes-all).

## Foreground services

Apps that target Android 9 or higher and use foreground services must request
the [`FOREGROUND_SERVICE`](https://developer.android.com/reference/android/Manifest.permission#FOREGROUND_SERVICE)
permission. This is a [normal permission](https://developer.android.com/guide/topics/permissions/normal-permissions),
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`](https://developer.android.com/reference/android/Manifest.permission#FOREGROUND_SERVICE),
the system throws a [`SecurityException`](https://developer.android.com/reference/java/lang/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`](https://developer.android.com/reference/android/os/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`](https://developer.android.com/reference/android/Manifest.permission#READ_PHONE_STATE)
permission, then call
[`getSerial()`](https://developer.android.com/reference/android/os/Build#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()`](https://developer.android.com/reference/android/security/NetworkSecurityPolicy#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](https://developer.android.com/training/articles/security-config).

#### 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`](https://developer.android.com/reference/android/webkit/WebView) data
directory among
[multiple processes](https://developer.android.com/guide/components/processes-and-threads). 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`](https://developer.android.com/reference/android/webkit/package-summary) package, such
as [`WebView`](https://developer.android.com/reference/android/webkit/WebView) and
[`CookieManager`](https://developer.android.com/reference/android/webkit/CookieManager), in only one
process. For example, you should move all
[`Activity`](https://developer.android.com/reference/android/app/Activity) objects that use a `WebView`
into the same process. You can more strictly enforce the "one process only" rule
by calling
[`disableWebView()`](https://developer.android.com/reference/android/webkit/WebView#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`](https://developer.android.com/reference/android/webkit/WebView) in more than one process,
you must assign a unique data directory suffix for each process, using the
[`WebView.setDataDirectorySuffix()`](https://developer.android.com/reference/android/webkit/WebView#setDataDirectorySuffix(java.lang.String))
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.
| **Note:** Even if you use `setDataDirectorySuffix()`, the system doesn't share cookies and other web data across your app's process boundaries. If multiple processes in your app need access to the same web data, you need to copy it between those processes yourself. For example, you can call [`getCookie()`](https://developer.android.com/reference/android/webkit/CookieManager#getCookie(java.lang.String)) and [`setCookie()`](https://developer.android.com/reference/android/webkit/CookieManager#setCookie(java.lang.String,%20java.lang.String,%20android.webkit.ValueCallback%3Cjava.lang.Boolean%3E)) to manually transfer cookie data from one process to another.

#### 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](https://source.android.com/security/overview/kernel-security#the-application-sandbox),
particularly the requirement that an app's
[private data](https://developer.android.com/guide/topics/data/data-storage#filesInternal) is accessible
only by that app.

To share files with other apps, use a [content
provider](https://developer.android.com/guide/topics/providers/content-provider-basics).

## 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`](https://developer.android.com/reference/android/app/usage/NetworkStatsManager)
class to query for that traffic.

In particular,
[`getMultipathPreference()`](https://developer.android.com/reference/android/net/ConnectivityManager#getMultipathPreference(android.net.Network))
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`](https://developer.android.com/reference/android/net/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](https://developer.android.com/about/versions/marshmallow/android-6.0-changes#behavior-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"/>

| **Note:** The `android:required="false"` attribute is required for apps that have a minimum SDK of 23 or lower, because on devices with API levels lower than 24, the `org.apache.http.legacy` library is not available. (On those devices, the Apache HTTP classes are available on the bootclasspath.)

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](https://github.com/shevek/jarjar)) 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](https://drafts.csswg.org/css-color/#hex-color)
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](https://developer.android.com/reference/android/webkit/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](https://developer.android.com/reference/android/webkit/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](https://developer.android.com/reference/android/webkit/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.