android Q

Android Q features and APIs

Android Q introduces great new features and capabilities for users and developers. This document highlights what's new for developers.

To learn about the new APIs, read the API diff report or visit the Android API reference — new APIs are highlighted to make them easy to see. Also be sure to check out Android Q behavior changes (for apps targeting Q and for all apps), as well as privacy changes, to learn about areas where platform changes may affect your apps.

Security enhancements

Android Q introduces a number of security features, which the following sections summarize.

Improved biometric authentication dialogs

Android Q introduces the following improvements to the unified biometric authentication dialogs added in Android 9:

Specify user confirmation requirements

You can now provide a hint that tells the system not to require user confirmation after the user has authenticated using an implicit biometric modality. For example, you could tell the system that no further confirmation should be required after a user has authenticated using Face authentication.

By default, the system requires user confirmation. Typically, users want to confirm sensitive or high-risk actions (for example, making a purchase). However, if you have certain low-risk actions for your app, you can provide a hint to not require user confirmation by passing false to the setConfirmationRequired() method. Because this flag is passed as a hint to the system, the system may ignore the value if the user has changed their system settings for biometric authentication.

An example of face authentication with no user confirmation.

Figure 1.Face authentication with no user confirmation

 

An example of face authentication that requires user confirmation.

Figure 2.Face authentication that requires user confirmation

 

Improved fallback support for device credentials

You can now tell the system to allow a user to authenticate using their device PIN, pattern, or password if they cannot authenticate using their biometric input for some reason. To enable this fallback support, use thesetDeviceCredentialAllowed() method.

If your app currently uses createConfirmDeviceCredentialIntent() to fall back to device credentials, switch to using the new method instead.

Check device for biometric capability

You can now check if a device supports biometric authentication prior to invoking BiometricPrompt by using the canAuthenticate() method in the BiometricManager class.

Run embedded DEX code directly from APK

You can now tell the platform to run embedded DEX code directly from your app’s APK file. This option can help prevent an attack if an attacker ever managed to tamper with the locally compiled code on the device.

Note: Enabling this feature could possibly affect your app’s performance because ART must use the JIT compiler when the app is started (instead of reading native code that was compiled ahead of time). We recommend testing your app’s performance before you decide whether or not to enable this feature in your published apps.

To enable this feature, set the value of the android:useEmbeddedDex attribute to true in the <application> element of your app’s manifest file. You must also build an APK that contains uncompressed DEX code that ART can access directly. Add the following options to your Gradle or Bazel configuration file to build an APK with uncompressed DEX code:

Gradle

aaptOptions {
   noCompress 'dex'
}

 

Bazel

android_binary(
   ...,
   nocompress_extensions = [“.dex”],
)

 

 

TLS 1.3 support

The platform's TLS implementation now supports TLS 1.3. TLS 1.3 is a major revision to the TLS standard that includes performance benefits and enhanced security. Our benchmarks indicate that secure connections can be established as much as 40% faster with TLS 1.3 compared to TLS 1.2.

TLS 1.3 is enabled by default for all TLS connections. You can obtain an SSLContext that has TLS 1.3 disabled by calling SSLContext.getInstance("TLSv1.2"). You can also enable or disable protocol versions on a per-connection basis by calling setEnabledProtocols() on an appropriate object.

Here are a few important details about our TLS 1.3 implementation:

  • The TLS 1.3 cipher suites cannot be customized. The supported TLS 1.3 cipher suites are always enabled when TLS 1.3 is enabled, and any attempt to disable them via a call to setEnabledCipherSuites() is ignored.
  • When TLS 1.3 is negotiated, HandshakeCompletedListeners are called before sessions are added to the session cache (which is the opposite of TLS 1.2 and other previous versions).
  • SSLEngine instances will throw an SSLProtocolException in some circumstances where they would have thrown an SSLHandshakeException previously.
  • 0-RTT mode is not supported.

Public Conscrypt API

The Conscrypt security provider now includes a public API for TLS functionality. In the past, users could access this functionality via reflection. However, due to restrictions on calling non-public APIs added in P, this has been greylisted in Q and will be further restricted in future releases.

This update adds a collection of classes under android.net.ssl that contain static methods to access functionality not available from the generic javax.net.ssl APIs. The names for these classes can be inferred as the plural of the associated javax.net.ssl class. For example, code that operates on javax.net.ssl.SSLSocket instances can use methods from the new android.net.ssl.SSLSockets class.

Connectivity features

Android Q includes several improvements related to networking and connectivity.

Wi-Fi network connection API

Android Q adds support for peer-to-peer connections. This feature enables your app to prompt the user to change the access point that the device is connected to by using WifiNetworkSpecifier to describe properties of a requested network. The peer-to-peer connection is used for non-network-providing purposes, such as bootstrapping configuration for secondary devices like Chromecast and Google Home hardware.

You will use the following flow when using this API:

  1. Create a Wi-Fi network specifier using WifiNetworkSpecifier.Builder.

  2. Set a network filter to match networks to connect to, along with required credentials.

  3. Decide on a combination of SSIDSSID patternBSSID, and BSSID pattern to set the network filter in each request, subject to the following requirements:

    • Each request should provide at least one of SSIDSSID patternBSSID, or BSSID pattern
    • Each request can set only one of SSID or SSID pattern
    • Each request can set only one of BSSID or BSSID pattern
  4. Add the specifiers to the network request along with a NetworkCallback instance to track the status of the request.

    If the user accepts the request and the connection to the network is successful,NetworkCallback.onAvailable() is invoked on the callback object. If the user denies the request or if the connection to the network is unsuccessful, NetworkCallback.onUnavailable() is invoked on the callback object.

Peer-to-peer connections do not require Location or Wi-Fi permissions. Initiating the request to connect to a peer device launches a dialog box on the same device, from which that device's user can accept the connection request.

Bypassing user approval

Once the user approves a network to connect to in response to a request from a specific app, the device stores the approval for the particular access point. If the app makes a specific request to connect to that access point again, the device will skip the user approval phase and automatically connect to the network. If the user chooses to forget the network while connected to a network requested by the API, then this stored approval for that combination of app and network is removed, and any future request from the app will need to be approved by the user again. If the app makes a non-specific (such as with an SSID or BSSID pattern) request, then the user will need to approve the request.

Code sample

The following code sample shows how to connect to an open network with a SSID prefix of "test" and a BSSID OUI of "10:03:23":

KOTLINJAVA

final NetworkSpecifier specifier =
  new WifiNetworkSpecifier.Builder()
  .setSsidPattern(new PatternMatcher("test", PatterMatcher.PATTERN_PREFIX))
  .setBssidPattern(MacAddress.fromString("10:03:23:00:00:00"), MacAddress.fromString("ff:ff:ff:00:00:00"))
  .build();

final NetworkRequest request =
  new NetworkRequest.Builder()
  .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
  .removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
  .setNetworkSpecifier(specifier)
  .build();

final ConnectivityManager connectivityManager = (ConnectivityManager)
  context.getSystemService(Context.CONNECTIVITY_SERVICE);

final NetworkCallback networkCallback = new NetworkCallback() {
  ...
  @Override
  void onAvailable(...) {
      // do success processing here..
  }

  @Override
  void onUnavailable(...) {
      // do failure processing here..
  }
  ...
};
connectivityManager.requestNetwork(request, networkCallback);
...
// Release the request when done.
connectivityManager.unregisterNetworkCallback(networkCallback);

 

Wi-Fi network suggestion API

Android Q adds support for your app to add network credentials for a device to auto-connect to a Wi-Fi access point. You can supply suggestions for which network to connect to using WifiNetworkSuggestion. The platform ultimately chooses which access point to accept based on the input from your app and others.

The following code sample shows how to provide credentials for one open, one WPA2, and one WPA3 network:

KOTLINJAVA

final WifiNetworkSuggestion suggestion1 =
  new WifiNetworkSuggestion.Builder()
  .setSsid("test111111")
  .setIsAppInteractionRequired() // Optional (Needs location permission)
  .build()

final WifiNetworkSuggestion suggestion2 =
  new WifiNetworkSuggestion.Builder()
  .setSsid("test222222")
  .setWpa2Passphrase("test123456")
  .setIsAppInteractionRequired() // Optional (Needs location permission)
  .build()

final WifiNetworkSuggestion suggestion3 =
  new WifiNetworkSuggestion.Builder()
  .setSsid("test333333")
  .setWpa3Passphrase("test6789")
  .setIsAppInteractionRequired() // Optional (Needs location permission)
  .build()

final List suggestionsList =
  new ArrayList {{
    add(suggestion1);
    add(suggestion2);
    add(suggestion3);
  }};

final WifiManager wifiManager =
  (WifiManager) context.getSystemService(Context.WIFI_SERVICE);

final int status = wifiManager.addNetworkSuggestions(suggestionsList);
if (status != WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS) {
// do error handling here…
}

// Optional (Wait for post connection broadcast to one of your suggestions)
final IntentFilter intentFilter =
  new IntentFilter(WifiManager.ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION);

final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
  @Override
  public void onReceive(Context context, Intent intent) {
    if (!intent.getAction().equals(
      WifiManager.ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION)) {
      return;
    }
    // do post connect processing here..
  }
};
context.registerReceiver(broadcastReceiver, intentFilter);

 

The suggestions from the app must be approved by the user before the platform initiates a connection to them. This approval is provided by the user in response to a notification the first time the platform finds a network matching one of the suggestions from the app in scan results. When the platform connects to one of the network suggestions, the settings will show text that attributes the network connection to the corresponding suggester app.

Improvements to Wi-Fi high-performance and low-latency modes

Android Q allows you to provide a hint to the underlying modem to minimize latency.

Android Q extends the Wi-Fi lock API to effectively support high-performance mode and low-latency mode. Wi-Fi power save is disabled for high-performance and low-latency mode, and further latency optimization may be enabled in low-latency mode, depending on modem support.

Low-latency mode is only enabled when the application acquiring the lock is running in the foreground and the screen is on. The low-latency mode is especially helpful for real-time mobile gaming applications.

Specialized lookups in DNS resolver

Android Q adds native support for both DNS over TLS and for specialized DNS lookups. Previously, platform DNS resolver supported type A resolutions, which would resolve an IP address against a domain name with no specifics about services offered at that IP. With this update, the SRV & NAPTR lookups are now also supported.

Android Q provides developers both standard cleartext lookups and a DNS-over-TLS mode.

