Behavior changes: Apps targeting Android 12

Like earlier releases, Android 12 includes behavior changes that may affect your app. The following behavior changes apply exclusively to apps that are targeting Android 12 or higher. If your app is targeting Android 12, you should modify your app to support these behaviors properly, where applicable.

Be sure to also review the list of behavior changes that affect all apps running on Android 12.

User experience

Picture-in-picture behavior improvements

Android 12 introduces behavior improvements for picture-in-picture (PiP) mode. See Picture-in-picture improvements for more information.

Custom notifications

Android 12 changes the appearance and behavior of fully custom notifications. Previously, custom notifications were able to use the entire notification area and provide their own layouts and styles. This resulted in anti-patterns that could confuse users or cause layout compatibility issues on different devices.

For apps targeting Android 12, notifications with custom content views will no longer use the full notification area; instead, the system applies a standard template. This template ensures that custom notifications have the same decoration as other notifications in all states, such as the notification's icon and expansion affordances (in the collapsed state) and the notification's icon, app name, and collapse affordance (in the expansion state). This behavior is nearly identical to the behavior of Notification.DecoratedCustomViewStyle.

In this way, Android 12 makes all notifications visually consistent and easy to scan, with a discoverable, familiar notification expansion for users.

The following illustration shows a custom notification in the standard template:

The following examples show how custom notifications would render in a collapsed and an expanded state:

The change in Android 12 affects apps that define custom subclasses of Notification.Style, or which use Notification.Builder’s methods setCustomContentView(RemoteViews), setCustomBigContentView(RemoteViews), and setCustomHeadsUpContentView(RemoteViews).

If your app is using fully custom notifications, we recommend testing with the new template as soon as possible.

  1. Enable the custom notifications change:

    1. Change your app's targetSdkVersion to S to enable the new behavior.
    2. Recompile.
    3. Install your app on a device or emulator running Android 12.
  2. Test all notifications that use custom views, ensuring they look as you expect in the shade. While testing, take these considerations into account and make the necessary adjustments:

    • The dimensions of custom views have changed. In general, the height afforded to custom notifications is less than before. In the collapsed state, the maximum height of the custom content has decreased from 106dp to 48dp. Also, there is less horizontal space.

    • All notifications are expandable for apps targeting Android 12. Typically, this means if you're using setCustomContentView, you'll also want to use setBigCustomContentView to make sure collapsed and expanded states are consistent.

    • To make sure that the "Heads Up" state looks as you expect, don’t forget to raise the importance of the notification channel to "HIGH" (Pops on screen).

On apps that target Android 12, the system makes several changes to how Android App Links are verified. These changes improve the reliability of the app-linking experience and provide more control to app developers and end users.

If you target Android 12 and rely on Android App Link verification to open web links in your app, update your Android App Links declarations to support the changed verification process. You can also manually invoke domain verification to test the reliability of your declarations.


Approximate location

The dialog has two sets of options, one above the
Figure 1. System permissions dialog that appears when your app targets Android 12 and requests both ACCESS_FINE_LOCATION and ACCESS_COARSE_LOCATION in a single runtime request.

When using an app that targets Android 12, users can request that the app have access to only approximate location information.

If your app targets Android 12 and requests the ACCESS_FINE_LOCATION runtime permission, you must also request the ACCESS_COARSE_LOCATION permission. You must include both permissions in a single runtime request.

When your app requests both ACCESS_FINE_LOCATION and ACCESS_COARSE_LOCATION, the system permissions dialog includes the following new options for the user, as shown in figure 1:

  • Precise: Provides the location accuracy that the ACCESS_FINE_LOCATION permission provides.
  • Approximate: Provides the location accuracy that the ACCESS_COARSE_LOCATION permission provides.

Learn more about approximate location in Android 12.

App hibernation

Android 12 expands upon the permissions auto-reset behavior that was introduced in Android 11 (API level 30). If your app targets Android 12 and the user doesn't interact with your app for a few months, the system auto-resets any granted permissions and places your app in a hibernation state.

