The Quick Developer’s Guide to Migrating Apps to Android 12 | by Sahil Sharma | Jul, 2022

Posted on

Getting your app ready for SplashScreen API, Approximate Location, PendingIntent Mutability and much more …

Photo by Sebastian Bednarek on Unsplash

Google announced Android 12 (L) on October 2021 and by March 2022 the stable build was released starting with the Pixel phones and soon followed by other major brands.

Android 12 comes with some big visual and user experience changes, also focusing on Privacy and Performance.

I thought that this article was necessary as now Google Play Store has enforced to update all the applications to target to API Level 31 (i.e. Android 12) by November 2022 and as I was still getting queries from many of you on how to migrate to Android 12, so here it is!

In this article, we will quickly start with the important stuff first and later will be reviewing some enhancements that are worth mentioning and deprecations of existing APIs and features.

So let’s quickly jump to what all changes you need to do to target your application to Android 12 and the things to keep in mind.

Safe Export

Whenever you define any component (like Activity, Service and Broadcast Receiver) in the manifest, you must have seen/used some thing like "android:exported"

By default this attribute is set to true, which means that the component can be accessed from outside of your application. For example, If an activity in your app includes intent filters, set this element to “true” to allow other apps to start it.

From API 31 onward, you have to explicitly set a value to this attribute.

A common rule of thumb is: If the app component includes the LAUNCHER category, set android:exported to true. In most other cases, set android:exported to false.

<service android:name="com.example.app.backgroundService"
android:exported="false">
<intent-filter>
<action android:name="com.example.app.START_BACKGROUND" />
</intent-filter>
</service>

Failing to do so might throw a compile time:

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

Read more about Safe Component Exporting and android:exported

Pending intents mutability

API level 31 onward, you will have to specify the mutability of each PendingIntent object that your app creates.

To declare that a given PendingIntent object is mutable or immutable, use the PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_IMMUTABLE flag, respectively.

val updatedPendingIntent = PendingIntent.getActivity(
applicationContext,
NOTIFICATION_REQUEST_CODE,
updatedIntent,
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
)

Failing to do so the system throws an IllegalArgumentException:

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

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

Approximate Location

Starting in Android 12, users can now chose to provide either Precise location or Approximate Location, even when your app requests the ACCESS_FINE_LOCATION runtime permission.

You will have to handle for both the scenarios now in order to respect users’ privacy, however if your apps use-case is such that requires Precise Location then make sure that the same is prompted to the user and handled in your app accordingly. Read more on asking for Precise location.

I recommend that you read the Best Practices on Requesting Location Permissions.

SplashScreen API

Earlier most of us used to create a custom Splash screens by using an Activity or setting a window theme on an Activity.

If you have previously implemented a custom splash screen in Android 11 or lower, you’ll need to migrate your app to the SplashScreen API to ensure that it displays correctly starting in Android 12.

On devices running on Android 11, this won’t be a problem but if you have targeted API level 31 and still not migrated to SplashScreen API, the system will throw a Runtime Exception on Android 12 devices.

It’s also worth noting that the system always applies the new Android system default splash screen on cold and warm starts for all apps. By default, this system default splash screen is constructed using your app’s launcher icon element and the windowBackground of your theme (if it’s a single color).

Read about how to migrate your existing Splash screen implementation to Android 12 or higher

Read more about Android Splash Screens

Bonus: Along with the new SplashScreen API, you can also make use of App Startup library to initialize components at application startup.

Exact alarm permission

To create an Exact alarm, your app needs have have access to the “Alarms & reminders” capability that appears within the Special app access screen in system settings.

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

Failing to do so, system will throw SecurityException.

But the catch here is that to obtain this special permission and get approval by Google Play store, your app must be of one of the following type:
1. Clock or Timer application
2. Calendar or Reminder application

Web intent resolution

Starting in Android 12 (API level 31), your app’s Activity can no longer resolve to generic web intents, the system will redirect them to the default browser, until your app is approved to handle that web intent.

Read more about how your app can get this approval.

Also read more about App Links verification changes.

Till now we have covered the main things that you need to migrate your app to Android 12, but there are a few things that you should know.

Restricted App Standby Bucket

We read about the App Standby Buckets before, simply put, these buckets help the system prioritize apps’ requests for resources based on how recently and how frequently the apps are used.

Now a new App Standby Bucket is introduced: Restricted.

According to the documentation, The system considers your app’s behavior, in addition to usage patterns, to decide whether to place your app in the restricted bucket. Your app is less likely to be placed in the restricted bucket if your app uses system resources more responsibly. Also, the system places your app in a less restrictive bucket if the user interacts directly with your app.

Read more about Restricted App Standby Bucket.

Microphone and camera indicators and toggle

Camera and Microphone indicators on the status bar. (Source)

Just like in Apple products, Android too has this feature now where you will get to see an indicator on the status bar whenever your device’s Camera or Microphone is in use.

Also, supported devices that run Android 12 or higher allow users to enable and disable camera and microphone access for all apps on the device, by pressing a single toggle option.

Read more about the best practices to access to more sensitive permissions.

Root launcher activities are no longer finished on Back press

If your activity is the root activity (ie. the last activity on the task stack), on press of the back button, it wont be killed but simply put to background. Just like how the press the home button.

This change means that users who use Back to navigate out of your app are able to more quickly resume your app from a warm state, instead of having to completely restart the app from a cold state.

Also, it is recommended using the AndroidX Activity APIs for providing custom back navigation, rather than overriding onBackPressed()

Read more about this.

Bouncy Castle implementation removed

Android 12 removes many BouncyCastle implementations of cryptographic algorithms that were previously deprecated, including all AES algorithms. The system instead uses the Conscrypt implementations of these algorithms.

Read more about this.

Display#getRealSize and getRealMetrics : deprecated

The following methods are deprecated:

Instead of these methods it is recommended to use the Jetpack WindowManager library, which includes a WindowMetrics class that supports Android 4.0 (API level 14) and higher.

Apps can’t close system dialogs

Starting with Android 12, you won’t be able to close system dialogs as the ACTION_CLOSE_SYSTEM_DIALOGS intent action is deprecated. If you try to launch this intent, the system will simply throw a SecurityException . On Android 11 devices, the system will ignore the intent.

However there are few special cases, Read more this change.

Let me know your suggestions and if you think I missed mentioning an important change in Android 12.

Now that you know everything to migrate your amazing app to Android 12, what are you waiting for?

See you next time.

Thank you!

Leave a Reply

Your email address will not be published.