Wi-Fi Easy Connect

Android Q enables you to use Easy Connect to provision Wi-Fi credentials to a peer device, as a replacement of WPS which has been deprecated. Apps can integrate Easy Connect into their setup and provisioning flow by using theACTION_PROCESS_WIFI_EASY_CONNECT_URI intent. This intent requires a URI. The calling app can retrieve the URI through various methods, including scanning a QR code from a sticker or display, or through scanning Bluetooth LE or NFC advertisements.

Once the URI is available, you can provision the peer device’s Wi-Fi credentials with the ACTION_PROCESS_WIFI_EASY_CONNECT_URI intent. This allows the user to select a Wi-Fi network to share and securely transfers the credentials.

Easy Connect does not require Location or Wi-Fi permissions.

Note: Before using this intent, the app must verify that Easy Connect is supported on the device by callingWifiManager.isEasyConnectSupported().

Wi-Fi Direct connection API

The WifiP2pConfig and WifiP2pManager API classes have updates in Android Q to support fast connection establishment capabilities to Wi-Fi Direct using predetermined information. This information is shared via a side channel, such as Bluetooth or NFC.

The following code sample shows how to create a group using predetermined information:

KOTLINJAVA

WifiP2pManager manager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);
Channel channel = manager.initialize(this, getMainLooper(), null);

// prefer 5G band for this group
WifiP2pConfig config = new WifiP2pConfig.Builder()
.setNetworkName("networkName")
.setPassphrase("passphrase")
.enablePersistentMode(false)
.setGroupOperatingBand(WifiP2pConfig.GROUP_OWNER_BAND_5GHZ)
.build();

// create a non-persistent group on 5GHz
manager.createGroup(channel, config, null);

 

To join a group using credentials, replace manager.createGroup() with the following:

KOTLINJAVA

manager.connect(channel, config, null);

 

Bluetooth LE Connection Oriented Channels (CoC)

Android Q enables your app to use BLE CoC connections to transfer larger data streams between two BLE devices. This interface abstracts Bluetooth and connectivity mechanics to simplify implementation.

Telephony features

Android Q includes several improvements related to telephony.

Call quality improvements

Android Q adds the ability to collect information about the quality of ongoing IP Multimedia Subsystem (IMS) calls, including quality to and from the network, on devices that support the feature.

Call screening and caller ID

Android Q provides your app with a means to identify calls not in the user's address book as potential spam calls, and to have spam calls silently rejected on behalf of the user. Information about these blocked calls is logged as blocked calls in the call log to provide greater transparency to the user when they are missing calls. Use of this new API eliminates the requirement to obtain READ_CALL_LOG permissions from the user to provide call screening and caller ID functionality.

Call redirection service API

Android Q changes how call intents are handled. The NEW_OUTGOING_CALL broadcast is deprecated and is replaced with the CallRedirectionService API. The CallRedirectionService API provides interfaces for you to modify outgoing calls made by the Android platform. For example, third-party apps might cancel calls and reroute them over VoIP.

Improvements in creating files on external storage

In addition to introducing the scoped storage privacy behavior change, Android Q provides more flexibility in writing files and introduces capabilities to help you influence where those files get saved on an external storage device.

Pending status for new media files

Android Q introduces the IS_PENDING flag, which gives your app exclusive access to a media file as it's written to disk.

The following code snippet shows how to use the IS_PENDING flag when creating a new image in your app:

KOTLINJAVA

ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.DISPLAY_NAME, "IMG1024.JPG");
values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
values.put(MediaStore.Images.Media.IS_PENDING, 1);

ContentResolver resolver = context.getContentResolver();
Uri collection = MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL);
Uri item = resolver.insert(collection, values);

try (ParcelFileDescriptor pfd = resolver.openFileDescriptor(item, "w", null)) {
    // Write data into the pending image.
} catch (IOException e) {
    e.printStackTrace();
}

// Now that we're finished, release the "pending" status, and allow other apps
// to view the image.
values.clear();
values.put(MediaStore.Images.Media.IS_PENDING, 0);
resolver.update(item, values, null, null);

 

Influence on storage location

Android Q introduces several capabilities to help you organize the files that your app contributes to external storage.

Directory hints

When your app contributes media on a device running Android Q, the media is organized based on its type by default. For example, new image files are placed in a "pictures" directory by default.

If your app is aware of a specific location where files should be stored, such as Pictures/MyVacationPictures, you can set MediaColumns.RELATIVE_PATH to provide the system a hint for where to store the newly-written files. Similarly, you can move files on disk during a call to update() by changing MediaColumns.RELATIVE_PATH orMediaColumns.DISPLAY_NAME.

Device selection

In Android 9 (API level 28) and lower, all files saved to external storage devices appear under a single volume called external. Android Q, on the other hand, gives each external storage device a unique volume name. This new naming system helps you efficiently organize and index content, and it gives you control over where new content is stored.

The primary shared storage device is always called VOLUME_EXTERNAL. You can discover other volumes by callingMediaStore.getAllVolumeNames().

To query, insert, update, or delete a specific volume, pass the volume name to any of the getContentUri() methods available in the MediaStore API, such as in the following code snippet:

// Publish an audio file onto a specific external storage device.
val values = ContentValues().apply {
    put(MediaStore.Audio.Media.RELATIVE_PATH, "Music/My Album/My Song")
    put(MediaStore.Audio.Media.DISPLAY_NAME, "My Song.mp3")
}

// Assumes that the storage device of interest is the 2nd one
// that your app recognizes.
val volumeNames = MediaStore.getAllVolumeNames(context)
val selectedVolumeName = volumeNames[1]
val collection = MediaStore.Audio.Media.getContentUri(selectedVolumeName)
val item = resolver.insert(collection, values)

 

Caution: The createAccessIntent() method from the StorageVolume class is deprecated in Android Q, so you shouldn't use this method to browse an external storage device. If you do, users running Android Q devices aren't able to view the files saved in external storage within your app.

Media and graphics

Android Q introduces the following new media and graphics features and APIs:

Audio playback capture

Android Q gives an app the ability to capture audio playback from other apps. For full information, see Playback capture.

Native MIDI API

The Android Native MIDI API (AMidi) gives application developers the ability to send and receive MIDI data with C/C++code, integrating more closely with their C/C++ audio/control logic and minimizing the need for JNI.

For more information, see Android Native MIDI API.

MediaCodecInfo improvements

There are new methods in MediaCodecInfo that reveal more information about a codec:

isSoftwareOnly()

Returns true if the codec runs in software only. Software codecs make no guarantees about rendering performance.

isHardwareAccelerated()

Returns true if a codec is accelerated by hardware.

isVendor()

Returns true if the codec is provided by the device vendor or false if provided by the Android platform.

isAlias()

MediaCodecList may contain additional entries for the same underlying codec using an alternate codec name/s (alias/es). This method returns true if the codec in this entry is an alias for another codec.

In addition, MediaCodec.getCanonicalName() returns the underlying codec name for codecs created via an alias.

Performance Points

performance point represents a codec's ability to render video at a specific height, width and frame rate. For example, the UHD_60 performance point represents Ultra High Definition video (3840x2160 pixels) rendered at 60 frames per second.

The method MediaCodecInfo.VideoCapabilities.getSupportedPerformancePoints() returns a list ofPerformancePoint entries that the codec can render or capture.

You can check whether a given PerformancePoint covers another by callingPerformancePoint.covers(PerformancePoint). For example, UHD_60.covers(UHD_50) returns true.

A list of performance points is provided for all hardware-accelerated codecs. This could be an empty list if the codec does not meet even the lowest standard performance point.

Note that devices which have been upgraded to Q without updating the vendor image will not have performance point data, because this data comes from the vendor HAL. In this case, getSupportedPerformancePoints() returns null.

ANGLE

With the release of Android Q, Android developers and partners have the option to run using ANGLE, a project in the Chrome organization that layers ES on top of Vulkan, instead of using the vendor-provided ES driver.

For details, see ANGLE.

Thermal API

When devices get too warm, they may throttle the CPU and/or GPU, and this can affect apps and games in unexpected ways. Apps using complex graphics, heavy computation, or sustained network activity are more likely to hit issues, and those can vary across devices based on chipset and core frequencies, levels of integration, and also device packaging and form factor.

Now in Android Q, apps and games can use a thermal API to monitor changes on the device and take action to maintain lower power usage to restore normal temperature. Apps register a listener in PowerManager, through which the system reports ongoing thermal status ranging from light and moderate to severe, critical, emergency, and shutdown.

When the device reports thermal stress, apps and games can help by backing off ongoing activities to reduce power usage on various ways. For example, streaming apps could reduce resolution/bit rate or network traffic, a camera app could disable flash or intensive image enhancement, a game could reduce frame rate or polygon tesselation, a media app could reduce speaker volume, and a maps app could turn off GPS.

The thermal API requires a new device HAL layer—it's currently supported on Pixel devices running Android Q and we’re working with our device-maker partners to bring broad support to the ecosystem as quickly as possible.

Camera and images

Android Q introduces the following new camera- and image-related features:

Monochrome camera support

Android 9 (API level 28) first introduced monochrome camera capability. Android Q adds several enhancements to monochrome camera support:

  • New Y8 stream format support to improve memory efficiency.
  • Support for monochrome raw DNG capture.
  • Introduction of MONO and NIR CFA enumerations to distinguish between regular monochrome camera and near infrared cameras.

You may use this feature to capture a native monochrome image. A logical multi-camera device may use a monochrome camera as a physical sub-camera to achieve better low-light image quality.

Dynamic Depth Format

Starting in Android Q, cameras can store the depth data for an image in a separate file, using a new schema called Dynamic Depth Format (DDF). Apps can request both the JPG image and its depth metadata, using that information to apply any blur they want in post-processing without modifying the original image data.

To read the specification for the new format, see Dynamic Depth Format.

High Efficiency Image File format

High Efficiency Image File (HEIF) format is a standard image and video format that introduces higher-quality encoding and smaller file size when compared to other file formats.

For more information about the file format, see HEIC.

Improvements in multi-camera

Android Q improves the fusing of multiple cameras into a single logical camera, a feature introduced in Android 9 (API level 28). The following were added to the Camera2 API:

Accessibility services API

Android Q introduces the following new accessibility service features and APIs:

AccessibilityNodeInfo entry key flag

