Android 14 Migration Guide
As Android systems continue to evolve, Google Play has new requirements for the targetSdkVersion
of apps.
As of August 31 2024, new apps and app updates must target Android 14 (API level 34) or higher to be submitted to Google Play.
Additionally, if more time is needed to upgrade an app, an extension can be requested until November 1, 2024. The extension form can be found from Google Play Console, usually in the app management page's inbox.
For more details, see Target API level requirements for Google Play apps.
This document aims to provide developers intending to upgrade the targetSdkVersion
of their project to 34 with information regarding the changes and impacts of API level 34. Troubleshooting steps as well as their solutions for common impact points are also included, ensuring your app's smooth transition to Android 14.
To prevent compilation errors, both compileSdkVersion
and targetSdkVersion
has to be upgraded to 34.
Troubleshooting impact points in Android 14
Here are some updates and changes in Android 14 that could impact game developers. For a full rundown of everything new in Android 14, check out: https://developer.android.com/about/versions/14/summary
Restrictions on implicit and pending intents
For apps with targetSdkVersion=34
, Android 14 has the following restrictions on implicit intents:
- Implicit intents can only be sent to exported components. For components that have not been exported, explicit intents must be used, or the components must be specified as exported first.
- If a mutable
PendingIntent
is created without specifying a component or package, the system will throw an exception.
Troubleshooting steps
Check if your game might be affected by unpacking the APK to see if the AndroidManifest
contains component declarations that meet both of the below criteria:
- Android component declaration includes the attribute
android:exported="false"
. - Android component declaration includes an
intent-filter
with a customaction
.
If you find any component declarations that meet both criteria, your app may be using implicit intents to launch components. Contact [diemliang] for further troubleshooting steps.
Sample code:
<service android:name="com.example.ExampleService"
android:exported="false">
<intent-filter>
<action android:name="com.example.EXAMPLE_ACTION"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</service>
Specify export behaviour for runtime-registered broadcast receivers
Broadcast receivers are often used to listen for changes in device status, such as network switches or changes in the battery level, and is a commonly used feature.
For apps with targetSdkVersion=34
, any BroadcastReceiver
registered at runtime through the Context
must have its export attribute specified in the parameters, or the system will throw an exception.
Troubleshooting steps
Search the smali files to see if the following code snippet is present after unpacking the APK:
Landroid/content/Context;->registerReceiver(Landroid/content/BroadcastReceiver;Landroid/content/IntentFilter;)Landroid/content/Intent;
If present, a portion of the logic involves registering a BroadcastReceiver
using Context
. Contact [diemliang] together with unpacked smali files for further troubleshooting steps.
For apps running on Unity 2020 or earlier versions, also see Unity.
Verify zip path traversal
For apps with targetSdkVersion=34
, if the zip file entry name contains ".." or starts with "/", methods ZipFile(String)
and ZipInputStream.getNextEntry()
will throw a ZipException
.
This is a safeguard against zip path traversal vulnerabilities.
Troubleshooting steps
Search the smali files to see if the following code snippets are present after unpacking the APK:
Ljava/util/zip/ZipFile;-><init>(Ljava/lang/String;)V
Ljava/util/zip/ZipInputStream;->getNextEntry()Ljava/util/zip/ZipEntry;
If present, it means your game involve using ZipFile
and ZipInputStream
. You'll need to check if the functionality using this interface runs smoothly on Android 14.
For the zip packages decompressed using the above interface, if the path of the compressed file contains ".." or starts with "/", it's advisable to alter the structure of the zip package and the way it's decompressed. Contact [diemliang] for further troubleshooting steps.
User consent for every MediaProjection Capture Session
For apps with targetSdkVersion=34
, user consent is required before every Capture Session. A single Capture Session can only be a one-time call to MediaProjection#createVirtualDisplay
, and each MediaProjection
instance can be used just once.
This API is related to screen recording, typically used to record standout player moves.
Troubleshooting steps
Search the smali files to see if the following code snippets are present after unpacking the APK:
Landroid/media/projection/MediaProjection;->createVirtualDisplay(
Landroid/media/projection/MediaProjectionManager;->createScreenCaptureIntent()
If present, it suggests your operations engage with MediaProjection
. You'll need to check if the feature using this interface operates correctly on Android 14, particularly focusing on whether the feature functions normally when this interface is used multiple times in a single run. Contact [diemliang] for further troubleshooting steps.
Specify foreground service types
When opening other content in-game, such as Google login or WebView, the game app enters a background state and may get closed by the system. Adding permissions for foreground services to your app may help to circumvent this issue.
For apps that use foreground services with targetSdkVersion=34
, at least one foreground service type must be specified for each foreground service. The foreground service type should represent your app's use case, in order to meet Android requirements.
The foreground service should also be declared in Google Play Console, from App content > Foreground service permissions. For example, if your app uses WebView, choose Other, then include a brief explanation together with a URL of a video of your app opening WebView in the game.
For more information about the available types, see Foreground service types are required.
Troubleshooting steps
Search the smali files to see if the following code snippets are present after unpacking the APK, to determine if a foreground service is being used:
->startForeground(ILandroid/app/Notification;)V
->startForeground(ILandroid/app/Notification;I)V
If present, check the corresponding Service
definition in AndroidManifest.xml
to see if it contains the android:foregroundServiceType
attribute and if the type is appropriate. Contact [diemliang] for further troubleshooting steps.
Sample code:
<!-- AndroidManifest.xml -->
<manifest ...>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<!-- Add the corresponding specific permission, in this example for mediaPlayback: FOREGROUND_SERVICE_MEDIA_PLAYBACK -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />
<application ...>
<!-- Define foregroundServiceType in the service -->
<service
android:name=".MyMediaPlaybackService"
android:foregroundServiceType="mediaPlayback"
android:exported="false">
</service>
</application>
</manifest>
Changes in the project environment
- Unity
- Unreal Engine
In Unity 2020 or earlier versions, the registerReceiver
method used in UnityPlayerActivity#onCreate
does not specify exported components. This causes apps using Unity 2020 or earlier versions to malfunction on Android 14 when trying to upgrade targetSdkVersion
to 34.
Upgrade Unity to the following LTS versions or later, which have fixed this issue:
- 2021.3.33f1
- 2022.3.13f1
- 2023.1.20f1
- 2023.3.0a11
For more information, see this bug report in the Unity Issue Tracker.
Upgrade to Android API level 34 by updating the targetSdkVersion
in your Unreal Engine project:
- Navigate to the Config folder in your Unreal Engine project directory.
- Open the
DefaultEngine.ini
file. In theDefaultEngine.ini
file, add or modify the following lines to set thetargetSdkVersion
:
TargetSDKVersion=34
SDKAPILevelOverride=android-34
- After making the changes, save and close the
DefaultEngine.ini
file.
Upgrade Android Gradle Plugin (AGP)
- Unity
- Unreal Engine
According to Minimum versions of tools for Android API level from the official Google documentations, when your app has targetSdkVersion=34
, the minimum required AGP version is 8.1.1.
However, in practical testing, it has been found that using version 7.1.2 is sufficient to meet the current compilation requirements. There is no need to upgrade to the higher version of 8.1.1.
- For Unity 2022.2 or later, the default AGP version already meets the requirements, and no further action is necessary.
- For Unity versions before Unity 2022.2, follow the below procedures to upgrade AGP.
Upgrade Gradle Wrapper version
In the Editor, find the option Gradle installed with Unity by going to Unity > Settings > External Tools and uncheck it, then select the path to
gradle-7.2-bin
on your device for Gradle:Modify the environment variable by setting
GRADLE_HOME
to the path of Gradle 7.2:# sh
export GRADLE_HOME=/Users/***/.gradle/wrapper/dists/gradle-7.2-bin/****/gradle-7.2
export PATH=${PATH}:${GRADLE_HOME}/bin
Modify AGP dependency version
If you have already upgraded to Player Network SDK V1.24, the AGP version in Assets/Plugins/Android/baseProjectTemplate.gradle
has already been updated to 7.1.2, and does not need to be modified.
Check the version of "com.android.tools.build:gradle:x.x.x"
in the Assets/Plugins/Android/baseProjectTemplate.gradle
file. If the version is below 7.1.2, you will need to update it to 7.1.2.
According to Minimum versions of tools for Android API level from the official Google documentations, when your app has targetSdkVersion=34
, the minimum required AGP version is 8.1.1.
However, in practical testing, it has been found that using version 7.1.2 is sufficient to meet the current compilation requirements. There is no need to upgrade to the higher version of 8.1.1.
Follow the below procedures to upgrade AGP for your project:
Upgrade Gradle Wrapper version
Download the gradle-7.2-bin.zip file from the official website and extract it to your chosen directory.
Set the path of the
GRADLE_HOME
environment variable to the extract location ofgradle-7.2-bin
.# sh
export GRADLE_HOME=/Users/***/.gradle/wrapper/dists/gradle-7.2-bin/****/gradle-7.2
export PATH=${PATH}:${GRADLE_HOME}/binModify the
/Engine/Build/Android/Java/gradle/gradle/wrapper/gradle-wrapper.properties
file in the engine directory, changingdistributionUrl
to the URL for Gradle 7.2:distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-all.zip
Modify AGP dependency version
If you have already upgraded to Player Network SDK V1.24, the AGP version in INTLSDK/Source/INTLCore/Libs/Android/INTLCore_APL.xml
has already been updated to 7.1.2, and does not need to be modified.
To add or modify the buildscript block in an APL (Android Project Library) file:
<buildscriptGradleAdditions>
<insert>
dependencies {
classpath 'com.android.tools.build:gradle:7.1.2'
}
</insert>
</buildscriptGradleAdditions>
Upgrade Java version
- Unity
- Unreal Engine
When upgrading the targetSdkVersion
to 34, it's necessary to also upgrade the Java version depending on your Unity version:
- For Unity 2022.3 or later, the default Java version already meets the requirements, and no further action is necessary.
- For Unity versions before Unity 2022.3, follow the below procedures to upgrade Java.
Navigate to
Assets/Plugins/Android/gradleTemplate.properties
and add the lineorg.gradle.java.home
, specifying the value as the Java 11 path:org.gradle.java.home=/Users/***/Library/Java/jdk-11.0.22.jdk/Contents/Home
Modify the environment variable by setting
JAVA_HOME
to the path of Java 11:# sh
# set JAVA_HOME to your jdk 11 installation path.
export JAVA_HOME=/Users/***/Library/Java/jdk-11.0.22.jdk/Contents/Home
export PATH=${PATH}:${JAVA_HOME}/bin
AGP 7.1.2 requires Java 11. If your current Java version is below 11, you'll need to download and install JDK 11 and update your environment variables accordingly:
# sh
# set JAVA_HOME to your jdk 11 installation path.
export JAVA_HOME=/Users/***/Library/Java/jdk-11.0.22.jdk/Contents/Home
export PATH=${PATH}:${JAVA_HOME}/bin
Validation
Verify basic information
When unpacking an APK, check the following fields in the AndroidManifest.xml
file to ensure they meet expectations:
Review the
package
attribute in the<manifest>
tag to confirm that the package name is correct.Examine the
platformBuildVersionCode
attribute in the<manifest>
tag, which should be set to 34.Look at the
android:minSdkVersion
attribute within the<uses-sdk>
tag. This should reflect the minimum Android API level supported by your game.Relationship between Android API Levels and Android Versions: https://apilevels.com/
Check the
android:targetSdkVersion
attribute within the<uses-sdk>
tag, expected to be 34.
AndroidManifest.xml
example:
<!---AndroidManifest-->
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
android:versionCode="1"
android:versionName="1.0"
android:compileSdkVersion="34"
android:compileSdkVersionCodename="14"
package="your.package.name"
platformBuildVersionCode="34"
platformBuildVersionName="14">
<uses-sdk
android:minSdkVersion="16"
android:targetSdkVersion="34" />
......
Compatibility testing
You'll need to perform compatibility testing using the generated APK, with a particular focus on how the APK performs on Android 14 devices. Pay special attention to scenarios that are related to the behavior changes outlined in Section 2.
Appendix
Guide to Unpacking an APK
To confirm whether the game involves any changes in the API, it is recommended to globally search by decompiling the APK package. The recommended tool for decompiling is apktool:
Execute the following command to decompile the APK:
apktool d your_apk_path.apk
- After executing the command, the decompiled files will be located in the
/your_apk_path
directory:
FAQ
- Unity
- Unreal Engine
Error when executing **File > Build And Run**
Error message:
FAILURE: Build failed with an exception.
* Where:
Build file '/Users/***/launcher/build.gradle' line: 1
* What went wrong:
A problem occurred evaluating project ':launcher'.
> Failed to apply plugin 'com.android.internal.application'.
> The option 'android.enableR8' is deprecated.
It was removed in version 7.0 of the Android Gradle plugin.
Please remove it from `gradle.properties`.
The enableR8 configuration is no longer supported in AGP 7.0 or later, as R8 is now enabled by default.
In Unity Editor, navigate to Edit > Project Settings > Player > Android > Publishing Settings > Minify, and ensure that the Use R8 checkbox is checked to resolve the issue with Build And Run
.
Unity 2021 compile error in gradle mergeDex
Error message:
> Task :launcher:mergeDexDebug FAILED
AGPBI: {"kind":"error","text":"com.android.tools.r8.kotlin.H","sources":[{}],"tool":"D8"}
com.android.tools.r8.kotlin.H
Execution failed for task ':launcher:mergeDexDebug'.
> Could not resolve all files for configuration ':launcher:debugRuntimeClasspath'.
> Failed to transform play-services-measurement-api-21.5.0.aar (com.google.android.gms:play-services-measurement-api:21.5.0) to match attributes {artifactType=android-dex, asm-transformed-variant=NONE, dexing-enable-desugaring=true, dexing-is-debuggable=true, dexing-min-sdk=16, org.gradle.status=release, org.gradle.usage=java-runtime}.
> Execution failed for DexingWithClasspathTransform: /Users/diemliang/.gradle/caches/transforms-3/e44e9aeb559794f90081ea4f47c131bc/transformed/jetified-play-services-measurement-api-21.5.0-runtime.jar.
> Error while dexing.
This issue due to r8 being specified as 4.0.48 in Unity 2021, which is incompatible with AGP 7.1.2. The official Google documentation recommends using 3.1.51 of r8 with AGP 7.1.2.
Modify the r8 version to V3.1.51 in settingsTemplate.gradle
:
dependencies {
// classpath("com.android.tools:r8:4.0.48")
classpath("com.android.tools:r8:3.1.51") // Change to 3.1.51
}
If you have already upgraded to Player Network SDK V1.24, the r8 version in Assets/Plugins/Android/settingsTemplate.gradle
has already been modified to 3.1.51, and does not need to be modified.
Compilation error: 'shortService' is incompatible with attribute foregroundServiceType (attr) flags
Both compileSdkVersion
and targetSdkVersion
has to be upgraded to 34.