There are not many adaptation points that need to be updated for Android 12. This article mainly introduces the two most common adaptation points: android:exported and SplashScreen .
1, android:exported
It is mainly used to set whether the Activity can be started by other application components. "true" means yes, and "false" means No.
If it is "false", the Activity can only be started by components of the same application or different applications using the same user ID.
Of course, not only activities, but also services and receivers will have exported scenarios.
In general, if an intent filter is used, the exported cannot be set to "false", otherwise the system will throw an ActivityNotFoundException exception when the Activity is called.
On the contrary, if there is no intent filter, the exported of Activity should not be set to true, which may be defined as a security vulnerability during security scanning.
On the Android 12 platform, that is, when using targetSdkVersion 31, you need to pay attention to:
If the Activity, Service or Receiver uses intent filter and does not explicitly declare the value of android:exported, the App will not be installed.
At this time, you may choose to manually modify AndroidManifest one by one, but what if the SDK or third-party library you use does not support it? Or do you want to play packages on different target platforms? At this time, the following gradle script can save you worry:
com. android. tools. build:gradle:3.4. Version below 3
/** * Modify Android 12 because of the construction problem of exported */ android.applicationVariants.all { variant -> variant.outputs.all { output -> output.processResources.doFirst { pm -> String manifestPath = output.processResources.manifestFile def manifestFile = new File(manifestPath) def xml = new XmlParser(false, true).parse(manifestFile) def exportedTag = "android:exported" ///Specify space def androidSpace = new groovy.xml.Namespace('http://schemas.android.com/apk/res/android', 'android') def nodes = xml.application[0].'*'.findAll { //Select the nodes to be modified. Only those without specified exported need to be added (it.name() == 'activity' || it.name() == 'receiver' || it.name() == 'service') && it.attribute(androidSpace.exported) == null } ///Add exported. The default is false nodes.each { def isMain = false it.each { if (it.name() == "intent-filter") { it.each { if (it.name() == "action") { if (it.attributes().get(androidSpace.name) == "android.intent.action.MAIN") { isMain = true println("......................MAIN FOUND......................") } } } } } it.attributes().put(exportedTag, "${isMain}") } PrintWriter pw = new PrintWriter(manifestFile) pw.write(groovy.xml.XmlUtil.serialize(xml)) pw.close() } } }
com. android. tools. build:gradle:4.1. Version above 0
/** * Modify Android 12 because of the construction problem of exported */ android.applicationVariants.all { variant -> variant.outputs.each { output -> def processManifest = output.getProcessManifestProvider().get() processManifest.doLast { task -> def outputDir = task.multiApkManifestOutputDirectory File outputDirectory if (outputDir instanceof File) { outputDirectory = outputDir } else { outputDirectory = outputDir.get().asFile } File manifestOutFile = file("$outputDirectory/AndroidManifest.xml") println("----------- ${manifestOutFile} ----------- ") if (manifestOutFile.exists() && manifestOutFile.canRead() && manifestOutFile.canWrite()) { def manifestFile = manifestOutFile ///The second parameter here is false, so the namespace is expanded, so instead of Android space, nameTag is used def xml = new XmlParser(false, false).parse(manifestFile) def exportedTag = "android:exported" def nameTag = "android:name" ///Specify space //def androidSpace = new groovy.xml.Namespace('http://schemas.android.com/apk/res/android', 'android') def nodes = xml.application[0].'*'.findAll { //Select the nodes to be modified. Only those without specified exported need to be added //If you can't get the exportedTag, you can try it attribute(androidSpace.exported) (it.name() == 'activity' || it.name() == 'receiver' || it.name() == 'service') && it.attribute(exportedTag) == null } ///Add exported. The default is false nodes.each { def isMain = false it.each { if (it.name() == "intent-filter") { it.each { if (it.name() == "action") { //If you can't get nameTag, you can try it attribute(androidSpace.name) if (it.attributes().get(nameTag) == "android.intent.action.MAIN") { isMain = true println("......................MAIN FOUND......................") } } } } } it.attributes().put(exportedTag, "${isMain}") } PrintWriter pw = new PrintWriter(manifestFile) pw.write(groovy.xml.XmlUtil.serialize(xml)) pw.close() } } } }
com. android. tools. build:gradle:7.0. Version below 3
During debugging, there are strange bugs in AGP, and XmlUtil cannot be serialized normally.
You can put this script directly into app / build It can be executed under gradle, or it can be separately placed in a gradle file and imported by apply. Its function is:
During the packaging process, retrieve all components that are not set to exported and dynamically configure them to exported. A special note here is that "android.intent.action.MAIN" needs to be exported to true because the launcher needs to open the Activity by default. (PS: the launcher category should be used, and MAIN is deliberately used here)
If necessary, you can add judgment to configure exported only when "intent filter" is set.
2, SplashScreen
Android 12 added SplashScreen API, which includes the action of entering the application at startup, displaying the icon screen of the application, and displaying the transition effect of the application itself.

image
It consists of the following four parts, which should be noted here:
- It is better to be a vector paintable object. Of course, it can be static or animated.
- 2 is optional, that is, the background of the icon.
- Like the adaptive icon, one third of the foreground is obscured (3).
- 4 is the window background.
The startup screen animation mechanism consists of entry animation and exit animation.
- The entry animation consists of the system view to the startup screen, which is controlled by the system and cannot be customized.
- The exit animation consists of an animation run that hides the startup screen. If you want Customize it , you can SplashScreenView Custom.

image
The more detailed introduction will not be carried out here. If you are interested, you can read the official data: https://developer.android.com/guide/topics/ui/splash-screen , here we mainly introduce how to adapt and use.
First of all, no matter what version of your TargetSDK is, when you run it on an Android 12 phone, all apps will add the function of SplashScreen.
If you don't do anything, the Launcher icon of the App will become the icon of the SplashScreen interface, and the color specified by the windowBackground attribute under the corresponding original theme will become the background color of the SplashScreen interface. This startup effect occurs during cold and hot startup of all applications.
In fact, there seems to be no problem with the discomfort.
For details on how to migrate and use SplashScreen, please refer to the official documentation: https://developer.android.com/guide/topics/ui/splash-screen/migrate
In addition, you can also refer to New Jetpack member SplashScreen: creating a new App launch screen This article details how to use the official Jetpack library to adapt this effect to the lower Target platform.
Under normal circumstances, what we can do is:
- 1. Upgrade compileSdkVersion 31, targetsdkversion 31 & buildtoolsversion '31.0 0'
- 2. Add dependency implementation "Android x.core: core splashScreen: 1.0.0-alpha02"
- 3. Add the directory of values-v31
- 4. Add styles XML, for example:
<resources> <style name="LaunchTheme" parent="Theme.SplashScreen"> <item name="windowSplashScreenBackground">@color/splashScreenBackground</item> <!--<item name="windowSplashScreenAnimatedIcon">@drawable/splash</item>--> <item name="windowSplashScreenAnimationDuration">500</item> <item name="postSplashScreenTheme">@style/AppTheme</item> </style> </resources>
- 5. Add this theme to your startup Activity, and use different themes in different directories to achieve the adaptation effect.
PS: personally, I don't like this thing at all.
3, Other
1. The notification center has changed again
Android 12 has changed the appearance and behavior of notifications that can be completely customized. Previously, customized notifications can use the entire notification area and provide their own layout and style. Now its behavior has changed.
If the App with TargetSDK 31 is used, the notification with custom content view will no longer use the full notification area; Instead, use the system standard template.
This template ensures that as like as two peas, the custom notification is exactly the same in other conditions, such as the notification icon and deployment function in the status of the retraction, and the notification icon, application name and retracting function in the expanded state, and Notification.. The behavior of the decorated customviewstyle is almost identical.

image
2. Android App Links validation
Android App Links is a special type of DeepLink, which is used to let the Web directly open the corresponding app content in the Android application without the user selecting the application. Using it requires the following steps:
How to use viewable: https://developer.android.com/training/app-links/verify-site-associations#auto-verification
Using the App with TargetSDK 31, the system will Android App Links Some adjustments have been made to the verification method of, which will improve the reliability of application links.
If your app relies on Android App Links validation to open web links in the app, please ensure that the correct format is used when adding intent filters for Android App Links validation. In particular, please ensure that these intent filters contain the BROWSABLE category and support the https scheme.
3. Security and privacy settings
3.1. Approximate position
Using the App with TargetSDK 31, users can request that the App can only access the approximate location information.
If App requests ACCESS_COARSE_LOCATION but access is not requested_ FINE_ Location then there will be no impact.
App with TargetSDK 31 requests ACCESS_FINE_LOCATION runtime permission, you must also request ACCESS_COARSE_LOCATION permission. When app requests these two permissions at the same time, the system permission dialog box will provide the user with the following new options:

image
3.2,SameSite Cookie
The SameSite property of a Cookie determines whether it can be sent with any request or only with requests from the same site.
- Cookie s without SameSite attribute are treated as SameSite=Lax.
- Cookie s with SameSite=None must also specify the Secure attribute, which means that they need a Secure context and need to be sent over HTTPS.
- The link between the HTTP and HTTPS versions of the site is now considered a cross site request, so unless the Cookie is correctly marked SameSite=None; Secure, otherwise the Cookie will not be sent.
stay WebView devtools in Switch interface flag WebView enable modern cookie same site , you can manually enable the SameSite behavior on the test device.
4. Application sleep
Android 12 was introduced in Android 11 (API level 30) Automatically reset permission behavior Based on.
If the App user with TargetSDK 31 does not open it for several months, the system will automatically reset all permissions granted and put the App into hibernation.
For more information: https://developer.android.com/topic/performance/app-hibernation
4, Finally
Generally, these are the things that need attention. In fact, except for expanded and SplashScreen, there is little need for adaptation. In fact, SplashScreen will be disliked by the products. After all, the treatment of Material Design in China is really a little miserable, and there is no way to remove SplashScreen. It is estimated that it will take some time to quarrel with the products, However, products and designs generally do not have Android phones, not to mention Android 12, so let's talk about it in the future ~