In Android Q, AccessibilityNodeInfo has been enhanced with a new flag designating whether it represents a text entry key. You can access this flag using the method AccessibilityNodeInfo.isTextEntryKey().

Accessibility dialog spoken feedback

When an accessibility service requires the user to repeat the accessibility shortcut to start the service, the dialog can now be accompanied by a text-to-speech prompt if the service requests it.

Accessibility shortcut for physical keyboards

In Android Q, users can now trigger the accessibility shortcut on a physical keyboard by pressing Control+Alt+Z.

Soft keyboard controller enhancement

In Android Q, accessibility services can now request that the soft keyboard be displayed even when the device detects a hard keyboard attached. Users can override this behavior.

User-defined accessibility timeouts

Android Q introduces the API method AccessibilityManager.getRecommendedTimeoutMillis(), providing support for user-defined timeouts for interactive and non-interactive Accessibility UI elements. The return value is influenced by both user preferences and accessibility service APIs.

Autofill improvements

Android Q contains the following improvements to the autofill service.

Compatibility-related autofill requests

You can now use the FillRequest.FLAG_COMPATIBILITY_MODE_REQUEST flag to determine whether an autofill request was generated via compatibility mode.

Save username and password simultaneously

You can now support cases where an application uses multiple activities to display username, password, and other fields by using the SaveInfo.FLAG_DELAY_SAVE flag.

User interaction with the Save UI

You can now show and hide a password field in a save dialog by setting an action listener on the dialog and changing the visibility of the corresponding password remote view.

Support for updating datasets

Autofill can now update existing passwords. For example, if a user has already stored a password, and they save a new password, Autofill now prompts the user to update the existing password instead of saving a new one.

Field Classification improvements

Android Q contains the following improvements to the Field Classification API.

UserData.Builder constructor

The UserData.Builder constructor has changed to better align to the Builder pattern.

Allow a Value to be mapped to multiple types of Category IDs

When using UserData.Builder in Android Q, you can now map a value to multiple types of category IDs. In previous releases, an exception was thrown if a value was added more than once.

Improved support for credit card numbers

Field classification can now detect four-digit numbers as the last four digits of a credit card number.

Support for app-specific field classification

Android Q adds FillResponse.setUserData(), which allows you to set app-specific user data for the duration of the session. This helps the autofill service detect types for fields with app-specific content.

UI and system controls

Android Q provides the following user-interface improvements:

Support JVMTI PopFrame caps

Android Q adds support for the can_pop_frames capability in the Android JVMTI implementation. When debugging, this feature allows you to re-run functions after pausing at a breakpoint and adjusting locals, globals, or implementation of a function. For more information, see Oracle's Pop Frame reference page.

Surface control API

Android Q provides a SurfaceControl API for low-level access to the system-compositor (SurfaceFlinger). For most users, SurfaceView is the correct way to leverage the compositor. The SurfaceControl API can be useful in certain cases, for example:

  • Synchronization of multiple surfaces
  • Cross-process surface embedding
  • Lower-level lifetime management

The SurfaceControl API is available in both SDK and NDK bindings. The NDK implementation includes an API for manual exchange of buffers with the compositor. This provides an alternative for users who have run up against the limitations of BufferQueue.

WebView hung renderer detection

Android Q introduces a new WebViewRenderProcessClient abstract class, which apps can use to detect if a WebViewhas become unresponsive. To use this class:

  1. Define your own subclass and implement its onRenderProcessResponsive() andonRenderProcessUnresponsive() methods.
  2. Attach an instance of your WebViewRenderProcessClient to one or more WebView objects.
  3. If the WebView becomes unresponsive, the system calls the client's onRenderProcessUnresponsive() method, passing the WebView and WebViewRenderProcess. (If the WebView is single-process, the WebViewRenderProcess parameter is null.) Your app can take appropriate action, such as showing a dialog box to the user asking if they want to halt the rendering process.

If the WebView remains unresponsive, the system calls onRenderProcessUnresponsive() periodically (no more than once every five seconds), but takes no other action. If the WebView becomes responsive again, the system calls onRenderProcessResponsive() just once.

Settings panels

Android Q introduces Settings Panels, an API which allows apps to show settings to users in the context of their app. This prevents users from needing to go into Settings to change things like NFC or Mobile data in order to use the app.

Figure 1. The user tries to open a web page while the device is not connected to the network. Chrome pops up the Internet Connectivitysettings panel...

 

 

Figure 2. The user can turn on Wi-Fi and select a network without leaving the Chrome app.

For example, suppose a user opens a web browser while their device is in airplane mode. Prior to Android Q, the app could only display a generic message asking the user to open Settings to restore connectivity. With Android Q, the browser app can display an inline panel showing key connectivity settings such as airplane mode, Wi-Fi (including nearby networks), and mobile data. With this panel, users can restore connectivity without leaving the app.

To display a settings panel, fire an intent with the one of the new Settings.Panel actions:

KOTLINJAVA

Intent panelIntent = new Intent(Settings.Panel.settings_panel_type);
startActivityForResult(panelIntent);

 

settings_panel_type can be one of:

ACTION_INTERNET_CONNECTIVITY

Shows settings related to internet connectivity, such as Airplane mode, Wi-Fi, and Mobile Data.

ACTION_WIFI:

Shows Wi-Fi settings, but not the other connectivity settings. This is useful for apps that need a Wi-Fi connection to perform large uploads or downloads.

ACTION_NFC

Shows all settings related to near-field communication (NFC).

ACTION_VOLUME

Shows volume settings for all audio streams.

We are planning to introduce an AndroidX wrapper for this functionality. When called on devices running Android 9 (API level 28) or lower, the wrapper will open the most-appropriate page in the Settings app.

Sharing improvements

Android Q provides a number of improvements to sharing. For full information, see Sharing improvements in Android Q.

Dark theme

Android Q offers a new Dark theme that applies to both the Android system UI and apps running on the device. For full information, see Dark theme.

Kotlin

Android Q includes the following updates for Kotlin development.

Nullability annotations for libcore APIs

Android Q improves the coverage of nullability annotations in the SDK for libcore APIs. These annotations enable app developers who are using either Kotlin or Java nullability analysis in Android Studio to get nullness information when interacting with these APIs.

Normally, nullability contract violations in Kotlin result in compilation errors. To ensure compatibility with your existing code, any new annotations are limited to @RecentlyNullable and @RecentlyNonNull. This means that nullability violations result in warnings instead of errors.

In addition, any @RecentlyNullable or @RecentlyNonNull annotations that were added in Android 9 are changing to @Nullable and @NonNull, respectively. This means that nullability violations now lead to errors instead of warnings.

For more information about annotation changes, see Android Pie SDK is now more Kotlin-friendly on the Android Developers Blog.

NDK

Android Q includes the following NDK changes.

Improved debugging of file descriptor ownership

Android Q adds fdsan, which helps you find and fix file descriptor ownership issues more easily.

Bugs related to mishandling of file descriptor ownership, which tend to manifest as use-after-close and double-close, are analogous to the memory allocation use-after-free and double-free bugs, but tend to be much more difficult to diagnose and fix. fdsan attempts to detect and/or prevent file descriptor mismanagement by enforcing file descriptor ownership.

For more information about crashes related to these issues, see Error detected by fdsan. For more information about fdsan, see the Googlesource page on fdsan.

ELF TLS

Applications built using the NDK with a minimum API level 29 no longer need to use emutls, but can instead use ELF TLS. Dynamic and static linker support has been added to support the new method of handling thread-local variables.

For apps built for API level 28 and lower, improvements have been implemented for libgcc/compiler-rt to work around some emutls issues.

For more information, see Android changes for NDK developers.

Runtime

Android Q includes the following runtime change.

Mallinfo-based garbage collection triggering

When small platform Java objects reference huge objects in the C++ heap, the C++ objects can often be reclaimed only when the Java object is collected and, for example, finalized. In previous releases, the platform estimated the sizes of many C++ objects associated with Java objects. This estimation was not always accurate and occasionally resulted in greatly increased memory usage, as the platform failed to garbage collect when it should have.

In Q, the garbage collector (GC) tracks the total size of the heap allocated by system malloc(), ensuring that large malloc() allocations are always included in GC-triggering calculations. Apps interleaving large numbers of C++ allocations with Java execution might see an increase in garbage collection frequency as a result. Other apps might see a small decrease.

Testing and debugging

Android Q includes the following improvements for testing and debugging.

Improvements for on-device system tracing

You can now specify limits for the size and duration of a trace when you perform an on-device system trace. When you specify either value, the system performs a long trace, periodically copying the trace buffer to the destination file while the trace is recorded. The trace completes when the size or duration limits that you specified are reached.

Use these additional parameters to test different use cases than you would test with a standard trace. For example, you might be diagnosing a performance bug that only occurs after your app has been running for a long period of time. In this case, you could record a long trace over an entire day, and then analyze the CPU scheduler, disk activity, app threads, and other data in the report to help you determine the cause of the bug.

TextClassifier improvements

Android Q provides additional text classification functionality in the TextClassifier interface.

Language detection

TextClassifier now features the detectLanguage() method. This method works similarly to existing classification methods, receiving a TextLanguage.Request object and returning a TextLanguage object.

The new TextLanguage object consists of a list of ordered pairs. Each pair contains a locale and a corresponding confidence score for the requested text sample.

Suggested conversation actions

TextClassifier now features the suggestConversationActions() method. This method works similarly to existing classification methods, receiving a ConversationActions.Request object and returning a ConversationActionsobject.

The new ConversationActions object consists of a list of ConversationAction objects. Each ConversationAction object includes a potential suggested action and its confidence score.

Smart replies/actions in notifications

Android 9 introduced the ability to display suggested replies within a notification. Beginning in Android Q, notifications can also include suggested intent-based actions. Furthermore, the system can now generate these suggestions automatically. Apps can still provide their own suggestions, or opt out of system-generated suggestions.

The API used to generate these replies is part of TextClassifier, and has also been directly exposed to developers in Android Q. Please read the section on TextClassifier improvements for more information.

If your app provides its own suggestions, the platform doesn't generate any automatic suggestions. If you don't want your app's notifications to display any suggested replies or actions, you can opt out of system-generated replies and actions by using setAllowGeneratedReplies() and setAllowSystemGeneratedContextualActions().

 

Building apps for Foldables

Android Q adds more support for foldable devices and different folding patterns.

Unfolding the device to provide a larger screen can have a positive impact on users:

  • A larger screen usually means a more immersive experience.
  • With multi-windows the user can perform multiple tasks at the same time.

