Along with new features and capabilities, Android 8.0 (API level 26) includes a variety of system and API behavior changes. This document highlights some of the key changes that you should understand and account for in your apps.

Most of these changes affect all apps, regardless of what version of Android they target. However, several changes only affect apps targeting Android 8.0. To maximize clarity, this page is divided into two sections:[Changes for all apps](https://developer.android.com/about/versions/oreo/android-8.0-changes#atap)and[Changes for apps targeting Android 8.0](https://developer.android.com/about/versions/oreo/android-8.0-changes#o-apps).

## Changes for all apps

These behavior changes apply toall appswhen they run on the Android 8.0 (API level 26) platform, regardless of the API level that they target. All developers should review these changes and modify their apps to support them properly, where applicable to the app.

### Background execution limits

As one of the changes that Android 8.0 (API level 26) introduces to improve battery life, when your app enters the[cached](https://developer.android.com/guide/topics/processes/process-lifecycle)state, with no active[components](https://developer.android.com/guide/components/fundamentals#Components), the system releases any wakelocks that the app holds.

In addition, to improve device performance, the system limits certain behaviors by apps that are not running in the foreground. Specifically:

- Apps that are running in the background now have limits on how freely they can access background services.
- Apps cannot use their manifests to register for most implicit broadcasts (that is, broadcasts that are not targeted specifically at the app).

By default, these restrictions only apply to apps that target O. However, users can enable these restrictions for any app from the**Settings**screen, even if the app has not targeted O.

Android 8.0 (API level 26) also includes the following changes to specific methods:

- The[startService()](https://developer.android.com/reference/android/content/Context#startService(android.content.Intent))method now throws an[IllegalStateException](https://developer.android.com/reference/java/lang/IllegalStateException)if an app targeting Android 8.0 tries to use that method in a situation when it isn't permitted to create background services.
- The new`Context.startForegroundService()`method starts a foreground service. The system allows apps to call`Context.startForegroundService()`even while the app is in the background. However, the app must call that service's[startForeground()](https://developer.android.com/reference/android/app/Service#startForeground(int, android.app.Notification))method within five seconds after the service is created.

For more information, see[Background Execution Limits](https://developer.android.com/about/versions/oreo/background).

### Android background location limits

In order to preserve battery, user experience, and system health, background apps receive location updates less frequently when used on a device running Android 8.0. This behavior change affects all apps that receive location updates, including Google Play services.

These changes affect the following APIs:

- Fused Location Provider (FLP)
- Geofencing
- GNSS Measurements
- Location Manager
- Wi-Fi Manager

To ensure that your app runs as expected, complete the following steps:

- Review your app's logic and ensure that you're using the latest location APIs.
- Test that your app exhibits the behavior that you expect for each use case.
- Consider using the[Fused Location Provider (FLP)](https://developers.google.com/android/reference/com/google/android/gms/location/FusedLocationProviderApi)or geofencing to handle the use cases that depend on the user's current location.

For more information about these changes, see[Background Location Limits](https://developer.android.com/about/versions/oreo/background-location-limits).

### App shortcuts

Android 8.0 (API level 26) includes the following changes to app shortcuts:

- The`com.android.launcher.action.INSTALL_SHORTCUT`broadcast no longer has any effect on your app, because it is now a private, implicit broadcast. Instead, you should create an app shortcut by using the[requestPinShortcut()](https://developer.android.com/reference/android/content/pm/ShortcutManager#requestPinShortcut(android.content.pm.ShortcutInfo, android.content.IntentSender))method from the[ShortcutManager](https://developer.android.com/reference/android/content/pm/ShortcutManager)class.
- The[ACTION_CREATE_SHORTCUT](https://developer.android.com/reference/android/content/Intent#ACTION_CREATE_SHORTCUT)intent can now create app shortcuts that you manage using the[ShortcutManager](https://developer.android.com/reference/android/content/pm/ShortcutManager)class. This intent can also create legacy launcher shortcuts that don't interact with[ShortcutManager](https://developer.android.com/reference/android/content/pm/ShortcutManager). Previously, this intent could create only legacy launcher shortcuts.
- Shortcuts created using[requestPinShortcut()](https://developer.android.com/reference/android/content/pm/ShortcutManager#requestPinShortcut(android.content.pm.ShortcutInfo, android.content.IntentSender))and shortcuts created in an activity that handles the[ACTION_CREATE_SHORTCUT](https://developer.android.com/reference/android/content/Intent#ACTION_CREATE_SHORTCUT)intent are now fully-fledged app shortcuts. As a result, apps can now update them using the methods in[ShortcutManager](https://developer.android.com/reference/android/content/pm/ShortcutManager).
- Legacy shortcuts retain their functionality from previous versions of Android, but you must convert them to app shortcuts manually in your app.

To learn more about changes to app shortcuts, see the[Pinning Shortcuts and Widgets](https://developer.android.com/guide/topics/ui/shortcuts#pinning)feature guide.

### Locales and internationalization

Android 7.0 (API level 24) introduced the concept of being able to specify a default Category Locale, but some APIs continued to use the generic[Locale.getDefault()](https://developer.android.com/reference/java/util/Locale#getDefault())method, without arguments, when they should have instead used default[DISPLAY](https://developer.android.com/reference/java/util/Locale.Category#DISPLAY)category Locale. In Android 8.0 (API level 26), the following methods now use[Locale.getDefault(Category.DISPLAY)](https://developer.android.com/reference/java/util/Locale#getDefault(java.util.Locale.Category))instead of[Locale.getDefault()](https://developer.android.com/reference/java/util/Locale#getDefault()):

- [Currency.getDisplayName()](https://developer.android.com/reference/java/util/Currency#getDisplayName())
- [Currency.getSymbol()](https://developer.android.com/reference/java/util/Currency#getSymbol())
- [Locale.getDisplayScript()](https://developer.android.com/reference/java/util/Locale#getDisplayScript())

[Locale.getDisplayScript(Locale)](https://developer.android.com/reference/java/util/Locale#getDisplayScript())also falls back to[Locale.getDefault()](https://developer.android.com/reference/java/util/Locale#getDefault())when the<var translate="no">displayScript</var>value specified for the[Locale](https://developer.android.com/reference/java/util/Locale)argument is not available.

Additional locale and internationalization-related changes are as follows:

- Calling[Currency.getDisplayName(null)](https://developer.android.com/reference/java/util/Currency#getDisplayName())throws a[NullPointerException](https://developer.android.com/reference/java/lang/NullPointerException), matching the documented behavior.
- Time zone name parsing has changed. Previously, Android devices used the system clock value sampled at boot time to cache the time zone names used for parsing date times. As a result, parsing could be negatively affected if the system clock was wrong at boot time or in other, rarer cases.Now, in common cases the parsing logic uses ICU and the current system clock value when parsing time zone names. This change provides more correct results, which may differ from earlier Android versions when your app uses classes like[SimpleDateFormat](https://developer.android.com/reference/java/text/SimpleDateFormat).

- Android 8.0 (API level 26) updates the version of ICU to version 58.

### Alert windows

If an app uses the[SYSTEM_ALERT_WINDOW](https://developer.android.com/reference/android/Manifest.permission#SYSTEM_ALERT_WINDOW)permission and uses one of the following window types to attempt to display alert windows above other apps and system windows:

- [TYPE_PHONE](https://developer.android.com/reference/android/view/WindowManager.LayoutParams#TYPE_PHONE)
- [TYPE_PRIORITY_PHONE](https://developer.android.com/reference/android/view/WindowManager.LayoutParams#TYPE_PRIORITY_PHONE)
- [TYPE_SYSTEM_ALERT](https://developer.android.com/reference/android/view/WindowManager.LayoutParams#TYPE_SYSTEM_ALERT)
- [TYPE_SYSTEM_OVERLAY](https://developer.android.com/reference/android/view/WindowManager.LayoutParams#TYPE_SYSTEM_OVERLAY)
- [TYPE_SYSTEM_ERROR](https://developer.android.com/reference/android/view/WindowManager.LayoutParams#TYPE_SYSTEM_ERROR)

...then these windows always appear beneath the windows that use the[TYPE_APPLICATION_OVERLAY](https://developer.android.com/reference/android/view/WindowManager.LayoutParams#TYPE_APPLICATION_OVERLAY)window type. If an app targets Android 8.0 (API level 26), the app uses the[TYPE_APPLICATION_OVERLAY](https://developer.android.com/reference/android/view/WindowManager.LayoutParams#TYPE_APPLICATION_OVERLAY)window type to display alert windows.

For more information, see the[Common window types for alert windows](https://developer.android.com/about/versions/oreo/android-8.0-changes#cwt)section within the behavior changes for[Apps targeting Android 8.0](https://developer.android.com/about/versions/oreo/android-8.0-changes#o-apps).

### Input and navigation

With the advent of Android apps on ChromeOS and other large form factors, such as tablets, we're seeing a resurgence of keyboard navigation use within Android apps. Within Android 8.0 (API level 26), we've re-addressed using the keyboard as a navigation input device, resulting in a more reliable, predictable model for arrow- and tab-based navigation.

In particular, we've made the following changes to element focus behavior:

- If you haven't defined any focus state colors for a[View](https://developer.android.com/reference/android/view/View)object (either its foreground or background drawable), the framework now sets a default focus highlight color for the[View](https://developer.android.com/reference/android/view/View). This focus highlight is a ripple drawable that's based on the activity's theme.

  If you don't want a[View](https://developer.android.com/reference/android/view/View)object to use this default highlight when it receives focus, set the`android:defaultFocusHighlightEnabled`attribute to`false`in the layout XML file containing the[View](https://developer.android.com/reference/android/view/View), or pass in`false`to`setDefaultFocusHighlightEnabled()`in your app's UI logic.
- To test how keyboard input affects UI element focus, you can enable the**Drawing \> Show layout bounds**developer option. In Android 8.0, this option displays an "X" icon over the element that currently has focus.

Also, all toolbar elements in Android 8.0 are automatically[keyboard navigation clusters](https://developer.android.com/about/versions/oreo/android-8.0#kbnc), making it easier for users to navigate into and out of each toolbar as a whole.

To learn more about how to improve support for keyboard navigation within your app, read the[Supporting Keyboard Navigation](https://developer.android.com/training/keyboard-input/navigation)guide.

### Web form autofill

Now that the Android[Autofill Framework](https://developer.android.com/guide/topics/text/autofill)provides built-in support for autofill functionality, the following methods related to[WebView](https://developer.android.com/reference/android/webkit/WebView)objects have changed for apps installed on devices running Android 8.0 (API level 26):

[WebSettings](https://developer.android.com/reference/android/webkit/WebSettings)
:
    - The[getSaveFormData()](https://developer.android.com/reference/android/webkit/WebSettings#getSaveFormData())method now returns`false`. Previously, this method returned`true`instead.
    - Calling[setSaveFormData()](https://developer.android.com/reference/android/webkit/WebSettings#setSaveFormData(boolean))no longer has any effect.

[WebViewDatabase](https://developer.android.com/reference/android/webkit/WebViewDatabase)
:
    - Calling[clearFormData()](https://developer.android.com/reference/android/webkit/WebViewDatabase#clearFormData())no longer has any effect.
    - The[hasFormData()](https://developer.android.com/reference/android/webkit/WebViewDatabase#hasFormData())method now returns`false`. Previously, this method returned`true`when the form contained data.

### Accessibility

Android 8.0 (API level 26) includes the following changes to accessibility:

- The accessibility framework now converts all double-tap gestures into[ACTION_CLICK](https://developer.android.com/reference/android/view/accessibility/AccessibilityNodeInfo.AccessibilityAction#ACTION_CLICK)actions. This change allows TalkBack to behave more like other accessibility services.

  If your app's[View](https://developer.android.com/reference/android/view/View)objects use custom touch handling, you should verify that they still work with TalkBack. You might just need to register the click handler that your[View](https://developer.android.com/reference/android/view/View)objects use. If TalkBack still doesn't recognize gestures performed on these[View](https://developer.android.com/reference/android/view/View)objects, override[performAccessibilityAction()](https://developer.android.com/reference/android/view/View#performAccessibilityAction(int, android.os.Bundle)).
- Accessibility services are now aware of all[ClickableSpan](https://developer.android.com/reference/android/text/style/ClickableSpan)instances within your app's[TextView](https://developer.android.com/reference/android/widget/TextView)objects.

To learn more about how to make your app more accessible, see[Accessibility](https://developer.android.com/guide/topics/ui/accessibility).

### Networking and HTTP(S) connectivity

Android 8.0 (API level 26) includes the following behavior changes to networking and HTTP(S) connectivity:

- OPTIONS requests with no body have a`Content-Length: 0`header. Previously they had no`Content-Length`header.
- HttpURLConnection normalizes URLs containing empty paths by appending a slash after the host or authority name with a slash. For example, it converts`http://example.com`to`http://example.com/`.
- A custom proxy selector set via ProxySelector.setDefault() only targets the address (scheme, host and port) of a requested URL. As a result, proxy selection may only be based on those values. A URL passed to a custom proxy selector does not include the requested URL's path, query parameters, or fragments.
- URIs cannot contain empty labels.Previously, the platform supported a workaround to accept empty labels in host names, which is an illegal use of URIs. This workaround was for compatibility with older libcore releases. Developers using the API incorrectly would see an ADB message: "URI example..com has empty labels in the hostname. This is malformed and will not be accepted in future Android releases." Android 8.0 removes this workaround; the system returns null for malformed URIs.

- Android 8.0's implementation of HttpsURLConnection does not perform insecure TLS/SSL protocol version fallback.
- Handling of tunneling HTTP(S) connections has changed as follows:
  - When tunneling HTTPS connection over connection, the system correctly places the port number (:443) in the Host line when sending this information to an intermediate server. Previously, the port number only occurred in the CONNECT line.
  - The system no longer sends user-agent and proxy-authorization headers from a tunneled request to the proxy server.The system no longer sends a proxy-authorization header on a tunneled Http(s)URLConnection to the proxy when setting up the tunnel. Instead, the system generates a proxy-authorization header, and sends it to the proxy when that proxy sends HTTP 407 in response to the initial request.

    Similarly, the system no longer copies the user-agent header from the tunneled request to the proxy request that sets up the tunnel. Instead, the library generates a user-agent header for that request.
- The[send(java.net.DatagramPacket)](https://developer.android.com/reference/java/net/DatagramSocket#send(java.net.DatagramPacket))method throws a SocketException if the previously executed connect() method failed.
  - DatagramSocket.connect() sets a pendingSocketException if there is an internal error. Prior to Android 8.0, a subsequent recv() call threw a SocketException even though a send() call would have succeeded. For consistency, both calls now throw a SocketException.
- InetAddress.isReachable() attempts ICMP before falling back to TCP Echo protocol.
  - Some hosts that block port 7 (TCP Echo), such as google.com, may now become reachable if they accept ICMP Echo protocol.
  - For truly unreachable hosts, this change means that twice the amount of time is spent before the call returns.

### Bluetooth

Android 8.0 (API level 26) makes the following changes to the length of the data that the[ScanRecord.getBytes()](https://developer.android.com/reference/android/bluetooth/le/ScanRecord#getBytes())method retrieves:

- The[getBytes()](https://developer.android.com/reference/android/bluetooth/le/ScanRecord#getBytes())method makes no assumptions as to the number of bytes received. Therefore, apps should not rely on any minimum or maximum number of bytes returned. Instead, they should evaluate the length of the resulting array.
- Bluetooth 5-compatible devices may return data length exceeding the previous maximum of \~60 bytes.
- If a remote device does not provide a scan response, fewer than 60 bytes may be returned as well.

### Seamless Connectivity

Android 8.0 (API level 26) makes a number of improvements to Wi-Fi Settings to make it easier to choose the Wi-Fi network that offers the best user experience. Specific changes include:

- Stability and reliability improvements.
- A more intuitively readable UI.
- A single, consolidated Wi-Fi Preferences menu.
- On compatible devices, automatic activation of Wi-Fi when a high quality saved network is nearby.

### Security

Android 8.0 includes the following security-related changes:

- The platform no longer supports SSLv3.
- When establishing an HTTPS connection to a server that incorrectly implements TLS protocol-version negotiation,[HttpsURLConnection](https://developer.android.com/reference/javax/net/ssl/HttpsURLConnection)no longer attempts the workaround of falling back to earlier TLS protocol versions and retrying.
- Android 8.0 (API level 26) applies a Secure Computing (SECCOMP) filter to all apps. The list of allowed syscalls is restricted to those exposed through bionic. Although there are several other syscalls provided for backwards compatibility, we recommend against their use.
- Your app's[WebView](https://developer.android.com/reference/android/webkit/WebView)objects now run in multiprocess mode. Web content is handled in a separate, isolated process from the containing app's process for enhanced security.
- You can no longer assume that APKs reside in directories whose names end in -1 or -2. Apps should use[sourceDir](https://developer.android.com/reference/android/content/pm/ApplicationInfo#sourceDir)to get the directory, and not rely on the directory format directly.
- For information about security enhancements related to use of native libraries, see[Native Libraries](https://developer.android.com/about/versions/oreo/android-8.0-changes#nl).

In addition, Android 8.0 (API level 26) introduces the following changes related to installing unknown apps from unknown sources:

- The value of the legacy setting[INSTALL_NON_MARKET_APPS](https://developer.android.com/reference/android/provider/Settings.Secure#INSTALL_NON_MARKET_APPS)is now always 1. To determine whether an unknown source can install apps using the package installer, you should instead use the return value of[canRequestPackageInstalls()](https://developer.android.com/reference/android/content/pm/PackageManager#canRequestPackageInstalls()).
- If you try to change the value of[INSTALL_NON_MARKET_APPS](https://developer.android.com/reference/android/provider/Settings.Secure#INSTALL_NON_MARKET_APPS)using[setSecureSetting()](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#setSecureSetting(android.content.ComponentName, java.lang.String, java.lang.String)), an[UnsupportedOperationException](https://developer.android.com/reference/java/lang/UnsupportedOperationException)is thrown. To prevent users from installing unknown apps using unknown sources, you should instead apply the[DISALLOW_INSTALL_UNKNOWN_SOURCES](https://developer.android.com/reference/android/os/UserManager#DISALLOW_INSTALL_UNKNOWN_SOURCES)user restriction.
- Managed profiles created on devices running Android 8.0 (API level 26) automatically have the[DISALLOW_INSTALL_UNKNOWN_SOURCES](https://developer.android.com/reference/android/os/UserManager#DISALLOW_INSTALL_UNKNOWN_SOURCES)user restriction enabled. For existing managed profiles on devices that are upgraded to Android 8.0, the[DISALLOW_INSTALL_UNKNOWN_SOURCES](https://developer.android.com/reference/android/os/UserManager#DISALLOW_INSTALL_UNKNOWN_SOURCES)user restriction is enabled automatically unless the profile owner has explicitly disabled this restriction (prior to upgrading) by setting[INSTALL_NON_MARKET_APPS](https://developer.android.com/reference/android/provider/Settings.Secure#INSTALL_NON_MARKET_APPS)to 1.

For additional details about installing unknown apps, see the[Unknown App Install Permissions](https://developer.android.com/studio/publish#publishing-unknown)guide.

For additional guidelines on making your app more secure, see[Security for Android Developers](https://developer.android.com/topic/security).

### Privacy

Android 8.0 (API level 26) makes the following privacy-related changes to the platform.

- The platform now handles identifiers differently.
  - For apps that were installed prior to an OTA to a version of Android 8.0 (API level 26) (API level 26), the value of[ANDROID_ID](https://developer.android.com/reference/android/provider/Settings.Secure#ANDROID_ID)remains the same unless uninstalled and then reinstalled after the OTA. To preserve values across uninstalls after OTA, developers can associate the old and new values by using[Key/Value Backup](https://developer.android.com/guide/topics/data/keyvaluebackup.html).
  - For apps installed on a device running Android 8.0, the value of[ANDROID_ID](https://developer.android.com/reference/android/provider/Settings.Secure#ANDROID_ID)is now scoped per app signing key, as well as per user. The value of[ANDROID_ID](https://developer.android.com/reference/android/provider/Settings.Secure#ANDROID_ID)is unique for each combination of app-signing key, user, and device. As a result, apps with different signing keys running on the same device no longer see the same Android ID (even for the same user).
  - The value of[ANDROID_ID](https://developer.android.com/reference/android/provider/Settings.Secure#ANDROID_ID)does not change on package uninstall or reinstall, as long as the signing key is the same (and the app was not installed prior to an OTA to a version of Android 8.0).
  - The value of[ANDROID_ID](https://developer.android.com/reference/android/provider/Settings.Secure#ANDROID_ID)does not change even if a system update causes the package signing key to change.
  - On devices shipping with Google Play services and Advertising ID, you must use[Advertising ID.](https://support.google.com/googleplay/android-developer/answer/6048248)A simple, standard system to monetize apps, Advertising ID is a unique, user-resettable ID for advertising. It is provided by Google Play services.

    Other device manufacturers should continue to provide[ANDROID_ID](https://developer.android.com/reference/android/provider/Settings.Secure#ANDROID_ID).
- Querying the`net.hostname`system property produces a null result.

### Logging of uncaught exceptions

If an app installs a[Thread.UncaughtExceptionHandler](https://developer.android.com/reference/java/lang/Thread.UncaughtExceptionHandler)that does not call through to the default[Thread.UncaughtExceptionHandler](https://developer.android.com/reference/java/lang/Thread.UncaughtExceptionHandler), the system does not kill the app when an uncaught exception occurs. Starting from Android 8.0 (API level 26), the system logs the exception stacktrace in this situation; in earlier versions of the platform, the system would not have logged the exception stacktrace.

We recommend that custom[Thread.UncaughtExceptionHandler](https://developer.android.com/reference/java/lang/Thread.UncaughtExceptionHandler)implementations always call through to the default handler; apps that follow this recommendation are unaffected by the change in Android 8.0.

### findViewById() signature change

All instances of the`findViewById()`method now return`
<T extends View> T`instead of`View`. This change has the following implications:

- This may result in existing code now having ambiguous return type, for example if there is both`someMethod(View)`and`someMethod(TextView)`that takes the result of a call to`findViewById()`.
- When using Java 8 source language, this requires an explicit cast to`View`when the return type is unconstrained (for example,`assertNotNull(findViewById(...)).someViewMethod())`.
- Overrides of non-final`findViewById()`methods (for example,`Activity.findViewById()`) will need their return type updated.

### Contacts provider usage stats change

In previous versions of Android, the Contacts Provider component allows developers to get usage data for each contact. This usage data exposes information for each email address and each phone number associated with a contact, including the number of times the contact has been contacted and the last time the contact was contacted. Apps that request the[READ_CONTACTS](https://developer.android.com/reference/android/Manifest.permission#READ_CONTACTS)permission can read this data.

Apps can still read this data if they request[READ_CONTACTS](https://developer.android.com/reference/android/Manifest.permission#READ_CONTACTS)permission. In Android 8.0 (API level 26) and higher, queries for usage data return approximations rather than exact values. The Android system maintains the exact values internally, so this change does not affect the auto-complete API.

This behavior change affects the following query parameters:

- [TIMES_CONTACTED](https://developer.android.com/reference/android/provider/ContactsContract.ContactOptionsColumns#TIMES_CONTACTED)
- [TIMES_USED](https://developer.android.com/reference/android/provider/ContactsContract.DataUsageStatColumns#TIMES_USED)
- [LAST_TIME_CONTACTED](https://developer.android.com/reference/android/provider/ContactsContract.ContactOptionsColumns#LAST_TIME_CONTACTED)
- [LAST_TIME_USED](https://developer.android.com/reference/android/provider/ContactsContract.DataUsageStatColumns#LAST_TIME_USED)

### Collection handling

[AbstractCollection.removeAll()](https://developer.android.com/reference/java/util/AbstractCollection#removeAll(java.util.Collection<?>))and[AbstractCollection.retainAll()](https://developer.android.com/reference/java/util/AbstractCollection#retainAll(java.util.Collection<?>))now always throw a[NullPointerException](https://developer.android.com/reference/java/lang/NullPointerException); previously, the[NullPointerException](https://developer.android.com/reference/java/lang/NullPointerException)was not thrown when the collection was empty. This change makes the behavior consistent with the documentation.

### Android enterprise

Android 8.0 (API level 26)[changes the behavior](https://developer.android.com/work/versions/Android-8.0#behavior-changes)of some APIs and features for enterprise apps, including device policy controllers (DPCs). The changes include:

- New behaviors to help apps support work profiles on fully managed devices.
- Changes to system update handling, app verification, and authentication to increase device and system integrity.
- Improvements to the user experience for provisioning, notifications, the Recents screen, and always-on VPN.

To see the all the enterprise changes in Android 8.0 (API level 26) and learn how they might affect your app, read[Android in the Enterprise](https://developer.android.com/work/versions/Android-8.0#behavior-changes).

## Apps targeting Android 8.0

These behavior changes apply exclusively to apps that are targeting Android 8.0 (API level 26) or higher. Apps that compile against Android 8.0, or set`targetSdkVersion`to Android 8.0 or higher must modify their apps to support these behaviors properly, where applicable to the app.

### Alert windows

Apps that use the[SYSTEM_ALERT_WINDOW](https://developer.android.com/reference/android/Manifest.permission#SYSTEM_ALERT_WINDOW)permission can no longer use the following window types to display alert windows above other apps and system windows:

- [TYPE_PHONE](https://developer.android.com/reference/android/view/WindowManager.LayoutParams#TYPE_PHONE)
- [TYPE_PRIORITY_PHONE](https://developer.android.com/reference/android/view/WindowManager.LayoutParams#TYPE_PRIORITY_PHONE)
- [TYPE_SYSTEM_ALERT](https://developer.android.com/reference/android/view/WindowManager.LayoutParams#TYPE_SYSTEM_ALERT)
- [TYPE_SYSTEM_OVERLAY](https://developer.android.com/reference/android/view/WindowManager.LayoutParams#TYPE_SYSTEM_OVERLAY)
- [TYPE_SYSTEM_ERROR](https://developer.android.com/reference/android/view/WindowManager.LayoutParams#TYPE_SYSTEM_ERROR)

Instead, apps must use a new window type called[TYPE_APPLICATION_OVERLAY](https://developer.android.com/reference/android/view/WindowManager.LayoutParams#TYPE_APPLICATION_OVERLAY).

When using the[TYPE_APPLICATION_OVERLAY](https://developer.android.com/reference/android/view/WindowManager.LayoutParams#TYPE_APPLICATION_OVERLAY)window type to display alert windows for your app, keep the following characteristics of the new window type in mind:

- An app's alert windows always appear under critical system windows, such as the status bar and IMEs.
- The system can move or resize windows that use the[TYPE_APPLICATION_OVERLAY](https://developer.android.com/reference/android/view/WindowManager.LayoutParams#TYPE_APPLICATION_OVERLAY)window type to improve screen presentation.
- By opening the notification shade, users can access settings to block an app from displaying alert windows shown using the[TYPE_APPLICATION_OVERLAY](https://developer.android.com/reference/android/view/WindowManager.LayoutParams#TYPE_APPLICATION_OVERLAY)window type.

### Content change notifications

Android 8.0 (API level 26) changes how[ContentResolver.notifyChange()](https://developer.android.com/reference/android/content/ContentResolver#notifyChange(android.net.Uri, android.database.ContentObserver))and[registerContentObserver(Uri, boolean, ContentObserver)](https://developer.android.com/reference/android/content/ContentResolver#registerContentObserver(android.net.Uri, boolean, android.database.ContentObserver))behave for apps targeting Android 8.0.

These APIs now require that a valid[ContentProvider](https://developer.android.com/reference/android/content/ContentProvider)is defined for the authority in all Uris. Defining a valid[ContentProvider](https://developer.android.com/reference/android/content/ContentProvider)with relevant permissions will help defend your app against content changes from malicious apps, and prevent you from leaking potentially private data to malicious apps.

### View focus

Clickable[View](https://developer.android.com/reference/android/view/View)objects are now also focusable by default. If you want a[View](https://developer.android.com/reference/android/view/View)object to be clickable but not focusable, set the[`android:focusable`](https://developer.android.com/reference/android/view/View#attr_android:focusable)attribute to`false`in the layout XML file containing the[View](https://developer.android.com/reference/android/view/View), or pass in`false`to[setFocusable()](https://developer.android.com/reference/android/view/View#setFocusable(boolean))in your app's UI logic.

### User-agent matching in browser detection

Android 8.0 (API level 26) and higher include the build identifier string`OPR`. Some pattern matches may cause browser-detection logic to misidentify a non-Opera browser as Opera. An example of such a pattern match might be:  

```
if(p.match(/OPR/)){k="Opera";c=p.match(/OPR\/(\d+.\d+)/);n=new Ext.Version(c[1])}
```

To avoid issues arising from such a misidentification, use a string other than`OPR`as a pattern-match for the Opera browser.

### Security

The following changes affect security in Android 8.0 (API level 26):

- If your app's network security configuration[opts out](https://developer.android.com/training/articles/security-config#CleartextTrafficPermitted)of supporting cleartext traffic, your app's[WebView](https://developer.android.com/reference/android/webkit/WebView)objects cannot access websites over HTTP. Each[WebView](https://developer.android.com/reference/android/webkit/WebView)object must use HTTPS instead.
- The**Allow unknown sources** system setting has been removed; in its place, the**Install unknown apps** permission manages unknown app installs from unknown sources. To learn more about this new permission, see the[Unknown App Install Permissions](https://developer.android.com/studio/publish#publishing-unknown)guide.

For additional guidelines on making your app more secure, see[Security for Android Developers](https://developer.android.com/topic/security).

### Account access and discoverability

In Android 8.0 (API level 26), apps can no longer get access to user accounts unless the authenticator owns the accounts or the user grants that access. The[GET_ACCOUNTS](https://developer.android.com/reference/android/Manifest.permission#GET_ACCOUNTS)permission is no longer sufficient. To be granted access to an account, apps should either use[AccountManager.newChooseAccountIntent()](https://developer.android.com/reference/android/accounts/AccountManager#newChooseAccountIntent(android.accounts.Account, java.util.List<android.accounts.Account>, java.lang.String[], java.lang.String, java.lang.String, java.lang.String[], android.os.Bundle))or an authenticator-specific method. After getting access to accounts, an app can call[AccountManager.getAccounts()](https://developer.android.com/reference/android/accounts/AccountManager#getAccounts())to access them.

Android 8.0 deprecates[LOGIN_ACCOUNTS_CHANGED_ACTION](https://developer.android.com/reference/android/accounts/AccountManager#LOGIN_ACCOUNTS_CHANGED_ACTION). Apps should instead use[addOnAccountsUpdatedListener()](https://developer.android.com/reference/android/accounts/AccountManager#addOnAccountsUpdatedListener(android.accounts.OnAccountsUpdateListener, android.os.Handler, boolean))to get updates about accounts during runtime.

For information about new APIs and methods added for account access and discoverability, see[Account Access and Discoverability](https://developer.android.com/about/versions/oreo/android-8.0#naa)in the New APIs section of this document.

### Privacy

The following changes affect privacy in Android 8.0 (API level 26).

- The system properties`net.dns1`,`net.dns2`,`net.dns3`, and`net.dns4`are no longer available, a change that improves privacy on the platform.
- To obtain networking information such as DNS servers, apps with the[ACCESS_NETWORK_STATE](https://developer.android.com/reference/android/Manifest.permission#ACCESS_NETWORK_STATE)permission can register a[NetworkRequest](https://developer.android.com/reference/android/net/NetworkRequest)or[NetworkCallback](https://developer.android.com/reference/android/net/ConnectivityManager.NetworkCallback)object. These classes are available in Android 5.0 (API level 21) and higher.
- Build.SERIAL is deprecated. Apps needing to know the hardware serial number should instead use the new[Build.getSerial()](https://developer.android.com/reference/android/os/Build#getSerial())method, which requires the[READ_PHONE_STATE](https://developer.android.com/reference/android/Manifest.permission#READ_PHONE_STATE)permission.
- The[LauncherApps](https://developer.android.com/reference/android/content/pm/LauncherApps)API no longer allows work profile apps to get information about the primary profile. When a user is in a work profile, the[LauncherApps](https://developer.android.com/reference/android/content/pm/LauncherApps)API behaves as if no apps are installed in other profiles within the same profile group. As before, attempts to access unrelated profiles causes SecurityExceptions.

### Permissions

Prior to Android 8.0 (API level 26), if an app requested a permission at runtime and the permission was granted, the system also incorrectly granted the app the rest of the permissions that belonged to the same permission group, and that were registered in the manifest.

For apps targeting Android 8.0, this behavior has been corrected. The app is granted only the permissions it has explicitly requested. However, once the user grants a permission to the app, all subsequent requests for permissions in that permission group are automatically granted.

For example, suppose an app lists both[READ_EXTERNAL_STORAGE](https://developer.android.com/reference/android/Manifest.permission#READ_EXTERNAL_STORAGE)and[WRITE_EXTERNAL_STORAGE](https://developer.android.com/reference/android/Manifest.permission#WRITE_EXTERNAL_STORAGE)in its manifest. The app requests[READ_EXTERNAL_STORAGE](https://developer.android.com/reference/android/Manifest.permission#READ_EXTERNAL_STORAGE)and the user grants it. If the app targets API level 25 or lower, the system also grants[WRITE_EXTERNAL_STORAGE](https://developer.android.com/reference/android/Manifest.permission#WRITE_EXTERNAL_STORAGE)at the same time, because it belongs to the same[STORAGE](https://developer.android.com/reference/android/Manifest.permission_group#STORAGE)permission group and is also registered in the manifest. If the app targets Android 8.0 (API level 26), the system grants only[READ_EXTERNAL_STORAGE](https://developer.android.com/reference/android/Manifest.permission#READ_EXTERNAL_STORAGE)at that time; however, if the app later requests[WRITE_EXTERNAL_STORAGE](https://developer.android.com/reference/android/Manifest.permission#WRITE_EXTERNAL_STORAGE), the system immediately grants that privilege without prompting the user.

### Media

- The framework can perform[automatic audio ducking](https://developer.android.com/guide/topics/media-apps/audio-focus#automatic-ducking)by itself. In this case, when another application requests focus with`AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK`, the application that has focus reduces its volume but usually does not receive an[onAudioFocusChange()](https://developer.android.com/reference/android/media/AudioManager.OnAudioFocusChangeListener#onAudioFocusChange(int))callback and will not lose audio focus. New APIs are available to override this behavior for applications that need to pause instead of ducking.
- When the user takes a phone call, active media streams mute for the duration of the call.
- All audio-related APIs should use[AudioAttributes](https://developer.android.com/reference/android/media/AudioAttributes)rather than audio stream types to describe the audio playback use case. Continue to use audio stream types for volume controls only. Other uses of stream types still work (for example, the`streamType`argument to the deprecated[AudioTrack](https://developer.android.com/reference/android/media/AudioTrack#AudioTrack(int, int, int, int, int, int))constructor), but the system logs this as an error.
- When using an[AudioTrack](https://developer.android.com/reference/android/media/AudioTrack), if the application requests a large enough audio buffer, the framework will try to use the deep buffer output if it is available.
- In Android 8.0 (API level 26) the handling of[media button events](https://developer.android.com/guide/topics/media-apps/mediabuttons)is different:
  1. The handling of media buttons in a UI activity has not changed: foreground activities still get priority in handling media button events.
  2. If the foreground activity does not handle the media button event, the system routes the event to the app that most recently played audio locally. The active status, flags, and playback state of a media session are not considered when determining which app receives media button events.
  3. If the app's media session has been released, the system sends the media button event to the app's[MediaButtonReceiver](https://developer.android.com/reference/android/support/v4/media/session/MediaButtonReceiver)if it has one.
  4. For every other case, the system discards the media button event.

### Native libraries

In apps targeting Android 8.0 (API level 26), native libraries no longer load if they contain any load segment that is both writable and executable. Some apps might stop working because of this change if they have native libraries with incorrect load segments. This is a security-hardening measure.

For more information, see[Writable and Executable Segments](https://android.googlesource.com/platform/bionic/+/master/android-changes-for-ndk-developers.md#Writable-and-Executable-Segments-Enforced-for-API-level-26).

Linker changes are tied to the API level that an app targets. If there is a linker change at the targeted API level, the app cannot load the library. If you are targeting an API level lower than the API level where the linker change occurs, logcat shows a warning.

### Collection handling

In Android 8.0 (API level 26),[Collections.sort()](https://developer.android.com/reference/java/util/Collections#sort(java.util.List<T>))is implemented on top of[List.sort()](https://developer.android.com/reference/java/util/List#sort(java.util.Comparator<? super E>)). The reverse was true in Android 7.x (API levels 24 and 25): The default implementation of[List.sort()](https://developer.android.com/reference/java/util/List#sort(java.util.Comparator<? super E>))called[Collections.sort()](https://developer.android.com/reference/java/util/Collections#sort(java.util.List<T>)).

This change allows[Collections.sort()](https://developer.android.com/reference/java/util/Collections#sort(java.util.List<T>))to take advantage of optimized[List.sort()](https://developer.android.com/reference/java/util/List#sort(java.util.Comparator<? super E>))implementations, but has the following constraints:

- Implementations of[List.sort()](https://developer.android.com/reference/java/util/List#sort(java.util.Comparator<? super E>))must not call[Collections.sort()](https://developer.android.com/reference/java/util/Collections#sort(java.util.List<T>)), because doing so would result in stack overflow due to infinite recursion. Instead, if you want the default behavior in your[List](https://developer.android.com/reference/java/util/List)implementation, you should avoid overriding`sort()`.

  If a parent class implements`sort()`inappropriately, it's usually fine to override[List.sort()](https://developer.android.com/reference/java/util/List#sort(java.util.Comparator<? super E>))with an implementation built on top of[List.toArray()](https://developer.android.com/reference/java/util/List#toArray()),[Arrays.sort()](https://developer.android.com/reference/java/util/Arrays#sort(java.lang.Object[])), and[ListIterator.set()](https://developer.android.com/reference/java/util/ListIterator#set(E)). For example:  

  ```transact-sql
  @Override
  public void sort(Comparator<? super E> c) {
    Object[] elements = toArray();
    Arrays.sort(elements, c);
    ListIterator<E> iterator = (ListIterator<Object>) listIterator();
    for (Object element : elements) {
      iterator.next();
      iterator.set((E) element);
    }
  }
  ```

  In most cases, you can also override[List.sort()](https://developer.android.com/reference/java/util/List#sort(java.util.Comparator<? super E>))with an implementation that delegates to different default implementations depending on API level. For example:  

  ```transact-sql
  @Override
  public void sort(Comparator<? super E> comparator) {
    if (Build.VERSION.SDK_INT <= 25) {
      Collections.sort(this);
    } else {
      super.sort(comparator);
    }
  }
  ```

  If you're doing the latter only because you want to have a`sort()`method available on all API levels, consider giving it a unique name, such as`sortCompat()`, instead of overriding`sort()`.
- [Collections.sort()](https://developer.android.com/reference/java/util/Collections#sort(java.util.List<T>))now counts as a structural modification in List implementations that call`sort()`. For example, in versions of the platform prior to Android 8.0 (API level 26), iterating over an[ArrayList](https://developer.android.com/reference/java/util/ArrayList)and calling`sort()`on it partway through the iteration would have thrown a[ConcurrentModificationException](https://developer.android.com/reference/java/util/ConcurrentModificationException)if the sorting was done by calling[List.sort()](https://developer.android.com/reference/java/util/List#sort(java.util.Comparator<? super E>)).[Collections.sort()](https://developer.android.com/reference/java/util/Collections#sort(java.util.List<T>))did not throw an exception.

  This change makes the platform behavior more consistent: Either approach now results in a[ConcurrentModificationException](https://developer.android.com/reference/java/util/ConcurrentModificationException).

### Class-loading behavior

Android 8.0 (API level 26) checks to make sure that class loaders do not break the assumptions of the runtime when loading new classes. These checks are performed whether the class is referenced from Java (from[forName()](https://developer.android.com/reference/java/lang/Class#forName(java.lang.String, boolean, java.lang.ClassLoader))), Dalvik bytecode, or JNI. The platform does not intercept direct calls from Java to the[loadClass()](https://developer.android.com/reference/java/lang/ClassLoader#loadClass(java.lang.String))method, nor does it check the results of such calls. This behavior should not affect the functioning of well-behaved class loaders.

The platform checks that the descriptor of the class that the class loader returns matches the expected descriptor. If the returned descriptor does not match, the platform throws a[NoClassDefFoundError](https://developer.android.com/reference/java/lang/NoClassDefFoundError)error, and stores in the exception a detailed message noting the discrepancy.

The platform also checks that the descriptors of the requested classes are valid. This check catches JNI calls that indirectly load classes such as`GetFieldID()`, passing invalid descriptors to those classes. For example, a field with signature`java/lang/String`is not found because that signature is invalid; it should be`Ljava/lang/String;`.

This is different from a JNI call to`FindClass()`where`java/lang/String`is a valid fully-qualified name.

Android 8.0 (API level 26) does not support having multiple class loaders try to define classes using the same DexFile object. An attempt to do so causes the Android runtime to throw an[InternalError](https://developer.android.com/reference/java/lang/InternalError)error with the message "Attempt to register dex file`<filename>`with multiple class loaders".

DexFile API is now deprecated, and you are strongly encouraged to use one of the platform classloaders, including`PathClassLoader`or`BaseDexClassLoader`, instead.

**Note:** You can create multiple class loaders that reference the same APK or JAR file container from the file system. Doing so normally does not result in much memory overhead: If DEX files in the container are stored instead of compressed, the platform can perform an`mmap`operation on them rather than directly extracting them. However, if the platform must extract the DEX file from the container, referencing a DEX file in this fashion may consume a lot of memory.

In Android, all class loaders are considered parallel-capable. When multiple threads race to load the same class with the same class loader, the first thread to complete the operation wins, and the result is used for the other threads. This behavior occurs regardless of whether the class loader has returned the same class, returned a different class, or thrown an exception. The platform silently ignores such exceptions.

**Caution:**In versions of the platform lower than Android 8.0 (API level 26), breaking these assumptions can lead to defining the same class multiple times, heap corruption due to class confusion, and other undesirable effects.