Examples of app usage

Each of the following behaviors is considered to be a user interaction, which extends the amount of time before your app enters hibernation:

  • An activity is resumed.
  • The user interacts with a widget.
  • The user interacts with a notification, except for dismissing the notification.

Non-examples of app usage

If your app only ever exhibits the behaviors in the following list, your app enters hibernation after a few months:

Characteristics of an app in hibernation

An app that's in hibernation has the following characteristics:

  • The system optimizes for storage space instead of performance. Any files in your app's cache are removed.
  • The app can't run jobs or alerts from the background.
  • The app can't receive push notifications, including high-priority messages that are sent through Firebase Cloud Messaging.

When the user next interacts with the app, the app exits hibernation, and it can create jobs, alerts, and notifications again. However, you need to reschedule any jobs, alerts, and notifications that were scheduled before the app went into hibernation. This workflow is similar to when the user manually force-stops your app from system settings. To support this workflow more easily, use WorkManager. You can also add rescheduling logic in the ACTION_BOOT_COMPLETED broadcast receiver, which is invoked when your app leaves hibernation and after the device boots up.

Request user to disable hibernation

If you anticipate that a use case in your app is affected by hibernation, you can send the user a request to grant your app an exemption from hibernation and permissions auto-reset. This exemption is useful for situations in which users expect your app to work primarily in the background, even without the user interacting with your app, such as when your app does one or more of the following:

  • Provide family safety by periodically reporting the location of family members.
  • Sync data between a device and your app's server.
  • Communicate with smart devices, such as a TV.
  • Pair to companion devices, such as a watch.

To request an exemption, invoke an intent that contains the Intent.ACTION_APPLICATION_DETAILS_SETTINGS intent action. From the screen that appears, users can turn off the option called Remove permissions and free up space.

There is also a backward-compatible Jetpack API that handles both app hibernation and the related permission auto-reset feature. If hibernation is enabled for your app, the getUnusedAppRestrictionsStatus API returns API_31.

Test the hibernation behavior