Folding and unfolding can change the screen size, density, or ratio. This is not a new problem in Android development. It already happens in these non-folding cases:

  • Phones: switching between portrait and landscape mode.
  • Chrome OS running in desktop mode: resizing Android apps.
  • Devices with multiple or additional screens.

This page describes best practices to make sure your app works well with foldable form factors.

You may also want to read the Android Q preview summary of changes that involve foldable support.

App continuity

When running on a foldable device, an app can transition from one screen to another automatically. To provide a great user experience, it is very important that the current task continue seamlessly after the transition. The app should resume in the same state and location. Note that foldable devices can fold in many ways, such as in or out:

Since the system will trigger a configuration change during the transition, an app should save the UI state and support configuration changes gracefully.

Make your app resizable

You should ensure that your app works in multi-window mode and with dynamic resizing. Do this by setting resizeableActivity=true. This provides maximum compatibility with whatever form factors and environments your app might encounter (like foldables, desktop mode, or freeform windows). Test your app's behavior in split-screen or with a Foldable emulator.

If your app sets resizeableActivity=false, this tells the platform it doesn't support multi-window. The system may still resize your app or put it in multi- window mode, but compatibility is implemented by applying the same configuration to all the components in the app (including all of its Activities, Services, and more). In some cases, major changes (like a display size change) might restart the process rather than change the configuration.

For example, the activity below has set resizableActivity=false along with a maxAspectRatio. When the device is unfolded, the activity configuration, size, and aspect ratio are maintained by putting the app in compatibility mode.

If you do not set resizeableActivity, or set it to true, the system assumes the app fully supports multi-window and is resizable.

Note that some OEMs might implement a feature that adds a small restart icon on the screen each time the activity's display area changes. This gives the user the chance to restart the activity in the new configuration.

New screen ratios

Android Q supports a wider range of aspect ratios. With Foldables, form factors can vary from super high long and thin screens (such as 21:9 for a folded device) all the way down to 1:1.

To be compatible with as many devices as possible, you should test your apps for as many of these screen ratios as you can:

If you cannot support some of those ratios, you can use the maxAspectRatio (as before), as well as the new Android QminAspectRatio to indicate the highest and lowest ratios your app can handle. In cases with screens that exceed these limits, your app might be put in compatibility mode.

When there are five icons in the bottom navigation view devices running Android Q are guaranteed a minimum touch target size of 2 inches. See the Compatibility Definition Document.

Multi-window

Being able to run multiple windows is one of the benefits of large screens. In the past, having two apps side by side was common in some devices. The technology has improved to the point where three or more apps can run on the screen at the same time, and also share content between themselves:

If an app doesn't properly support multi-window, it can set resizeableActivity=false. For more information, read the Multi-Window guide.

With multi-window becoming more common, consider supporting drag and drop in your app.

Multi-resume

When running on Android 9.0 and earlier, only the app in focus is in the resumed state. Any other visible Activities are paused. This can create problems if apps close resources or stop playing content when they pause.

In Android Q, this behavior is changing so that all Activities remain in the resumed state when the device is in multi-window mode. This is called multi-resume. Note that an activity can be paused if there’s a transparent activity on top, or the Activity is not focusable (e.g. picture-in-picture mode). It’s also possible that no activities have focus at a given time, for example, if the Notification drawer is opened. OnStop keeps working as usual. It will be called any time the activity is taken off the screen.

Multi-resume is also available on select devices running Android 9.0. To opt-in to multi-resume on those devices, you can add the following manifest meta-data:

<meta-data
    android:name="android.allow_multiple_resumed_activities" android:value="true" />

 

To verify that a given device supports this manifest meta-data, refer to the device specifications.

Exclusive resources access

To help support the multi-resume feature, there’s a new lifecycle callback,Activity#onTopResumedActivityChanged().

This method is invoked when an activity gains or loses the top resumed Activity position. This is important to know when an activity uses a shared single-user resource, such as the microphone or camera.

protected void onTopResumedActivityChanged(boolean topResumed) {
    if (topResumed) {
        // Top resumed activity
        // Can be a signal to re-acquire exclusive resources
    } else {
        // No longer the top resumed activity
    }
}

 

Note that an app can lose resources for several other reasons, such as removing a shared piece of hardware.

In any case, an app should gracefully handle resource loss events and state changes that affect available resources.

For apps that use a camera it’s recommended to use the new Android Q methodCameraManager.AvailabilityCallback#onCameraAccessPrioritiesChanged() as a hint that it might be a good time to try to get access to the camera.

Remember that resizeableActivity=false is not a guarantee of exclusive camera access, since other camera-using apps can be opened on other displays.

Camera in multi-window mode.

 

Your app does not necessary have to release the camera when it loses focus. For example, you might want to continue camera preview while the user interacts with the newly focused topmost resumed app. It's fine for your app to keep running the camera when it’s not the topmost resumed app but it has to handle the disconnect case properly. When the topmost resumed app wants to use the camera it can open it, and your app will lose access. Your app can re-open the camera when it gets the focus back.

After an app receives a CameraDevice.StateCallback#onDisconnected() callback, subsequent calls on the camera device will throw a CameraAccessException.

Multi-display

In the future, you might see foldable phones that support more than one screen or display at a time. Handling this configuration is similar to how developers work with projected screens today on Chrome OS.

Android Q supports activities on secondary displays. If an activity is running on a device with multiple displays, users can move the activity from one display to another. Multi-resume applies to multi-screen scenarios as well. Several activities can receive user input at the same time.

An app can specify which display it should run on when it launches, or when it creates another activity. This behavior depends on the activity launch mode defined in the manifest file, and in the intent flags and options set by the entity launching the activity. See ActivityOptions for more details.

As with folding transitions, when an activity moves to a secondary display, it can go through a context update, window resize, and configuration and resource changes. If the activity handles the configuration change, it will be notified inonConfigurationChanged(). If not, it will be relaunched.

An activity should check the current display in onCreate and onConfigurationChanged if handled. Make sure to update the resources and layouts when the display changes.

If the selected launch mode for an activity allows multiple instances, remember that launching on a secondary screen can create a new instance of the activity. Both activities will be resumed at the same time.

Multiple instances of an Activity in multiple displays.

 

You may also want to read about the existing multi-display APIs that were introduced in Android 8.0.

Display cutouts

Foldable devices might have different cutout geometry when folded and unfolded. To avoid cutout issues read Best practices for display cutout.

Activity vs application context

Using the right context is crucial in multi-display. When accessing resources, the activity context (which is displayed) is different from the application context (which is not).

The activity context contains information about the display and is always adjusted for the display area on which it appears. To get the current display metrics and resources use the activity context. This also affects some system APIs that use information from the context (like Toast).

The activity window configuration and parent display define resources and context. To get the current display use:

val activityDisplay = activity.windowManager.defaultDisplay

 

To get the current activity window metrics use:

val windowMetrics = DisplayMetrics()
activityDisplay.getMetrics(windowMetrics)

 

or:

val windowMetrics = activity.resources.displayMetrics

 

Using secondary screens

You can get the available displays from the DisplayManager system service:

val dm = getSystemService(Context.DISPLAY_SERVICE) as DisplayManager
val displays = dm.displays

 

Use the Display class to get information about a particular display:

  • Display metrics give you information about the size, resolution and density of the screen.
  • Check the flags to see if a display is secure.

To determine if an activity can launch on a display:

activityManager.isActivityStartAllowedOnDisplay(context, displayId, intent)

 

And to launch an activity on a display:

val options = ActivityOptions.makeBasic()
options.launchDisplayId = targetDisplay.displayId
startActivity(intent, options.toBundle())

 

Multi-display support

Android already supports Software keyboards, Wallpapers, and Launchers.

Software keyboard

A keyboard can be shown on a secondary screen if the display is configured to support system decorations. The input method editor will automatically show up if a text field requests input on that display.

Keyboard on a secondary display.

 

Wallpaper

In Android Q, secondary screens can have wallpaper. The framework creates a separate instance ofWallpaperService.Engine for each display. Make sure the surface of each engine is drawn independently. Developers can load assets using the display context in WallpaperService.Engine#getDisplayContext(). Also, make sure yourWallpaperInfo.xml file sets android:supportsMultipleDisplays="true".

Wallpapers on phone and secondary display.

 

Launchers

There is a new intent filter category SECONDARY_HOME to provide a dedicated activity for secondary screens. Instances of this activity are used on all displays that support system decorations, one per each display.

<activity>
    ...
    <intent-filter>
        <category android:name="android.intent.category.SECONDARY_HOME" />
        ...
    </intent-filter>
</activity>

 

The activity must have a launch mode that does not prevent multiple instances and can adapt to different screen sizes. The launch mode cannot be singleInstance or singleTask.

As example, the AOSP implementation of Launcher3 supports a SECONDARY_HOME activity.

Material Design Launcher on phone.

 

Material Design Launcher on a secondary display.

 

Testing

To get your app ready for Foldables, you should test how your app reacts to:

  • Configuration changes
  • Multi-window and multi-resume
  • Resizing and new screen ratios

Foldable emulators

The AOSP emulator supports folding devices. This allows developers to test their apps in folding scenarios.

7.3’’ foldable emulator

7.3"DisplayResolutionLogical Display
 SizeXYdensityDpiSize
Unfolded7.315362152420large
Folded4.68401960420normal

8’’ foldable emulator

8"DisplayResolutionLogical Display
 SizeXYdensityDpiSize
Unfolded8.0322002480420large
Folded6.6211482480420normal

AOSP folding emulator.

 

Multiple foldable emulators are available in Android Studio 3.5:

Android Studio 3.5 foldable emulators.

 

Testing multi-display

The new Dev Option called Force desktop mode lets the developer turn on system decoration support on all secondary displays and displays a mouse pointer there instead of on the default display. When used with Enable Freeform windowsForce desktop simulates a desktop experience with multi-window and the ability to resize windows.

On Pixel you can try it using Simulated display. Or, if you have a device that supports HDMI or displayport-over-USB-C, you can test it using a wired connection.

Simulated display.

 

Sharing Improvements

Android Q provides a number of new features related to sharing.

Sharing Shortcuts API

The ShareSheet has changed in Android Q. The Direct Share APIs have been replaced with the new Sharing Shortcuts API. The existing Direct Share mechanism will continue to work, but have a lower priority than any apps that use the new API.

