What’s New in Android 12 for Zebra Developers

Daniel Neamtu -


At the time of the release of Android 12 in 2021, we at Zebra Technologies made a decision to focus our resources on consolidating Android 11, delivering it to customers with newly released technologies such as 5G and Wi-Fi 6. The reasons that Zebra skipped A-12 centered on lack of customer demand for the features being implemented at the time. But for our developers and partners, it’s important to keep an eye on the most impactful changes made in Android 12, because all will be included on top of those of Android 13, which will be available for Zebra devices in 2023.

This article includes a panoramic view of what to expect from the changes introduced in Android 12 in a way that's friendly to our enterprise developers. For more in-depth information about the changes or topics introduced in A12/13, please refer to the Android Developer Portal.




Material You

With Android 12, Google released the next iteration of Material Design, marking the third major version since Material Design was introduced. It brings an updated design with newer interface elements from Google’s current Material Design specification, but with the introduction of many colors, different styles and components missing from previous versions.

There’s now a major emphasis on using all the available screen space, so with that we can expect a major support for Tablets and Folded Screens as well. Updated dependency is available for integration, and you can start experimenting with the latest goodies from this release by updating it to version 1.5.0 or higher:

  dependencies {
    // ...
    implementation 'com.google.android.material:material:1.5.0'

There’s also a handy Materials Migration Guide to help with the process.


Storage Changes

Google has introduced some changes related to storage management in general and how to further access media files from the external storage of the device. These changes are not associated with the ongoing Scoped Storage restrictions.

  • MediaDocumentsProvider can now retrieve a media URI that’s the equivalent to a given documents provider URI.
  • MANAGE_MEDIA permission was introduced. It will allow an app to perform media management operations without showing a confirmation dialog to the user for each operation.
  • Recordings, a new directory for voice recordings, has been introduced. The folder will act in the same way as other generic ones such as Music, Pictures etc.
  • Apps that have both the MANAGE_EXTERNAL_STORAGE and the QUERY_ALL_PACKAGES permissions such as for file management can now invoke a custom activity to manage another app's storage space, considering that the other app creates the required custom activity.


Secure LockScreen Notifications Actions

From Android 12 it is now possible to require the device to be unlocked for certain notification actions before being invoked by the user. If you want to use this capability, you will have to include the setAuthenticationRequired() method when creating the notification with the Notification.Builder. This way, all incoming notifications will have their content hidden until the user unlocks the device.

A possible example for such a use case could be a situation when a worker receives a notification containing sensitive data for a new order in a warehouse. The worker will have to unlock the device before seeing and taking any actions from the notification.


Splash Screen APIs

Splash Screens represented a common way for developers to load and perform specific operations before the actual start of the main activity for the user to start using the application.

Starting with Android 12, Google has changed how Splash Screens should be viewed, and it's now considered bad practice to create customized Splash Screen activities to perform preliminary tasks. This is mainly because heavy operations should not be performed before making the application ready for the user. That's because, all those tasks being performed at the beginning, are going to be repeated at every launch of application if it’s not in the background or if you haven’t adopted any strategies to skip some of them which are no longer required to be run.

Google’s recommendation is to try to have a “healthy” development style by using the resources responsibly, and load data to the user only when it is necessary. By doing so, the application will have a better structure and it will result in a much better user experience per general.

Now, Splash Screens are being shown by default for all installed applications and that also includes those that didn’t have one in previous Android versions. When the application is opened for the first time, a default Splash Screen activity is going to be shown with the app icon in the center of it.

To allow different customizations, a new Set of APIs has been introduced to be used to change the appearance of the screen with colors, styles and themes.

For enterprise-oriented applications, this change is not that impactful. But keep this in mind and don’t leave it too much for later. This could also be a good opportunity for you to revamp some logic being performed at the beginning.

To summarize, here's the composition of a typical Splash Screen:

  1. App Icon (should be a vector drawable).
  2. App Icon Background (optional), useful if you want to have a contrast color in place. If an adaptive icon is used, then its background color will be used.
  3. App Adaptive Icon (it will cover one third of the foregrounded marked space).
  4. Window Background, it should be opaque and if not specified, the system will use the primary color of the main app theme.



Microphone, Camera Toggles & Indicators

This is not an actual “feature” that the developers could use or gain benefit from, but it’s important to note that starting with Android 12, users will have the ability to disable microphone and camera access system-wide .

To give a little bit more explanation here, even if your application had the permission granted to use the device microphone or camera, it won’t be able to use them as long as they’re disabled by the user system-wide.

It’s more like a privacy mechanism to prevent unwanted usage from the device if they’re not needed, and on top of that, the OS will send a notification every time an application uses the mic or camera, and an indicator is going to be shown on the right side of the Status Bar. Both capabilities can be disabled from the newly introduced Quick Tiles in the Notification Drawer.


Changes for Apps Targeting API Level 32


Custom Notifications

There was an interesting change related to Custom Notifications and how we’re not going to be able anymore to create customized layouts as we’ve used to.

This change was introduced to limit different issues associated with these layouts because they acted in different ways across different Android versions, and also across different OEM Skins hence resulted in anti-patterns.

The solution to this was to create a sort of bubble, like a container to enclose the customized notification, with a template that is going to be operated entirely by the OS.

This bubble will wrap up the entire notification with a same structure as other notifications. It will provide the same order and placement for the app icon, name, collapse movement and some other small details.

By doing so, all the notifications will have a more consistent design and be visually pleasing for the user with a more familiar user experience.



Toast messages have gotten some updates in Android 11 as well as in Android 12. We can clearly see some changes on the UI side:

  • They were visually redesigned as part of the Material UI overhaul.
  • Now they’re also showing the app icon from which the Toast message has been launched.
  • Text has now been limited to two lines. The length of these lines is relative because it’s not going to be the same if displayed on a tablet or on a typical smartphone screen.


New Bluetooth Permissions

Android 12 also saw the introduction of a new set of Bluetooth permissions. This good news because now we’re going to have three different permissions each for one different use case.

All of these are runtime permissions so they are going to be allowed from the user side.

  • BLUETOOTH_SCAN: When the app needs to look out and scan for Bluetooth nearby devices
  • BLUETOOTH_ADVERTISE: When we want to make our device discoverable for other devices
  • BLUETOOTH_CONNECT: When we want to connect to an already-paired Bluetooth device

There are also two primary things to consider when working now with these new permissions:

  • You will still have to use the old legacy permissions used prior to API Level 31, but with a little variation by adding the attribute android:maxSdkVersion = "30“ to the permission block. This attribute must be set in order to tell to the OS that this permission should only be treated until a specific Android version.
  • ACCESS_FINE_LOCATION permission should be used only if there’s a specific need to get the physical location of nearby devices, otherwise it is strongly recommended not to include the permission unless it is used also for other purposes. Previously we had to use this permission while performing scanning operations for other Bluetooth peripherals, but now that we have the new BLUETOOTH_SCAN permission, this is no longer required because this permission will only search for the new devices without asking for physical location information.

To summarize, here’s how the Android Manifest could look like after the additions of these new Bluetooth permissions:


    <!-- Request legacy Bluetooth permissions on older devices. -->
    <uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" />

    <!-- Needed only if your app looks for Bluetooth devices.
         If your app doesn't use Bluetooth scan results to derive physical
         location information, you can strongly assert that your app
         doesn't derive physical location. -->
    <uses-permission android:name="android.permission.BLUETOOTH_SCAN" />

    <!-- Needed only if your app makes the device discoverable to Bluetooth
         devices. -->
    <uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />

    <!-- Needed only if your app communicates with already-paired Bluetooth
         devices. -->
    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />

    <!-- Needed only if your app uses Bluetooth scan results to derive physical location. -->
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />



Access Fine Location Permission Changes

Regarding the Access Fine Location, we have some changes on that side too.

On previous Android versions, you had the ability to ask in a permission request only for the precise location of the user. This has been changed and Google is recommending to put in the request as a choice also the approximate location permission that in this case it is called: ACCESS_COARSE_LOCATION.

This is more like an enforcement kind of change, because the developer always had the choice of whether to include only the precise location permission in the request or both, giving freedom to the user by allowing the preferred one.

Now if the developer doesn’t conform with this, two possible scenarios could occur, and that also depends on the Android version.

The first one is that the request is going to be filtered by the OS and basically the request will also show the option to allow the approximate location permission even if we haven’t included it in the request.

The second one instead was occurring on some Android 12 versions and essentially the request would just get ignored by the OS.

Having tested this also on an Android 13 powered device, the scenario currently occurring is the first one. The permission request will not get ignored, but you will see a warning from Android Studio if you attempt to use only the ACCESS_FINE_LOCATION.

The recommendation from Google which applies also for the previous topic we’ve covered regarding the new Bluetooth Permissions, is to limit the use of the precise location permission only when we absolutely need it and for the rest of the other use cases, to use the the approximate location permission.

Here’s also a snippet of code related to how the permission request should look:

//Permissions Request on Kotlin
val locationPermissionRequest = registerForActivityResult(
		) {  permissions ->
				when {
					permissions.getOrDefault(Manifest.permission.ACCESS_FINE_LOCATION, false) -> {
					   // Precise location access granted.
					permissions.getOrDefault(Manifest.permission.ACCESS_COARSE_LOCATION, false) -> {
					   // Only approximate location access granted.
					} else -> {
                       // No location access granted.

//Also, better to check first if we have already these permissions granted


App Hibernation Changes

Google has also introduced some changes to App Hibernation specifically related to some new post effects for applications being hibernated. If you don’t know how the process of hibernation works, the OS based on different factors and especially by the usage of an application, will decide whether to “Hibernate” this application or not, in order to reduce the consumption and resources from applications that are not being used that much.

On older versions of Android, we only had one main post effect of the hibernation process, which was the reset of the runtime permission. So if the user started to use the app again in a second moment, all the runtime permissions needed by the app would have to be requested again.

With Android 12, the new effects of the post hibernation process are:

  • Application can no longer run jobs or run alerts from the background
  • Application can no longer receive push notifications, including high fidelity ones
  • Application’s cache is removed



Motion Sensors Refresh Limit

There also were some minor changes, a particular one impacting applications that are receiving data from some motion sensors at a high refresh rate.

This has been changed starting with Android 12, and now if you want to keep the same high refresh rate, you will need to include in your application a new permission called: HIGH_SAMPLING_RATE_SENSORS.

Failing to comply with this and attempting to obtain the data from these sensors at the same high refresh rate will lead the the OS throwing an exception, which is going to make your application crash.


Misc performance Changes


Foreground Services Restrictions

Foreground services are important in our enterprise daily use cases; they run indefinitely and provide continuous operations for our applications.

In the latest Android versions, we had been having different and small changes related to how the foreground services are behaving and there has been no exception in the case of Android 12.

Foreground services now have a new limitation, and applications that were previously launching them from the background (meaning that the application was not running in the foreground) are not going to be able to do that anymore unless your application has one of these listed exemptions.

If you try to launch the foreground service while your application is in a background state, the system will throw an exception in the background, notifying that you can’t do that anymore.


Exact Alarms Changes

If you’re using Alarms to schedule processes that your application should perform when it is not running, you have to know that starting with Android 12 there’s going to be a restriction on the usage of the “Exact” Alarms, and it will no longer be possible to set and schedule them freely as before.

Developers will have to include in their Android Manifest a new permission called: SCHEDULE_EXACT_ALARM, which the user will have to grant it, and in this case it’s not a runtime one but instead is a manual one which has to be granted by the user from the System Settings by allowing the “Alarms & Reminders” capability for the application.


Concurrent Peer to Peer + Internet Connection

For supported devices, it is now possible to have a concurrent peer-to-peer and Wi-Fi internet connection, which was not possible on previous Android versions because you always had to drop the first connection before joining another one.

To adapt to these changes, also the WifiManager.getConnectionInfo() method’s logic, which returns the Wi-Fi information for a single network, also has been changed to support the new case scenarios.

Now if:

  • A single Wi-Fi network is available, it's WiFiInfo object is returned
  • More than one Wi-Fi network is available and the calling app triggered a peer-to-peer connection, the WiFiInfo object of the peer-to-peer connection is returned
  • More than one Wi-Fi network is available and the calling app did not trigger a peer-to-peer connection, it will be returned the WiFiInfo object of the main network


Safer Components Exporting

It is now mandatory to explicitly declare in the AndroidManifest whether a component (Activity, Service, Broadcast Receiver) that uses Intent Filters should be exported.

What does that mean?

When we refer to components being exported, mean those that can be called with the same package and class name from outside the app. And components that are not exported are the ones that are accessible only within the app and not callable from outside applications.

The default launcher activity should always have the exported flag set to true, otherwise it would be impossible to launch the application from the launcher.

Usually if there are no special requirements, most of the tims the flag will be set to false.


Mutability of Pending Intents

Starting with Android 12 and for any application that is targeting API level >31, it is now mandatory to declare the mutability of any created Pending Intent. In most of the use cases, the pending intents should be immutable, so that other applications can’t alter the original one.

So when changing and adapting the initialization of a pending intent in your code, you should also add to the signature of the constructor one of these two flags:

  • PendingIntent.FLAG_IMMUTABLE
  • PendingIntent.FLAG_MUTABLE


Activity Lifecycle

Android 12 also saw a major change related to the Activity Lifecycle, in which the root launcher activities are no longer going to be finished with the back press. In previous Android versions, the behavior was that the system would finish the root activities just like the rest. Now, the activity with its task will be moved in the background with the same behavior of the swipe-up gesture or a press of the home button.

This will help to achieve faster response times for applications when they’ve resumed and accessed again by the user instead of requiring them to be restarted again from the beginning.


System Dialogs

If your application used to close system dialogs while performing different tasks, starting with Android 12 the action that was used to fire up the Intent: ACTION_CLOSE_SYSTEM_DIALOGS has been deprecated and it is no longer usable as per updated documentation.

Whenever there’s an Intent with this action, one of the following scenarios will occur:

  • If the app targets Android 12 or higher, then a SecurityException will be thrown
  • If the app targets Android 11 or lower, then the intent will not be executed and a message will be displayed in the Logcat

However, there are a couple of exemptions, where the use of this action is still permitted:

  • If the app is running instrumentation tests
  • If the app targets Android 11 or lower and is showing a window that is on top of the notification drawer
  • If the app targets Android 11 or lower and has an active accessibility service
  • If the app targets Android 11 or lower and in addition the user has interacted with a notification and the app is processing a service or a broadcast receiver in response to a specific user action


Enterprise Changes


Work Profile

  • Every personal device profile enrollment will have a unique ID called: Enrollment-Specific ID. This ID will remain stable and will not change across factory resets.
  • There’s now the ability to set and retrieve profile network logging. This was not possible on previous Android versions, and it will only be available on work profiles, so personal ones are not affected by this change.
  • User can control the following permissions and deny them if allowed by their IT administrator:
    • Location
    • Camera
    • Microphone
    • Body Sensor
    • Physical Activity


Company Owned Devices

  • An IT administrator can now disable USB capabilities of a device (except for the charging function)
  • It is now possible to limit the input methods used on a company-owned device by restricting them to system input methods only



  • setPasswordQuality() and getPasswordQuality() DPCs should use now setRequiredPasswordComplexity() method instead
  • setOrganizationColor() and getOrganizationColor()
  • ACTION_PROVISION_MANAGED_DEVICE will no longer work from Android 12. Any start operation of provisioning profile will fail. Instead DPCs should start using these actions from now on:
    • ACTION_GET_PROVISIONING_MODE: Used to start the administrator to get the mode for the provisioning
    • ACTION_ADMIN_POLICY_COMPLIANCE: Starts the administrator to show the policy compliance for the provisioning. It can be used any time the administrator has an opportunity to show it before the end of the setup wizard. Note: EMMs should still use the old way if provisioning operations are being done on Android 11-based devices or lower.
  • setPermissionPolicy() & setPermissionGrantState() for granting sensor-related permissions for all work profiles are now deprecated




Daniel Neamtu

Please register or login to post a reply

0 Replies