To place your app in the hibernation state for testing purposes, do the following:

  1. Check that your app targets Android 12. If your app targets a lower version, the system can't place your app into hibernation.

  2. Enable the behavior on your device:

    adb shell device_config put app_hibernation app_hibernation_enabled true
  3. Save the default amount of time that the system waits to enter hibernation. That way, you can restore it after testing:

    threshold=$(adb shell device_config get permissions \
  4. Reduce the amount of time that the system waits to place your app into hibernation. In the following example, the system is modified such that an app enters hibernation only one second after you stop interacting with an app:

    adb shell device_config put permissions \
      auto_revoke_unused_threshold_millis2 1000
  5. Wait for any boot-time broadcasts to finish on your test device by running the following command:

    adb shell am wait-for-broadcast-idle

    When the broadcasts are finished, this command returns the message: All broadcast queues are idle!

  6. Invoke the app hibernation process manually, as shown in the following snippet:

    adb shell cmd jobscheduler run -u 0 -f \ 2
  7. Confirm that the app is hibernated, using one of the following methods:

    • Observe that the test device now shows a notification, indicating that unused apps are hibernated.
    • Run the following command:

      adb shell cmd app_hibernation get-state PACKAGE-NAME
  8. Restore the default amount of time that the system waits before it places your app into hibernation:

    adb shell device_config put permissions \
      auto_revoke_unused_threshold_millis2 $threshold

Motion sensors are rate-limited

To protect potentially sensitive information about users, if your app targets Android 12, the system places a limit on the refresh rate of data from certain motion sensors and position sensors. This data includes values recorded by the device's accelerometer, gyroscope, and geomagnetic field sensor.

The refresh rate limit depends on how you access sensor data:

  • If you call the registerListener() method, the sensor sampling rate is limited to 200 Hz. This is true for all overloaded variants of the registerListener() method.
  • If you use the SensorDirectChannel class, the sensor sampling rate is limited to RATE_NORMAL, which is usually about 50 Hz.

If your app targets Android 12 and needs to gather motion sensor data at a higher rate, you must declare the HIGH_SAMPLING_RATE_SENSORS permission. Otherwise, if your app tries to gather motion sensor data at a higher rate without declaring this permission, a SecurityException occurs.

Data access auditing

The data access auditing API, introduced in Android 11 (API level 30), allows you to create attribution tags based on your app's use cases. These tags make it easier for you to determine which part of your app performs a specific type of data access.

If your app targets Android 12, you must declare these attribution tags in your app's manifest file, using the format shown in the following code snippet. If your app targets Android 12 and you attempt to use an attribution tag that you don't declare in your app's manifest file, the system creates a null tag for you and logs a message in Logcat.

<manifest ...>
    <!-- The value of "android:tag" must be a literal string, and the
         value of "android:label" must be a resource. The value of
         "android:label" should be user-readable. -->
    <attribution android:tag="sharePhotos"
                 android:label="@string/share_photos_attribution_label" />

Modern SameSite cookies in WebView

Android’s WebView component is based on Chromium, the open source project that powers Google’s Chrome browser. Over the last year, Chromium has introduced changes to the handling of third-party cookies to provide more security and privacy and offer users more transparency and control. These changes are already rolled out to many Chrome users, and starting with Android 12, the changes are now coming to WebView.

The SameSite attribute of a cookie controls whether it can be sent with any requests, or only with same-site requests. The base version of WebView in Android 12 (version 89.0.4385.0) includes the following privacy-protecting changes that improve the default handling of third-party cookies and help protect against unintended cross-site sharing:

  • Cookies without a SameSite attribute are treated as SameSite=Lax.
  • Cookies with SameSite=None must also specify the Secure attribute, meaning they require a secure context and should be sent over HTTPS.
  • Links between HTTP and HTTPS versions of a site are now treated as cross-site requests, so cookies are not sent unless they are appropriately marked as SameSite=None; Secure.

For developers, the general guidance is to identify the cross-site cookie dependencies in your critical user flows and ensure that the SameSite attribute is explicitly set with the appropriate values where needed. You must explicitly specify the cookies that are allowed to work across websites or across same-site navigations that move from HTTP to HTTPS.

For complete guidance for web developers on these changes, see SameSite Cookies Explained and Schemeful SameSite.

Test SameSite behaviors in your app

If your app uses WebView, or if you manage a website or service that uses cookies, we recommend testing your flows on Android 12 WebView. If you find issues, you might need to update your cookies to support the new SameSite behaviors.

Watch for issues in logins and embedded content, as well as sign-in flows, purchasing, and other authentication flows where the user starts on an insecure page and transitions to a secure page.

To test an app with WebView, you must enable the new SameSite behaviors for the app that you want to test by completing either of the following steps:

  • Manually enable SameSite behaviors on the test device by toggling the UI flag webview-enable-modern-cookie-same-site in the WebView devtools.

    This approach lets you test on any device running Android 5.0 (API level 21) or higher—including Android 12—and WebView version 89.0.4385.0 or higher.

  • Compile your app to target Android 12 (API level 31) by targetSdkVersion.

    If you use this approach, you must use a device that runs Android 12 and WebView version 89.0.4385.0 or higher.

For information on remote debugging for WebView on Android, see Get Started with Remote Debugging Android Devices.

Other resources

For more information about the SameSite modern behaviors and rollout to Chrome and WebView, visit the Chromium SameSite Updates page. If you find a bug in WebView or Chromium, you can report it in the public Chromium issue tracker.

ADB backup restriction

To help protect private app data, Android 12 (API level 31) changes the default behavior of the adb backup command. For apps that target Android 12, when a user runs the adb backup command, app data is excluded from any other system data that is exported from the device.

If your testing or development workflows rely on app data using adb backup, you can now opt in to exporting your app's data by setting android:debuggable to true in your app's manifest file.


Safer component exporting

If your app targets Android 12 and contains activities, services, or broadcast receivers that use intent filters, you must explicitly declare the android:exported attribute for these app components.

The following code snippet shows an example of a service that contains an intent filter and is configured correctly for Android 12:

<service android:name=""
        <action android:name="" />

Messages in Android Studio

If your app contains an activity, service, or broadcast receiver that uses intent filters but doesn't declare android:exported, the following warning messages appear, depending on the version of Android Studio that you use:

Android Studio 2020.3.1 Canary 11 or later

The following messages appear:

  1. The following lint warning appears in your manifest file:

    When using intent filters, please specify android:exported as well
  2. When you attempt to compile your app, the following build error message appears:

    Manifest merger failed : Apps targeting Android 12 and higher are required \
    to specify an explicit value for android:exported when the corresponding \
    component has an intent filter defined.
Older versions of Android Studio

If you attempt to install the app, Logcat displays the following error message:

Installation did not succeed.
The application could not be installed: INSTALL_FAILED_VERIFICATION_FAILURE
List of apks:
[0] '.../build/outputs/apk/debug/app-debug.apk'
Installation failed due to: 'null'

Pending intents mutability

If your app targets Android 12, you must specify the mutability of each PendingIntent object that your app creates. This additional requirement improves your app's security.

To declare that a given PendingIntent object is mutable or immutable, use the PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_IMMUTABLE flag, respectively. If your app attempts to create a PendingIntent object without setting either mutability flag, the system throws an IllegalArgumentException, and the following message appears in Logcat:

PACKAGE_NAME: Targeting S+ (version 31 and above) requires that one of \
FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent.

Strongly consider using FLAG_IMMUTABLE, only use FLAG_MUTABLE if \
some functionality depends on the PendingIntent being mutable, e.g. if \
it needs to be used with inline replies or bubbles.

Create immutable pending intents whenever possible

In most cases, your app should create immutable PendingIntent objects, as shown in the following code snippet. If a PendingIntent object is immutable, then an app cannot modify the intent to adjust the result of invoking the intent.


val pendingIntent = PendingIntent.getActivity(applicationContext,
        REQUEST_CODE, intent,
        /* flags */ PendingIntent.FLAG_IMMUTABLE)


PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(),
        REQUEST_CODE, intent,
        /* flags */ PendingIntent.FLAG_IMMUTABLE);