Instead of retrieving results reactively on demand, the Sharing Shortcuts API lets apps publish direct share targets in advance. This is how the ShortcutManager works. Since the two APIs are similar, we have expanded the ShortcutInfo API to make using both features easier. With the new API, you can directly assign categories or people to a share target. The share targets persist in the system until the same app updates them or the app is uninstalled.

Sample Code: SharingShortcuts

Publish direct share targets

Currently only dynamic shortcuts are supported for publishing direct share targets. Follow these steps to publish direct share targets using the new API:

  1. Declare share-target elements in an app's XML resource file. For details, see Declare a share target below.
  2. Publish dynamic shortcuts with matching categories to the declared share-targets. Shortcuts can be added, accessed, updated, and removed using the ShortcutManager or ShortcutManagerCompat in AndroidX. Using the compatibility library in AndroidX is the preferred method since it provides backwards compatibility on older Android versions.

The DirectShare API

ShortcutInfo.Builder includes new and enhanced methods that provide additional info about the share target:

setCategories()

This is not a new method, but now categories are also used to filter shortcuts that can handle share intents or actions. See Declare a share target below for details. This field is required for shortcuts that are meant to be used as share targets.

setLongLived()

Specifies whether or not a shortcut is valid when it has been unpublished or made invisible by the app (as a dynamic or pinned shortcut). If a shortcut is long lived, it can be cached by various system services even after if has been unpublished as a dynamic shortcut.

setPerson()setPersons()

Associates one or more Person objects with the shortcut. This can be used to better understand user behavior across different apps, and to help potential prediction services in the framework provide better suggestions in a ShareSheet. Adding Person info to a shortcut is optional, but strongly recommended if the share target can be associated with a person. Note that som share targets, such as cloud, cannot be associated with a person.

For a typical messaging app, a separate share target (shortcut) should be published for each contact, and the Person field should contain the contact's info. If the target can be associated with multiple people (like a group chat), add multiple Persons to a single share target.

Declare a share target

Share targets must be declared in the app's resource file, similar to static shortcuts definitions. Add share target definitions inside the <shortcuts> root element in the resource file, along with other static shortcut definitions. Each<share-target> element contains information about the shared data type, matching categories, and the target class that will handle the share intent. The XML code looks something like this:

<shortcuts xmlns:android="http://schemas.android.com/apk/res/android">
  <share-target android:targetClass="com.example.android.sharingshortcuts.SendMessageActivity">
    <data android:mimeType="text/plain" />
    <category android:name="com.example.android.sharingshortcuts.category.TEXT_SHARE_TARGET" />
  </share-target>
</shortcuts>

 

The data element in a share target is similar to the data specification in an intent filter. Each share target can have multiple categories, which are only used to match an app's published shortcuts with its share target definitions. Categories can have any arbitrary app-defined values.

In case the user selects a direct share target (shortcut) in ShareSheet that matches with the example target-share above, the app will get the following share intent:

Action: Intent.ACTION_SEND
ComponentName: {com.example.android.sharingshortcuts /
                com.example.android.sharingshortcuts.SendMessageActivity}
Data: Uri to the shared content
EXTRA_SHORTCUT_ID: <ID of the selected shortcut>

 

If the user opens the share target from the launcher shortcuts, the app will get the intent that was created when adding the sharing shortcut to the ShortcutManagerCompat. Since it's a different intent, Intent.EXTRA_SHORTCUT_ID won't be available, and you will have to pass the ID manually if you need it.

DirectShare in AndroidX

ShortcutManagerCompat is a new AndroidX API that provides backwards compatibility with the old DirectShare API. This is the preferred way to publish share targets.

To be able to work with the compatibility library, the app’s manifest must contain the meta-data chooser-target-service and intent-filters set. See the current Direct Share API.

This service is already declared in the compatibility library, so the user does not need to declare the service in the app’s manifest. However, the link from the share activity to the service must be taken into account as a chooser target provider.

In the following example, the implementation of ChooserTargetService isandroidx.core.content.pm.ChooserTargetServiceCompat, which is already defined in AndroidX:

<activity
    android:name=".SendMessageActivity"
    android:label="@string/app_name"
    android:theme="@style/SharingShortcutsDialogTheme">
    <!-- This activity can respond to Intents of type SEND -->
    <intent-filter>
        <action android:name="android.intent.action.SEND" />
        <category android:name="android.intent.category.DEFAULT" />
        <data android:mimeType="text/plain" />
    </intent-filter>
    <!-- Only needed if you import the sharetarget AndroidX library that
         provides backwards compatibility with the old DirectShare API.
         The activity that receives the Sharing Shortcut intent needs to be
         taken into account with this chooser target provider. -->
    <meta-data
        android:name="android.service.chooser.chooser_target_service"
        android:value="androidx.sharetarget.ChooserTargetServiceCompat" />
</activity>

 

Content preview

When an app shares content, it can show an optional preview of the content in the Sharesheet UI.

The preview can have a title, an image, or both.

Intent sendIntent = new Intent(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, "Hello!");

// (Optional) Here we're setting the title of the content
sendIntent.putExtra(Intent.EXTRA_TITLE, "Send message");

// (Optional) Here we're passing a content URI to an image to be displayed
sendIntent.setClipData(contentUri);
sendIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

// Start the chooser to show the Sharesheet
startActivity(Intent.createChooser(sendIntent, null));

 

The image content URI should be provided from a FileProvider, usually from a configured <cache-path>. See Sharing files.

A complete example can be seen in the sample app.

FAQ

What are the main differences between the new API and the old DirectShare API?

The new API uses a push model, versus the pull model used in the old DirectShare API. This makes the process of retrieving direct share targets much faster when preparing the ShareSheet. From the app developer's point of view, when using the new API, the app needs to provide the list of direct share targets ahead of time, and potentially update the list of shortcuts every time the internal state of the app changes (for example, if a new contact is added in a messaging app).

What happens if I don't migrate to use the new APIs?

On Android Q and higher, ShareSheet will put higher priority on share targets which are provided via ShortcutManager (the new API). So your published share targets may get buried under other apps' share targets and potentially never appear when sharing.

Can I use both old and new DirectShare APIs in my app for backwards compatibility?

Don't do it! Instead, use the provided support library APIs (ShortcutManagerCompat). Mixing the two sets of APIs may result in unwanted/unexpected behavior when retrieving the share targets.

How are published shortcuts for share targets different from launcher shortcuts (the typical usage of shortcuts when long pressing on app icons in launcher)?

Any shortcuts published for a "share target" purpose, is also a launcher shortcut, and will be shown in the menu when long pressing your app's icon. The maximum shortcut count limit per activity also applies to the total number of shortcuts an app is publishing (share targets and legacy launcher shortcuts combined).

 

Bubbles

Bubbles are a new preview feature in Android Q, which let users easily multi-task from anywhere on their device. They are designed to be an alternative to using SYSTEM_ALERT_WINDOW and are available for developer use and experimentation in Android Q.

Note: Bubbles are currently enabled for all users in the Q developer previews. In the final release, Bubbles will be available for developer use only.

Bubbles are built into the Notification system. They float on top of other app content and follow the user wherever they go. Bubbles can be expanded to reveal app functionality and information, and can be collapsed when not being used.

When the device is locked or the always-on-display is active, bubbles appear just as a notification normally would.

Bubbles are an opt-out feature. When an app presents its first bubble, a permission dialog is shown that offers two choices:

  • Block all bubbles from your app - notifications are not blocked, but they will never appear as bubbles
  • Allow all bubbles from your app - all notifications sent with BubbleMetaDatawill appear as bubbles

The Bubble API

Bubbles are created via the Notification API, you send your notification as normal. If you want it to bubble you need to attach some extra data to it.

The expanded view of a bubble is created from an activity that you choose. The Activity needs to be configured to display properly as a bubble. The activity must be resizeableembedded, and always launch in document UI mode. If it lacks any of these requirements it will display as a notification instead.

The following code demonstrates how to implement a simple bubble:

<activity
  android:name=".bubbles.BubbleActivity"
  android:theme="@style/AppTheme.NoActionBar"
  android:label="@string/title_activity_bubble"
  android:allowEmbedded="true"
  android:documentLaunchMode="always"
  android:resizeableActivity="true"
/>

 

If your app shows multiple bubbles of the same type, like multiple chat conversations with different contacts, the activity must be able to launch multiple instances. Set documentLaunchMode to "always".

To send a bubble, follow these steps:

KOTLINJAVA

// Create bubble intent
Intent target = new Intent(mContext, BubbleActivity.class);
PendingIntent bubbleIntent =
    PendingIntent.getActivity(mContext, 0, target, 0 /* flags */);

// Create bubble metadata
Notification.BubbleMetadata bubbleData =
    new Notification.BubbleMetadata.Builder()
        .setDesiredHeight(600)
        // Note: although you can set the icon is not displayed in Q Beta 2
        .setIcon(Icon.createWithResource(context, R.drawable.icon))
        .setIntent(bubbleIntent)
        .build();

// Create notification
Person chatBot = new Person.Builder()
        .setBot(true)
        .setName("BubbleBot")
        .setImportant(true)
        .build();

Notification.Builder builder =
    new Notification.Builder(mContext, CHANNEL_ID)
        .setContentIntent(contentIntent)
        .setSmallIcon(smallIcon)
        .setBubbleMetadata(bubbleData)
        .addPerson(chatBot);

 

Note: The first time you send the notification to display a bubble, it has to be in a notification channel with IMPORTANCE_HIGH. This is because bubbles are handled by the notification importance manager. If the system lowers your notification’s importance before the user has a chance to allow or block bubbles, the notification will not bubble.

If your app is in the foreground when a bubble is sent, importance is ignored and your bubble will always be shown (unless the user has blocked bubbles or notifications from your app).

Creating an expanded bubble

You can configure your bubble to present it in expanded state automatically. We recommend only using this functionality if the user performs an action that would result in a bubble, like tapping on a button to start a new chat. In this case, it also makes sense to suppress the initial notification sent when a bubble is created.

There are methods you can use to set flags that enable these behaviours: setAutoExpandBubble() andsetSuppressInitialNotification().

Note: Although you can set these flags in Android Q Beta 2, they do not yet have any effect.

KOTLINJAVA

Notification.BubbleMetadata bubbleData =
    new Notification.BubbleMetadata.Builder()
        .setDesiredHeight(600)
        .setIntent(bubbleIntent)
        .setAutoExpandBubble(true)
        .setSuppressInitialNotification(true)
        .build();

 

Bubble content lifecycle

When a bubble is expanded, the content activity goes through the normal process lifecycle, resulting in the application becoming a foreground process (if not already).

When the bubble is collapsed or dismissed the activity will be destroyed. This may result in the process being cached and later killed, depending on whether the app has any other foreground components running.

When bubbles appear

To reduce the number of interruptions for the user, bubbles will appear only if one or more of these conditions are met:

If none of those are true, only the notification will be shown.

Note: This policy is not final, and may change before Android Q comes out of beta

Best practices

  • Bubbles take up screen real estate and cover other app content. You should only send a notification as a bubble if it is important enough such as ongoing communications, or if the user has explicitly requested a bubble for some content.
  • Note that the bubble can be disabled by the user. In that case, a bubble notification is shown as a normal notification. You should always make sure your bubble notification works as a normal notification as well.
  • Processes that are launched from a bubble (such as activities and dialogs) appear within the bubble container. This means a bubble can have a task stack. Things can get complicated if there is a lot of functionality or navigation within your bubble. We recommend keeping the functionality as specific and light-weight as possible.

 

Dark theme

Android Q offers a new Dark theme that applies to both the Android system UI and apps running on the device.

Dark theme has many benefits:

  • Can reduce power usage by a significant amount (depending on the device’s screen technology).
  • Improves visibility for users with low vision and those who are sensitive to bright light.
  • Makes it easier for anyone to use a device in a low-light environment.

In Android Q there are three ways to enable Dark theme:

  • A new system setting (Settings -> Display -> Theme) lets the user enable Dark theme.
  • A new Quick Settings tile lets the user quickly switch themes from the notification tray (once enabled).
  • On Pixel devices, the Battery Saver mode also enables Dark theme at the same time. Other OEMs may or may not support this behavior.

Supporting Dark theme in your app

In order to support Dark theme, you must set your app's theme (usually found in res/values/styles.xml) to inherit from a DayNight theme:

<style name="AppTheme" parent="Theme.AppCompat.DayNight">

 

You can also use MaterialComponents' dark theming:

<style name="AppTheme" parent="Theme.MaterialComponents.DayNight">

 

This ties the app's main theme to the system-controlled night mode flags and gives the app a default Dark theme (when it is enabled).

Themes and styles

Your themes and styles should avoid hard-coded colors or icons intended for use under a light theme. You should use theme attributes (preferred) or night-qualified resources instead.

Here are the two most important theme attributes to know about:

  • ?android:attr/textColorPrimary This is a general purpose text color. It is near-black in Light theme and near-white on Dark themes. It contains a disabled state.
  • ?attr/colorControlNormal A general-purpose icon color. It contains a disabled state.

We recommend using Material Design Components, since its color theming system (such as the theme attributes ?attr/colorSurface and ?attr/colorOnSurface) provides easy access to suitable colors. Of course, you can customize these attributes in your theme.

Changing themes in-app

You might want to allow users to change the app's theme while the app is running. Your app can let the user choose between themes.

When running on devices running Android 9 or earlier, the recommended theme options are:

  • Light
  • Dark
  • Set by Battery Saver (the recommended default option)

When running on Android Q, the recommended options are different, to allow the user to override the system default:

  • Light
  • Dark
  • System default (the recommended default option)

Note that if the user selects Light, then Battery Saver will not change that setting.

Each of the options map directly to one of the AppCompat.DayNight modes:

To switch the theme, call AppCompatDelegate.setDefaultNightMode().

Note: Starting with AppCompat v1.1.0-alpha05, setDefaultNightMode() does not automatically recreate any started activities.

Force Dark

Android Q provides Force Dark, a feature for developers to quickly implement a Dark theme without explicitly setting a DayNight theme, as described above.

Force Dark analyzes each view of your light-themed app, and applies a dark theme automatically before it is drawn to the screen. Some developers use a mix of Force Dark and native implementation to cut down on the amount of time needed to implement Dark theme.

Apps must opt-in to Force Dark by setting android:forceDarkAllowed="true" in the app’s theme. This attribute is set on all of the system and AndroidX provided light themes, such as Theme.Material.Light. When you use Force Dark, you should make sure to test your app thoroughly and exclude views as needed.

If your app uses a dark theme (such as Theme.Material), Force Dark will not be applied. Similarly, if your app's theme inherits from a DayNight theme, Force Dark will not be applied, due to the automatic theme switching.

Disabling Force Dark on a view

Force Dark can be controlled on specific views with the android:forceDarkAllowed layout attribute or with setForceDarkAllowed().

Best Practices

Notifications and Widgets

For UI surfaces that you display on the device but do not directly control, it is important to make sure that any views you use reflect the host app’s theme. Two good examples are notifications and launcher widgets.

Notifications

Use the system-provided notification templates (such as MessagingStyle). This means that the system is responsible for ensuring the correct view styling is applied.

Widgets and custom notification views

For launcher widgets, or if your app uses custom notification content views, it is important to make sure you test the content on both the Light and Dark themes.

Common pitfalls to look out for:

  • Assuming that the background color is always light
  • Hardcoding text colors
  • Setting a hardcoded background color, while using the default text color
  • Using a drawable icon which is a static color

In all of these cases, use appropriate theme attributes instead of hardcoded colors.

Launch screens

If your app has a custom launch screen, it may need to be modified so that it reflects the selected theme.

Remove any hardcoded colors, for example any background colors pointing may be white. Use the ?android:attr/colorBackground theme attribute instead.

Note that dark-themed android:windowBackground drawables only work on Android Q.

Configuration changes

When the app’s theme changes (either through the system setting or AppCompat) it triggers a uiMode configuration change. This means that Activities will be automatically recreated.

In some cases you might want an app to handle the configuration change. For example, you might want to delay a configuration change because a video is playing.

An app can handle the implementation of Dark theme itself by declaring that each Activity can handle the uiModeconfiguration change:

<activity
    android:name=".MyActivity"
    android:configChanges="uiMode" />

 

When an Activity declares it handles configuration changes, its onConfigurationChanged() method will be called when there is a theme change.

To check what the current theme is, apps can run code like this:

KOTLINJAVA

int currentNightMode = configuration.uiMode & Configuration.UI_MODE_NIGHT_MASK
switch (currentNightMode) {
    case Configuration.UI_MODE_NIGHT_NO:
        // Night mode is not active, we're using the light theme
        break;
    case Configuration.UI_MODE_NIGHT_YES:
        // Night mode is active, we're using dark theme
        break;
}

 

Playback Capture

Android Q contains a new AudioPlaybackCapture API. This API gives apps the ability to copy the audio being played by other apps. This feature is the analog of screen capture, but for audio. The primary use case is for streaming apps that want to capture the audio being played by games.

Note that the capture API does not affect the latency of the app whose audio is being captured.

Building a capture app

Prerequisites

For security and privacy, playback capture imposes some limitations. To be able to capture audio, an app must meet these requirements:

Capturing audio

To capture audio from another app, your app must build an AudioRecord object and add anAudioPlaybackCaptureConfiguration to it. Follow these steps:

  1. Call AudioPlaybackCaptureConfiguration.Builder.build() to build anAudioPlaybackCaptureConfiguration.
  2. Pass the configuration to the AudioRecord by calling setAudioPlaybackCaptureConfig.

Constraining capture by audio content

An app can limit which audio it can capture by using these methods:

Note that you cannot use the addMatchingUsage() and excludeUsage() methods together. You must choose one or the other. Likewise, you cannot use addMatchingUid() and excludeUid() at the same time.

Allowing playback capture

You can configure an app to prevent other apps from capturing its audio. The audio coming from an app can be captured only if the app meets these requirements:

Usage

The player producing the audio must set its usage to USAGE_MEDIAUSAGE_GAME, or USAGE_UNKNOWN.

Capture policy

The player's capture policy must be AudioAttributes.ALLOW_CAPTURE_BY_ALL, which allows other apps to capture playback. This can be done in a number of ways:

If these prerequisites are met, any audio produced by the player can be captured.

Note: The ability for an app's audio to be captured also depends on the app's targetSdkVersion.

  • By default, apps that target versions up to and including to Android 9.0 do not permit playback capture. To enable it, include android:allowAudioPlaybackCapture="true" in the app's manifest.xml file.
  • By default, apps that target Android Q or later allow their audio to be captured. To disable playback capture, includeandroid:allowAudioPlaybackCapture="false" in the app's manifest.xml file.

Disabling system capture

The protections permitting capture described above apply only to apps. Android system components ignore these constraints and can capture playback by default. Many of these components are customized by Android vendors and support features like accessibility and captioning. For this reason it is recommended that apps allow the system to capture their playback. In the rare case when you do not want the system to capture your app's playback, set the capture policy to ALLOW_CAPTURE_BY_NONE.

Setting policy at runtime

You can call AudioManager.setAllowedCapturePolicy() to change the capture policy while an app is running. If a MediaPlayer or AudioTrack is playing when you call the method, the audio is not affected. You must close and reopen the player or track for the policy change to take effect.

Policy = manifest + AudioManager + AudioAttributes

Since the capture policy can be specified in several places, it's important to understand how the effective policy is determined. The most restrictive capture policy is always applied. For example, an app whose manifest includes setAllowedCapturePolicy="false" will never permit non-system apps to capture its audio, even if AudioManager#setAllowedCapturePolicy is set to ALLOW_CAPTURE_BY_ALL. Similarly, if theAudioManager#setAllowedCapturePolicy is set to ALLOW_CAPTURE_BY_ALL and the manifest sets setAllowedCapturePolicy="true", but the media player's AudioAttributes were built withAudioAttributes.Builder#setAllowedCapturePolicy(ALLOW_CAPTURE_BY_SYSTEM), then this media player will not be capturable by non-system apps.

The table below summarizes the effect of the manifest attribute and the effective policy:

allowAudioPlaybackCaptureALLOW_CAPTURE_BY_ALLALLOW_CAPTURE_BY_SYSTEMALLOW_CAPTURE_BY_NONE
trueany appsystem onlyno capture
falsesystem onlysystem only

no capture

 

 

 

ANGLE

There are a number of OpenGL ES drivers supplied by the different hardware vendors on Android devices. This contributes to an inconsistent behavior on those drivers. It also means that bug fixes often do not propagate to all devices and helps lead to fragmentation of the OpenGL ES ecosystem.