However, certain use cases require mutable PendingIntent objects instead:

  • Supporting direct reply actions in notifications. The direct reply requires a change to the clip data in the PendingIntent object that's associated with the reply. Usually, you request this change by passing FILL_IN_CLIP_DATA as a flag to the fillIn() method.
  • Associating notifications with the Android Auto framework, using instances of CarAppExtender.
  • Placing conversations in bubbles using instances of PendingIntent. A mutable PendingIntent object allows the system to apply the correct flags, such as FLAG_ACTIVITY_MULTIPLE_TASK and FLAG_ACTIVITY_NEW_DOCUMENT.
  • Requesting device location information by calling requestLocationUpdates() or similar APIs. The mutable PendingIntent object allows the system to add intent extras that represent location lifecycle events. These events include a change in location and a provider becoming available.
  • Scheduling alarms using AlarmManager. The mutable PendingIntent object allows the system to add the EXTRA_ALARM_COUNT intent extra. This extra represents the number of times that a repeating alarm has been triggered. By containing this extra, the intent can accurately notify an app as to whether a repeating alarm was triggered multiple times, such as when the device was asleep.

If your app creates a mutable PendingIntent object, it's strongly recommended that you use an explicit intent and fill in the ComponentName. That way, whenever another app invokes the PendingIntent and passes control back to your app, the same component in your app always starts.

Test the pending intent mutability change

To determine whether your app is missing mutability declarations, look for the following lint warning in Android Studio:

Warning: Missing PendingIntent mutability flag [UnspecifiedImmutableFlag]

During the Developer Preview, you can disable this system behavior for testing purposes by turning off the PENDING_INTENT_EXPLICIT_MUTABILITY_REQUIRED app compatibility flag.

Unsafe intent launches

To improve platform security, Android 12 provides a debugging feature that warns you if your app performs an unsafe launch of an intent. For example, your app might perform an unsafe launch of an intent that's recreated from a URI, or an unsafe launch of a nested intent, which the next section defines.

About nested intents

A nested intent is an intent that is passed as an extra in another intent. If your app performs both of the following actions, a StrictMode violation occurs.

Configure your app to detect unsafe intent launches

To check for unsafe intent launches in your app, call detectUnsafeIntentLaunch() when you configure your VmPolicy, as shown in the following code snippet. If your app detects a StrictMode violation, you might want to stop app execution to protect potentially sensitive information.


fun onCreate() {
        // Other StrictMode checks that you've previously added.
        // ...
        // Consider also adding penaltyDeath()


protected void onCreate() {
    StrictMode.setVmPolicy(new VmPolicy.Builder()
        // Other StrictMode checks that you've previously added.
        // ...
        // Consider also adding penaltyDeath()

Use intents more responsibly

Your app might launch intents to navigate between components inside of your app, or to perform an action on behalf of another app. To minimize the chance of encountering a StrictMode violation in either situation, do the following:

  • Copy only the essential extras within intents, and perform any necessary sanitation and validation. Your app might copy the extras from one intent to another intent that is used to launch a new component. This occurs when your app calls putExtras(Intent) or putExtras(Bundle). If your app performs one of these operations, copy only the extras that the receiving component expects. If the other intent (that receives the copy) launches a component that isn't exported, sanitize and validate the extras before copying them to the intent that launches the component.
  • Internal launch of nested intent: Make sure that these components aren't exported.
  • Cross-app launch of nested intent: Use a PendingIntent instead of a nested intent. That way, when the PendingIntent is unparceled out of its containing Intent, an app component can launch the PendingIntent using the identity of the calling process. This configuration allows a provider app to send a callback to any component, including a non-exported component, of the calling app.

    For more details on how to identify this situation and make changes to your app, read the blog post about Android Nesting Intents on Medium.


Foreground service launch restrictions

Apps that target Android 12 can no longer start foreground services while running in the background, except for a few special cases. If an app attempts to start a foreground service while running in the background, an exception occurs (except for the few special cases). Consider using WorkManager to schedule and start work while your app runs in the background.

To learn more about how your app is affected, and how you can update your app based on these changes, read the guide about foreground service launch restrictions. You can also look through the WorkManagerSample on GitHub.

Exact alarm permission

To encourage apps to conserve system resources, Android 12 requires the "Alarms & reminders" special app access to apps that target Android 12 that set exact alarms.

To obtain this special app access, request the SCHEDULE_EXACT_ALARM permission in the manifest.

Exact alarms should only be used for user-facing features, such as one of the situations described in the acceptable use cases section.

Both the user and the system can revoke the "Alarms & reminders" special app access. When the "Alarms & reminders" special app access is revoked for your app, your app is stopped, and all future exact alarms are canceled.

When the "Alarms & reminders" special app access is granted to your app, the system sends it the ACTION_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED broadcast. Your app should implement a broadcast receiver that does the following:

  1. Confirm that your app still has the special app access. To do so, call canScheduleExactAlarms().
  2. Reschedule any exact alarms that your app needs, based on its current state. This logic should be similar to what your app does when it receives the ACTION_BOOT_COMPLETED broadcast.

If your app attempts to use APIs that set exact alarms but isn't granted the special app access, a SecurityException occurs.

Consider whether your app's use case absolutely requires exact alarms, such as one of the situations described in the acceptable use cases section. To perform longer work, or work that requires network access, use WorkManager or JobScheduler. To perform work while the device is in Doze, create an inexact alarm using setAndAllowWhileIdle(), and start a job from the alarm.

Exact alarms and inexact alarms

Your app sets an exact alarm when it calls methods such as the following:

In contrast, you set inexact alarms when you call methods such as the following:

Acceptable use cases for this permission

The option is called 'Allow setting alarms and reminders'
Figure 2. "Alarms & reminders" special app access page in system settings, where users can allow your app to set exact alarms.

Your app should use exact alarms, and declare the associated permission and broadcast receivers, only if a user-facing function in your app requires precisely-timed actions, such as in the following situations:

  • Your app is an alarm clock app or a timer app.
  • Your app allows users to schedule precisely-timed actions, such as notifications for tasks and events.

Android 12 considers exact alarms to be critical, time-sensitive interruptions. For this reason, exact alarms aren't affected by the new foreground service launch restrictions.

Ask users to grant the app access

If necessary, you can send users to the Alarms & reminders screen in system settings, as shown in figure 2. To do so, complete the following steps:

  1. In your app's UI, explain to the user why your app needs to schedule exact alarms.
  2. Invoke an intent that includes the ACTION_REQUEST_SCHEDULE_EXACT_ALARM intent action.

Enable the behavior change

To enable the behavior change for testing purposes, do one of the following:

  • In the Developer options setting screen, select App Compatibility Changes. On the screen that appears, tap on your app's name, then turn on REQUIRE_EXACT_ALARM_PERMISSION.
  • In a terminal window on your development machine, run the following command:


Notification trampoline restrictions

When users interact with notifications, some apps respond to notification taps by launching an app component that eventually starts the activity that the user finally sees and interacts with. This app component is known as a notification trampoline.

To improve app performance and UX, apps that target Android 12 cannot start activities from services or broadcast receivers that are used as notification trampolines. In other words, after the user taps on a notification, or an action button within the notification, your app cannot call startActivity() inside of a service or broadcast receiver.

When your app tries to start an activity from a service or broadcast receiver that acts as a notification trampoline, the system prevents the activity from starting, and the following message appears in Logcat:

Indirect notification activity start (trampoline) from PACKAGE_NAME, \
this should be avoided for performance reasons.

Identify which app components act as notification trampolines

When testing your app, after you tap on a notification, you can identify which service or broadcast receiver acted as the notification trampoline in your app. To do so, look at output of the following terminal command:

adb shell dumpsys activity service \

A section of the output includes the text "NotifInteractionLog". This section contains the information that's necessary to identify the component that starts as the result of a notification tap.

Update your app

If your app starts an activity from a service or broadcast receiver that acts as a notification trampoline, complete the following migration steps:

  1. Create a PendingIntent object that is associated with the activity that users see after they tap on the notification.
  2. Use the PendingIntent object that you created in the previous step as part of building your notification.

To identify the origin of the activity, in order to perform logging for example, use extras when posting the notification. For centralized logging, use ActivityLifecycleCallbacks or Jetpack lifecycle observers.

Toggle the behavior

When testing your app during the Developer Preview, you can enable and disable this restriction using the NOTIFICATION_TRAMPOLINE_BLOCK app compatibility flag.

Backup and restore

Android 12 (API level 31) changes how backup and restore works in apps that run on and target Android 12 or higher. For more information, see Changes in backup and restore.


Concurrent Peer-to-Peer + Internet Connection

Starting with Android 12, devices that support concurrent peer-to-peer and internet connections can maintain simultaneous Wi-Fi connections to both the peer device and the primary internet-providing network, making the user experience more seamless. This feature is automatically enabled for all apps targeting API level 31 and higher. Apps targeting lower API levels still experience the legacy behavior, where the primary Wi-Fi network is disconnected prior to connecting to the peer device.


WifiManager.getConnectionInfo() is able to return the WifiInfo for only a single network. Because of this, the API's behavior has been changed in the following ways in Android 12:

  • If only a single Wi-Fi network is available, its WifiInfo is returned.
  • If more than one Wi-Fi network is available and the calling app triggered a peer-to-peer connection, the WifiInfo corresponding to the peer device is returned.
  • If more than one Wi-Fi network is available and the calling app did not trigger a peer-to-peer connection, the primary internet-providing connection's WifiInfo is returned.

To provide a better user experience on devices that support dual concurrent Wi-Fi networks, we recommend all apps—especially ones that trigger peer-to-peer connections—migrate away from calling WifiManager.getConnectionInfo() and instead use NetworkCallback.onCapabilitiesChanged() to get all WifiInfo objects that match the NetworkRequest used to register the NetworkCallback. getConnectionInfo() is deprecated as of Android 12.

The following code sample shows how to get the WifiInfo in a NetworkCallback:


val networkCallback = object : ConnectivityManager.NetworkCallback() {
  override fun onCapabilitiesChanged(
           network : Network,
           networkCapabilities : NetworkCapabilities) {
    val transportInfo = networkCapabilities.getTransportInfo()
    if (transportInfo !is WifiInfo) return
    val wifiInfo : WifiInfo = transportInfo


final NetworkCallback networkCallback = new NetworkCallback() {
  public void onCapabilitiesChanged(
         Network network,
         NetworkCapabilities networkCapabilities) {
    final TransportInfo transportInfo = networkCapabilities.getTransportInfo();
    if (!(transportInfo instanceof WifiInfo)) return;
    final WifiInfo wifiInfo = (WifiInfo) transportInfo;

Enable screen off for NFC payments

In apps that target Android 12 and higher, you can enable NFC payments without the device's screen on by setting requireDeviceScreenOn to false. For more information about NFC payments with screen off or locked, see Screen off and lock-screen behavior.

mDNSResponder native API

Android 12 changes when apps can interact with the mDNSResponder daemon using the mDNSResponder native API. Previously, when an app registered a service on the network and called the getSystemService() method, the system's NSD service started the mDNSResponder daemon, even if the app had not called any NsdManager methods yet. The daemon then subscribed the device to the all-nodes multicast groups, causing the system to wake more frequently and use additional power. To minimize battery usage, in Android 12 the system now starts the mDNSResponder daemon only when it is needed for NSD events and stops it afterwards.

Because this change affects when the mDNSResponder daemon is available, apps that assume that the mDNSResponder daemon will be started after calling the getSystemService() method might receive messages from the system that say that the mDNSResponder daemon is not available. Apps that use NsdManager and do not use the mDNSResponder native API are unaffected by this change.

Vendor libraries

Vendor-supplied native shared libraries

Non-NDK native shared libraries that are provided by silicon vendors or device manufacturers are not accessible by default if the app is targeting Android 12 or higher. The libraries are accessible only when they are explicitly requested using the <uses-native-library> tag.

If the app is targeting Android 11 or lower, the <uses-native-library> tag is not required. In that case, any native shared library is accessible regardless of whether it is an NDK library.

Updated non-SDK restrictions

Android 12 includes updated lists of restricted non-SDK interfaces based on collaboration with Android developers and the latest internal testing. Whenever possible, we make sure that public alternatives are available before we restrict non-SDK interfaces.

If your app does not target Android 12, some of these changes might not immediately affect you. However, while you can currently use some non-SDK interfaces (depending on your app's target API level), using any non-SDK method or field always carries a high risk of breaking your app.

If you are unsure if your app uses non-SDK interfaces, you can test your app to find out. If your app relies on non-SDK interfaces, you should begin planning a migration to SDK alternatives. Nevertheless, we understand that some apps have valid use cases for using non-SDK interfaces. If you cannot find an alternative to using a non-SDK interface for a feature in your app, you should request a new public API.

To learn more about the changes in this release of Android, see Updates to non-SDK interface restrictions in Android 12. To learn more about non-SDK interfaces generally, see Restrictions on non-SDK interfaces.