With the release of Android Q, Android developers and partners have the option to run using ANGLE, a project in the Chrome organization that layers ES on top of Vulkan, instead of using the vendor-provided ES driver.

When ANGLE is available, developers and OEMs can decide whether or not a particular application should use ANGLE. Since a complete OpenGL driver will take time, Android Q introduces an opt-in option that lets developers make the shift gradually. ANGLE will be updated over time, introducing more OpenGL functionality, bug fixes and performance optimizations. Android Q introduces two new features to help you evaluate and choose ANGLE on a per-app basis:

  • To evaluate ANGLE at the developer level, Android Q includes a developer options setting that allows a developer to specify that a non-core application should run with ANGLE.

  • When Android Q is released, the ANGLE APK will include a configuration file that indicates what applications should or should not use ANGLE.

How to select ANGLE

The new ANGLE developer option can be used to get quick feedback on how ANGLE works with an installed application on a specific device. Follow these steps to run an app with ANGLE:

  1. Enable developer options.
  2. Open developer options and then select ANGLE Preferences.
  3. Select an app.
  4. Choose the driver for the app. There are three options:

    default

    Uses the driver determined from the ANGLE APK configuration file. Since the current APK doesn't opt anything in to ANGLE, this is the same as selecting "native".

    angle

    Uses ANGLE.

    native

    Uses the native OpenGL driver.

How to configure ANGLE

Android Q Beta 1 includes the ANGLE APK. The APK contains a configuration file that determines which applications will use ANGLE. Developers can override this default by selecting ANGLE in the developer options, as explained above.

The configuration file allows customization so that ANGLE can be enabled based on the application name, version, the device, Vulkan driver version, GPU vendor, and other factors.

Since the configuration file is part of the ANGLE APK, ANGLE can be used on any AOSP solution. In addition, the configuration rules can be updated whenever ANGLE is updated. Google will manage the configuration file based on ISV requests, partner feedback, customer issues, and test results.

Report an ANGLE issue

Developers can log issues on the ANGLE bug tracker.

 

What's new for Android in the enterprise

This page provides an overview of the new enterprise APIs, features, and behavior changes introduced in Android Q.

Work profiles for company-owned devices

Android Q introduces new provisioning and attestation features for company-owned devices that only require a work profile.

Improved provisioning tools for work profiles

It's now possible to provision work profiles on Android Q and later devices enrolled using QR code or Zero touch. During the provisioning of a company-owned device, a new intent extra allows device policy controller apps (DPCs) to initiate work profile or fully managed setup. After a work profile is created or full management is established, DPCs must launch policy compliance screens to enforce any initial policies.

Important: Existing DPC implementations that only support fully managed provisioning won't be affected by this feature—they'll continue to work on Android Q and later devices.

In your DPC’s manifest file, declare a new intent filter for GET_PROVISIONING_MODE in an activity and add the BIND_DEVICE_ADMIN permission to prevent arbitrary apps from starting the activity. For example:

<activity
    android:name=".GetProvisioningModeActivity"
    android:label="@string/app_name"
    android:permission="android.permission.BIND_DEVICE_ADMIN">
    <intent-filter>
        <action
            android:name="android.app.action.GET_PROVISIONING_MODE" />
        <category android:name="android.intent.category.DEFAULT"/>
    </intent-filter>
</activity>

 

During provisioning, the system launches the activity associated with the intent filter. The purpose of this activity is to specify a management mode (work profile or fully managed).

It may be useful to retrieve provisioning extras before determining the appropriate management mode for the device. The activity can call getIntent() to retrieve the following:

DPCs can also create a new result intent and add the following extras to it:

To set the management mode on the device, callputExtra(DevicePolicyManager.EXTRA_PROVISIONING_MODE,desiredProvisioningMode), where desiredProvisioningMode is:

  • Work profile: PROVISIONING_MODE_MANAGED_PROFILE
  • Fully managed: PROVISIONING_MODE_FULLY_MANAGED_DEVICE

Complete work profile or fully managed provisioning by sending provisioning details back to setup via setResult(RESULT_OK, Intent) and close all active screens with finish().

Note: To prevent failed provisioning, don't launch any activities or background services after returning to setup.

After provisioning is complete, a new Intent is available for DPCs to launch their compliance screens and enforce initial policy settings. On work profile devices, compliance screens are displayed in the work profile. Your DPC must ensure that its compliance screens are shown to users, even if a user escapes the setup flow.

In your DPC's manifest file, declare a new intent filter for ADMIN_POLICY_COMPLIANCE in an activity and add the BIND_DEVICE_ADMIN permission to prevent arbitrary apps from starting the activity. For example:

<activity
    android:name=".PolicyComplianceActivity"
    android:label="@string/app_name"
    android:permission="android.permission.BIND_DEVICE_ADMIN">
    <intent-filter>
        <action android:name="android.app.action.ADMIN_POLICY_COMPLIANCE" />
        <category android:name="android.intent.category.DEFAULT"/>
    </intent-filter>
</activity>

 

Your DPC must use this new Intent instead of listening for the ACTION_PROFILE_PROVISIONING_COMPLETE broadcast.

The activity associated with the intent filter can call getIntent() to retrieve theEXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE. After performing policy compliance, ADMIN_POLICY_COMPLIANCE must return setResult(RESULT_OK, Intent) and close all active screens with finish().

Fully managed devices return users to the homescreen. Work profile devices prompt users to add their personal account before returning them to the home screen.

Work-profile device-ID attestation

DPCs set as the admin of a work profile provisioned using zero-touch enrollment can now get secure-hardware-attested device IDs, such as an IMEI or manufacturer’s serial number. The device must include secure hardware (such as a trusted execution environment (TEE) or Secure Element (SE)) and support device-ID attestation and zero-touch enrollment.

The admin component of a work profile can call DevicePolicyManager.generateKeyPair(), passing one or more of ID_TYPE_SERIALID_TYPE_IMEI, or ID_TYPE_MEID for the idAttestationFlags argument.

To learn more about extracting and validating device IDs, see Verifying hardware-backed key pairs with Key Attestation.

Work profile improvements

New APIs are available for supporting cross-profile calendar visibility and device-wide blocking of app installations from unknown sources.

Access to work profile calendars

Apps running in the personal profile can show events from the work profile calendar. To query work profile calendar data, call the Calendar Provider APIs with the following content provider URIs:

When work profile calendars aren't available, queries return null. A work profile calendar isn't available when an IT admin blocks access or when the work profile is turned off. A person using the device can also turn off cross-profile calendars in Settings.

Apps running in the personal profile can show work events and redirect a person looking to edit a work event by navigating them to the same event in the work profile. When your app is installed in both the personal and work profiles, call startViewCalendarEventInManagedProfile(). Apps that want to support cross-profile calendar events must handle the ACTION_VIEW_MANAGED_PROFILE_CALENDAR_EVENT action. Prepare your user interface to show an existing event with data from the following intent extras:

Manage work profile calendar access

IT admins can block the work profile from sharing calendar information with the personal profile. To allow access to work profile calendars, the admin component of a work profile must call setCrossProfileCalendarPackages().

If this method is not called or if it’s called with an empty set, then no apps will be able to read work profile calendars. To grant read access to work profile calendars to all apps, pass null. To ensure that only a specific set of apps can read work profile calendars, pass the package names of those apps.

To get any app packages it previously set, the admin component of a work profile can callgetCrossProfileCalendarPackages().

Work profile, device-wide unknown sources

Apps downloaded from sources other than Google Play (or other trusted app stores) are called apps from unknown sources. In Android Q, admins of work profiles can now prevent any user or profile from installing apps from unknown sources anywhere on the device by adding the new user restriction DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY. After adding this restriction, however, a person using the device can still install apps using adb.

To prevent users from mistakenly installing apps from unknown sources, we recommend adding this user restriction because it doesn't require Google Play services to be installed. If you want to support older Android versions, you can set a managed configuration value for Google Play.

Limit permitted input devices to work profiles

When admins of work profiles call DevicePolicyManager.setPermittedInputMethods(), users are only restricted to the permitted input methods inside their work profile instead of the entire device, giving users full control over input methods on the personal side of their device.

Silently wipe work profiles

Added new WIPE_SILENTLY flag to DevicePolicyManager.wipeData(). If the flag is set, users won’t be notified after their work profile is wiped using wipeData().

New features for fully managed devices

Android Q introduces new features and APIs for fully managed devices, including manual system updates, extending QR-code and NFC provisioning to include the credentials for an EAP Wi-Fi network, and support for DNS over TLS.

Manual system update installation

In Android Q, admins of fully managed devices can install system updates via a system update file. Manual system updates allow IT admins to do the following:

  • Test an update on a small number of devices before installing them widely.
  • Avoid duplicate downloads on bandwidth-limited networks.
  • Stagger installations, or update devices only when they're not being used.

First, an IT admin sets a postponed system-update policy to delay automatic installation (if required). Next, a device's DPC calls installSystemUpdate() with the path to a device manufacturer's system update file. Pass an InstallSystemUpdateCallback object that the system can use to report errors that happen before the device restarts. If something goes wrong, the system calls onInstallUpdateError() with the error code.

After the device restarts, your DPC needs to confirm a successful installation using a version API, such asBuild.FINGERPRINT. If the update fails, report the failure to an IT admin.

EAP Wi-Fi provisioning

In Android Q, QR codes and NFC data used for device provisioning can now contain EAP config and credentials—including certificates. When a person scans a QR code or taps an NFC tag, the device automatically authenticates to a local Wi-Fi network using EAP and starts the provisioning process without any additional manual input.

To authenticate Wi-Fi using EAP, add an EXTRA_PROVISIONING_WIFI_SECURITY_TYPE extra with the value "EAP". To specify the EAP authentication, you can add the following provisioning extras to your intent:

Private DNS support

Organizations can use DNS over TLS (called Private DNS on Android devices) to avoid leaking DNS queries, including those of internal hostnames. Admin components of fully managed devices can control the Private DNS settings of the device. To set the Private DNS mode, call:

When your DPC calls either of these methods, the system returns PRIVATE_DNS_SET_NO_ERROR if the call was successful. Otherwise it returns an error.

To retrieve the Private DNS mode and host set on a device, call getGlobalPrivateDnsMode() and getGlobalPrivateDnsHost(). You can prevent users from changing private DNS settings by adding theDISALLOW_CONFIG_PRIVATE_DNS user restriction.

VPN lockdown mode exemption

VPN lockdown mode allows a DPC to block any network traffic that doesn't use the VPN. Admins of fully managed devices and work profiles can now exempt apps from lockdown mode. Exempted apps use a VPN by default, but automatically connect to other networks if the VPN isn't available. Exempted apps that are also explicitly denied access the VPN will only use other networks.

To exempt an app from lockdown mode, call the new DevicePolicyManager method setAlwaysOnVpnPackage() that now accepts a list of exempted app packages. Any app packages the DPC adds must be installed on the device when the method is called. If an app is uninstalled and reinstalled, the app must be exempted again. To get the apps previously exempted from lockdown mode, call getAlwaysOnVpnLockdownWhitelist().

To help admins of fully managed devices and work profiles get the lockdown mode status, Android Q adds theisAlwaysOnVpnLockdownEnabled() method.

New delegation scopes

Android Q extends the list of functions that a DPC can delegate to other, more specialized apps. Android groups the API methods needed for a task into scopes. To delegate a scope, call setDelegatedScopes() and pass one or more of the following scopes:

Android Q introduces the new class DelegatedAdminReceiver for delegate apps. The system uses this broadcast receiver to send DPC-like callbacks to delegate apps. Apps that have been delegated network activity logging and certificate selection should implement this class. To add this component to a delegate app, follow these steps:

  1. Add a subclass of DelegatedAdminReceiver to the delegate app.
  2. Declare the <receiver> in the app manifest, adding an intent-filter action for each callback. For example,ACTION_NETWORK_LOGS_AVAILABLE or ACTION_CHOOSE_PRIVATE_KEY_ALIAS.
  3. Protect the broadcast receiver with the BIND_DEVICE_ADMIN permission.

The following snippet shows the app manifest of a single delegate app that handles both network logging and certificate selection:

<receiver android:name=".app.DelegatedAdminReceiver"
        android:permission="android.permission.BIND_DELEGATED_ADMIN">
    <intent-filter>
        <action android:name="android.app.admin.action.NETWORK_LOGS_AVAILABLE">
        <action android:name="android.app.action.CHOOSE_PRIVATE_KEY_ALIAS">
    </intent-filter>
    </receiver>

 

Network activity logging

To help organizations detect and track malware, DPCs can log TCP connections and DNS lookups by the system. In Android Q, admins of fully managed devices can delegate network logging to a specialized app.

To retrieve network logs after the system makes a batch available, delegate apps should first subclassDelegatedAdminReceiver (described previously). In your subclass, implement the onNetworkLogsAvailable()callback by following the guidance in Retrieve logs.

Delegate apps can call the following DevicePolicyManger methods (passing null for the admin argument):

To avoid losing logs, DPC's shouldn't enable network logging if planning to delegate to another app. The delegate app should enable and collect network logs. After a DPC delegates network logging, it won't receive any further onNetworkLogsAvailable() callbacks.

To learn how to report network activity logging from a delegate app, read the developer's guide Network activity logging.

Certificate selection

In Android Q, admins of fully managed devices, work profiles, and secondary users can delegate certificate selection to a specialized app.

To select a certificate alias, delegate apps should first subclass DelegatedAdminReceiver (described previously). In your subclass, implement the onChoosePrivateKeyAlias() callback and return an alias for a preferred certificate or, to prompt the user to select a certificate, return null.

Deprecation of device admin policies

Android Q prevents DPCs from applying legacy device admin policies. We recommend customers and partners transition to fully managed devices or work profiles. The following policies throw a SecurityException when invoked by a device admin targeting Android Q:

Note: As a replacement for the keyguard and password policies listed above, apps should use the method described in Screen lock quality check.

Some applications use device admin for consumer device administration. For example, locking and wiping a lost device. To enable this, the following policies continue to be available:

For more information about these changes, read Device admin deprecation.

New features for apps

Apps targeting Android Q can query the screen lock complexity set on a device before displaying confidential data or launching critical features. Apps calling the KeyChain API benefit from behavior improvements, while new features are also available for VPN apps.

Screen lock quality check

Starting in Android Q, apps with critical features that require a screen lock can query a device or work profile’s screen lock complexity. Apps needing a stronger screen lock can direct the user to the system screen lock settings, allowing them to update their security settings.

To check screen lock quality:

To launch system screen lock settings, use ACTION_SET_NEW_PASSWORD with extra EXTRA_PASSWORD_COMPLEXITY—options that don't meet the complexity specified in the intent extra are grayed out. Users can choose from the available screen lock options or exit the screen.

Best practice: Display a message in your app before launching the system screen lock page. When your app resumes, call DevicePolicyManager.getPasswordComplexity() again. If a stronger screen lock is still required, restrict access rather than repeatedly prompting users to update their security settings.

HTTP proxy support in VPN apps

In Android Q, VPN apps can set an HTTP proxy for their VPN connection. To add an HTTP proxy, a VPN app must configure a ProxyInfo instance with a host and port, before calling VpnService.Builder.setHttpProxy(). The system and many networking libraries use this proxy setting but the system doesn't force apps to proxy HTTP requests.

For sample code that shows how to set an HTTP proxy, see the ToyVPN sample app.

VPN service modes

VPN apps can now discover if the service is running because of always-on Vpn and if lockdown mode is active. New methods added in Android Q can help you adjust your user interface. For example, you might disable your disconnect button when always-on VPN controls the lifecycle of your service.

VPN apps can call the following VpnService methods after connecting to the service and establishing the local interface:

  • isAlwaysOn() to find out if the system started the service because of always-on VPN
  • isLockdownEnabled() to find out if the system is blocking connections that don't use the VPN

The always-on status remains the same while your service is running but the lockdown-mode status might change.

Keychain improvements

Android Q introduces several improvements related to the KeyChain API.

When an app calls KeyChain.choosePrivateKeyAlias(), devices now filter the list of certificates a user can choose from based on the issuers and key algorithms specified in the call.

For example, when a TLS server sends a Certificate Request message as part of a TLS handshake and the browser callsKeyChain.choosePrivateKeyAlias(), the certificate selection prompt now only includes options that match the issuers parameter. If no matching options are available or there are no certificates installed on the device, then the selection prompt won’t be displayed to the user.

Additionally, KeyChain no longer requires a device to have a screen lock before keys or CA certificates can be imported.

Learn more

To learn about other changes that might affect your app, read the Android Q behavior changes pages (for apps targeting Q and for all apps).

 

Gestural Navigation

Android Q introduces an option for fully gestural system navigation. There are two things that app developers should do to prepare for this feature:

  • Extend app content from edge to edge.
  • Handle conflicting app gestures.

Edge-to-edge app content

In order to take advantage of the additional screen space made available by the floating navigation bar, you'll need to make some changes to your app.

Setting transparent system bars

You can do this by setting the following values in your theme:

<!-- values-29/themes.xml: -->

<style name="AppTheme" parent="...">
    <item name="android:navigationBarColor">@android:color/transparent</item>

    <!-- Optional, but recommended for full edge-to-edge rendering -->
    <item name="android:statusBarColor">@android:color/transparent</item>
</style>

 

Alternatively, you can do this dynamically by using Window.setNavigationBarColor() and Window.setStatusBarColor().

Setting UI visibility flag

To be able to lay out your view edge-to-edge, your app must tell the system that the app can handle such a view. You can accomplish this using View.setSystemUiVisibility() to set the following flags:

KOTLINJAVA

view.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
        | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);

 

Together, these flags tell the system that your app should be laid out fullscreen, and as if the navigation and status bars were not there. For additional full-screen events, you can also set SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN, which allows you to draw behind the status bar.

If you are using a view class such as CoordinatorLayout or DrawerLayout that automatically handles the status bar, the SYSTEM_UI_FLAG_LAYOUT_STABLE and SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN flags may already be set. Also, if you are using setSystemUiVisibility() to set other flags, such as SYSTEM_UI_FLAG_IMMERSIVE, you should be careful that those other flags do not overwrite the ones referenced above.

Even if your app uses an edge-to-edge view, the system still uses the WindowInsets API to indicate where the system bars are.

Consuming insets manually

If your app uses a custom view hierarchy, you may need to consume system window insets manually. You typically do this by implementing an OnApplyWindowInsetsListener interface:

KOTLINJAVA

view.setOnApplyWindowInsetsListener(new View.OnApplyWindowInsetsListener() {
    @Override
    public WindowInsets onApplyWindowInsets(View v, WindowInsets insets) {
        // 1. Move views on top edge down by insets.getSystemWindowInsetTop()
        // 2. Move views on bottom edge up by insets.getSystemWindowInsetBottom()
        // 3. Also check getSystemWindowInsetLeft/Right()
        //    (i.e landscape orientations)
        return insets.consumeSystemWindowInsets();
    }
});

 

WindowInsets provides regular visual insets for all system bars through getSystemWindowInsets(). In addition, Android Q adds the following methods to WindowInsets:

Handling conflicting app gestures

The gestural navigation model may conflict with gestures that were previously used by app developers. You may need to make adjustments to your app's user interface as a result.

Conflicts with Back gestures

The new system gesture for Back is an inward swipe from either the left or the right edge of the screen. This may interfere with app navigation elements in those areas. To maintain functionality of elements on the left and right edges of the screen, you'll need to opt out of the Back gesture selectively by indicating to the system which regions need to receive touch input. You can do this by passing a List<Rect> to the View.setSystemGestureExclusionRects() API introduced in Android Q. This method is also available in ViewCompat as of androidx.core:core:1.1.0-dev01.

For example:

KOTLINJAVA

List<Rect> exclusionRects;

public void onLayout(
        boolean changedCanvas, int left, int top, int right, int bottom) {
    // Update rect bounds and the exclusionRects list
    setSystemGestureExclusionRects(exclusionRects);
}

public void onDraw(Canvas canvas) {
    // Update rect bounds and the exclusionRects list
    setSystemGestureExclusionRects(exclusionRects);
}

 

Note: The DrawerLayout and SeekBar components support automatic opt-out behavior out of the box.

Conflicts with Home/Quick Switch gestures

The new system gestures for Home and Quick Switch both involve swipes at the bottom of the screen in the space previously occupied by the nav bar. Apps cannot opt out of these gestures, as they can with the Back gesture.

To mitigate this problem, Android Q introduces the WindowInsets.getMandatorySystemGestureInsets() API, which informs apps of the touch recognition thresholds.

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值