Comme les versions précédentes, Android 14 apporte des modifications de comportement pouvant affecter votre application. Les modifications de comportement suivantes s'appliquent exclusivement aux applications qui ciblent Android 14 (niveau d'API 34) ou version ultérieure. Si votre application cible Android 14 ou une version ultérieure, vous devez la modifier pour qu'elle prenne en charge ces comportements, le cas échéant.
Veillez également à consulter la liste des modifications de comportement qui affectent toutes les applications exécutées sur Android 14, peu importe la targetSdkVersion de l'application.
Fonctionnalité de base
Le type de service au premier plan doit être indiqué
Si votre application cible Android 14 (niveau d'API 34) ou version ultérieure, elle doit spécifier au moins un type de service de premier plan pour chaque service de premier plan dans votre application. Vous devez choisir un type de service de premier plan qui représente le cas d'utilisation de votre application. Le système s'attend à ce que des services de premier plan présentant un type particulier répondent à un cas d'utilisation particulier.
Si un cas d'utilisation dans votre application n'est associé à aucun de ces types, il est fortement recommandé de migrer votre logique pour utiliser WorkManager ou les tâches de transfert de données déclenchées par l'utilisateur.
Application de l'autorisation BLUETOOTH_CONNECT dans BluetoothAdapter
Android 14 applique l'autorisation BLUETOOTH_CONNECT lors de l'appel de la méthode BluetoothAdapter getProfileConnectionState() pour les applications ciblant Android 14 (niveau d'API 34) ou version ultérieure.
Cette méthode nécessitait déjà l'autorisation BLUETOOTH_CONNECT, mais elle n'était pas appliquée. Assurez-vous que votre application déclare BLUETOOTH_CONNECT dans son fichier AndroidManifest.xml, comme indiqué dans l'extrait suivant, et vérifiez qu'un utilisateur a accordé l'autorisation avant d'appeler getProfileConnectionState.
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
Mises à jour OpenJDK 17
Android 14 poursuit le travail d'actualisation des principales bibliothèques Android afin de s'adapter aux fonctionnalités des dernières versions d'OpenJDK LTS, y compris les mises à jour de la bibliothèque et la compatibilité avec le langage Java 17 pour les développeurs d'applications et de plates-formes.
Quelques modifications peuvent avoir un impact sur la compatibilité des applications :
- Modifications apportées aux expressions régulières : les références de groupe non valides sont désormais interdites afin de suivre de manière plus fidèle la sémantique d'OpenJDK. Vous pouvez rencontrer de nouveaux cas où une
IllegalArgumentExceptionest générée par la classejava.util.regex.Matcher. Veillez donc à tester votre application pour les éléments qui utilisent des expressions régulières. Pour activer ou désactiver cette modification lors des tests, activez/désactivez l'indicateurDISALLOW_INVALID_GROUP_REFERENCEà l'aide des outils du framework de compatibilité. - Gestion de l'UUID : la méthode
java.util.UUID.fromString()effectue désormais des contrôles plus stricts lors de la validation de l'argument d'entrée. Vous pouvez donc voir uneIllegalArgumentExceptionpendant la désérialisation. Pour activer ou désactiver cette modification lors des tests, activez/désactivez l'indicateurENABLE_STRICT_VALIDATIONà l'aide des outils du framework de compatibilité. - Problèmes avec ProGuard : dans certains cas, l'ajout de la classe
java.lang.ClassValuecause un problème si vous essayez de réduire, d'obscurcir ou d'optimiser votre application avec ProGuard. Le problème provient d'une bibliothèque Kotlin qui modifie le comportement d'exécution selon queClass.forName("java.lang.ClassValue")renvoie une classe ou non. Si votre application a été développée avec une ancienne version de l'environnement d'exécution sans la classejava.lang.ClassValuedisponible, ces optimisations peuvent supprimer la méthodecomputeValuedes classes dérivées dejava.lang.ClassValue.
JobScheduler renforce le comportement des rappels et du réseau
Since its introduction, JobScheduler expects your app to return from
onStartJob or onStopJob within a few seconds. Prior to Android 14,
if a job runs too long, the job is stopped and fails silently.
If your app targets Android 14 (API level 34) or higher and
exceeds the granted time on the main thread, the app triggers an ANR
with the error message "No response to onStartJob" or
"No response to onStopJob".
This ANR may be a result of 2 scenarios:
1. There is work blocking the main thread, preventing the callbacks onStartJob
or onStopJob from executing and completing within the expected time limit.
2. The developer is running blocking work within the JobScheduler
callback onStartJob or onStopJob, preventing the callback from
completing within the expected time limit.
To address #1, you will need to further debug what is blocking the main thread
when the ANR occurs, you can do this using
ApplicationExitInfo#getTraceInputStream() to get the tombstone
trace when the ANR occurs. If you're able to manually reproduce the ANR,
you can record a system trace and inspect the trace using either
Android Studio or Perfetto to better understand what is running on
the main thread when the ANR occurs.
Note that this can happen when using JobScheduler API directly
or using the androidx library WorkManager.
To address #2, consider migrating to WorkManager, which provides
support for wrapping any processing in onStartJob or onStopJob
in an asynchronous thread.
JobScheduler also introduces a requirement to declare the
ACCESS_NETWORK_STATE permission if using setRequiredNetworkType or
setRequiredNetwork constraint. If your app does not declare the
ACCESS_NETWORK_STATE permission when scheduling the job and is targeting
Android 14 or higher, it will result in a SecurityException.
API de lancement des tuiles
Pour les applications ciblant l'âge de 14 ans ou plus,
TileService#startActivityAndCollapse(Intent) est obsolète et génère désormais
une exception lorsqu'elle est appelée. Si votre application lance des activités à partir de cartes, utilisez plutôt TileService#startActivityAndCollapse(PendingIntent).
Confidentialité
Accès limité aux photos et aux vidéos
Android 14 introduces Selected Photos Access, which allows users to grant apps access to specific images and videos in their library, rather than granting access to all media of a given type.
This change is only enabled if your app targets Android 14 (API level 34) or higher. If you don't use the photo picker yet, we recommend implementing it in your app to provide a consistent experience for selecting images and videos that also enhances user privacy without having to request any storage permissions.
If you maintain your own gallery picker using storage permissions and need to
maintain full control over your implementation, adapt your implementation
to use the new READ_MEDIA_VISUAL_USER_SELECTED permission. If your app
doesn't use the new permission, the system runs your app in a compatibility
mode.
Expérience utilisateur
Notifications d'intent plein écran sécurisées
Avec Android 11 (niveau d'API 30), toutes les applications pouvaient utiliser Notification.Builder.setFullScreenIntent pour envoyer des intents plein écran lorsque le téléphone était verrouillé. Vous pouvez l'accorder automatiquement lors de l'installation de l'application en déclarant l'autorisation USE_FULL_SCREEN_INTENT dans le fichier AndroidManifest.
Les notifications d'intent plein écran sont conçues pour les notifications à priorité très élevée nécessitant l'attention immédiate de l'utilisateur, comme les appels entrants ou les paramètres d'alarme configurés par l'utilisateur. Pour les applications ciblant Android 14 (niveau d'API 34) ou version ultérieure, seules les applications qui proposent des fonctionnalités d'appel et d'alarmes peuvent utiliser cette autorisation. Le Google Play Store révoque les autorisations USE_FULL_SCREEN_INTENT par défaut pour toutes les applications qui ne correspondent pas à ce profil. La date limite pour appliquer ces modifications est le 31 mai 2024.
Cette autorisation reste activée pour les applications installées sur le téléphone avant que l'utilisateur passe à Android 14. Les utilisateurs peuvent activer et désactiver cette autorisation.
Vous pouvez utiliser la nouvelle API NotificationManager.canUseFullScreenIntent pour vérifier si votre application dispose de l'autorisation. Sinon, votre application peut utiliser le nouvel intent ACTION_MANAGE_APP_USE_FULL_SCREEN_INTENT pour afficher la page des paramètres où les utilisateurs peuvent accorder l'autorisation.
Sécurité
Restrictions concernant les intents implicites et en attente
Pour les applications ciblant Android 14 (niveau d'API 34) ou version ultérieure, Android empêche les applications d'envoyer des intents implicites à des composants d'application internes comme suit:
- Les intents implicites ne sont transmis qu'aux composants exportés. Les applications doivent utiliser un intent explicite pour transmettre les composants non exportés, ou marquer le composant comme exporté.
- Si une application crée un intent en attente modifiable avec un intent qui ne spécifie pas de composant ou de package, le système génère une exception.
Ces modifications empêchent les applications malveillantes d'intercepter les intents implicites destinés à être utilisés par les composants internes d'une application.
Par exemple, voici un filtre d'intent qui peut être déclaré dans le fichier manifeste de votre application:
<activity
android:name=".AppActivity"
android:exported="false">
<intent-filter>
<action android:name="com.example.action.APP_ACTION" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
Si votre application a tenté de lancer cette activité à l'aide d'un intent implicite, une exception ActivityNotFoundException sera générée :
Kotlin
// Throws an ActivityNotFoundException exception when targeting Android 14. context.startActivity(Intent("com.example.action.APP_ACTION"))
Java
// Throws an ActivityNotFoundException exception when targeting Android 14. context.startActivity(new Intent("com.example.action.APP_ACTION"));
Pour lancer l'activité non exportée, votre application doit utiliser un intent explicite :
Kotlin
// This makes the intent explicit. val explicitIntent = Intent("com.example.action.APP_ACTION") explicitIntent.apply { package = context.packageName } context.startActivity(explicitIntent)
Java
// This makes the intent explicit. Intent explicitIntent = new Intent("com.example.action.APP_ACTION") explicitIntent.setPackage(context.getPackageName()); context.startActivity(explicitIntent);
Les broadcasts receivers enregistrés lors de l'exécution doivent spécifier le comportement d'exportation
Les applications et les services qui ciblent Android 14 (niveau d'API 34) ou version ultérieure et utilisent des récepteurs enregistrés en contexte doivent spécifier un indicateur pour indiquer si le récepteur doit être, ou non, exporté vers toutes les autres applications de l'appareil: RECEIVER_EXPORTED ou RECEIVER_NOT_EXPORTED, respectivement.
Cette exigence permet de protéger les applications contre les failles de sécurité en tirant parti des fonctionnalités pour ces récepteurs introduites dans Android 13.
Exception pour les récepteurs qui ne reçoivent que des annonces du système
Si votre application n'enregistre un récepteur que pour les annonces du système via les méthodes Context#registerReceiver, telles que Context#registerReceiver(), aucun indicateur ne doit être spécifié lors de l'enregistrement du récepteur.
Chargement de code dynamique plus sécurisé
If your app targets Android 14 (API level 34) or higher and uses Dynamic Code Loading (DCL), all dynamically-loaded files must be marked as read-only. Otherwise, the system throws an exception. We recommend that apps avoid dynamically loading code whenever possible, as doing so greatly increases the risk that an app can be compromised by code injection or code tampering.
If you must dynamically load code, use the following approach to set the dynamically-loaded file (such as a DEX, JAR, or APK file) as read-only as soon as the file is opened and before any content is written:
Kotlin
val jar = File("DYNAMICALLY_LOADED_FILE.jar") val os = FileOutputStream(jar) os.use { // Set the file to read-only first to prevent race conditions jar.setReadOnly() // Then write the actual file content } val cl = PathClassLoader(jar, parentClassLoader)
Java
File jar = new File("DYNAMICALLY_LOADED_FILE.jar"); try (FileOutputStream os = new FileOutputStream(jar)) { // Set the file to read-only first to prevent race conditions jar.setReadOnly(); // Then write the actual file content } catch (IOException e) { ... } PathClassLoader cl = new PathClassLoader(jar, parentClassLoader);
Handle dynamically-loaded files that already exist
To prevent exceptions from being thrown for existing dynamically-loaded files, we recommend deleting and recreating the files before you try to dynamically load them again in your app. As you recreate the files, follow the preceding guidance for marking the files read-only at write time. Alternatively, you can re-label the existing files as read-only, but in this case, we strongly recommend that you verify the integrity of the files first (for example, by checking the file's signature against a trusted value), to help protect your app from malicious actions.
Restrictions supplémentaires concernant le démarrage d'activités en arrière-plan
Pour les applications ciblant Android 14 (niveau d'API 34) ou version ultérieure, le système restreint davantage le moment où les applications sont autorisées à lancer des activités en arrière-plan:
- Lorsqu'une application envoie un
PendingIntentà l'aide dePendingIntent#send()ou de méthodes similaires, elle doit l'activer si elle souhaite accorder ses propres privilèges de lancement d'activité en arrière-plan pour déclencher l'intent en attente. Pour l'activer, l'application doit transmettre un bundleActivityOptionsavecsetPendingIntentBackgroundActivityStartMode(MODE_BACKGROUND_ACTIVITY_START_ALLOWED). - Lorsqu'une application visible associe un service à une autre application en arrière-plan à l'aide de la méthode
bindService(), elle doit désormais l'activer si elle souhaite accorder ses propres privilèges de lancement d'activité d'arrière-plan au service lié. Pour l'activer, l'application doit inclure l'indicateurBIND_ALLOW_ACTIVITY_STARTSlors de l'appel de la méthodebindService().
Ces modifications étendent l'ensemble de restrictions existant afin de protéger les utilisateurs en empêchant les applications malveillantes d'utiliser les API de manière abusive pour démarrer des activités d'interruption en arrière-plan.
Traversée de répertoire ZIP
Pour les applications ciblant Android 14 (niveau d'API 34) ou version ultérieure, Android empêche la faille de traversée de répertoire ZIP de la manière suivante : ZipFile(String) et ZipInputStream.getNextEntry() génèrent un ZipException si les noms des entrées de fichiers ZIP contiennent ".." ou commencent par "/".
Les applications peuvent désactiver cette validation en appelant dalvik.system.ZipPathValidator.clearCallback().
Consentement de l'utilisateur requis pour chaque session de capture MediaProjection
Pour les applications ciblant Android 14 (niveau d'API 34) ou version ultérieure, une exception SecurityException est générée par MediaProjection#createVirtualDisplay dans l'un des scénarios suivants:
- Votre application met en cache le
Intentrenvoyé parMediaProjectionManager#createScreenCaptureIntentet le transmet plusieurs fois àMediaProjectionManager#getMediaProjection. - Votre application appelle
MediaProjection#createVirtualDisplayplusieurs fois sur la même instanceMediaProjection.
Votre application doit demander à l'utilisateur de donner son consentement avant chaque session de capture. Une session de capture unique correspond à une seule invocation sur MediaProjection#createVirtualDisplay, et chaque instance MediaProjection ne doit être utilisée qu'une seule fois.
Gérer les modifications de configuration
Si votre application doit appeler MediaProjection#createVirtualDisplay pour gérer les modifications de configuration (telles que l'orientation ou la taille de l'écran), vous pouvez suivre ces étapes pour mettre à jour VirtualDisplay pour l'instance MediaProjection existante:
- Appelez
VirtualDisplay#resizeavec la nouvelle largeur et la nouvelle hauteur. - Fournissez un nouvel élément
Surfaceavec la nouvelle largeur et la nouvelle hauteur àVirtualDisplay#setSurface.
Enregistrer un rappel
Votre application doit enregistrer un rappel pour gérer les cas où l'utilisateur ne donne pas son autorisation pour poursuivre une session de capture. Pour ce faire, implémentez Callback#onStop et demandez à votre application de libérer toutes les ressources associées (telles que VirtualDisplay et Surface).
Si votre application n'enregistre pas ce rappel, MediaProjection#createVirtualDisplay génère une exception IllegalStateException lorsque votre application l'appelle.
Mise à jour des restrictions non SDK
Android 14 inclut des listes à jour d'interfaces non SDK limitées grâce à la collaboration avec les développeurs Android et aux derniers tests internes. Dans la mesure du possible, nous nous assurons que des alternatives publiques sont disponibles avant de limiter les interfaces non SDK.
Si votre application ne cible pas Android 14, certaines de ces modifications ne vous affecteront peut-être pas immédiatement. Cependant, bien que vous puissiez actuellement utiliser certaines interfaces non SDK (en fonction du niveau d'API cible de votre application), l'utilisation d'un champ ou d'une méthode non SDK présente toujours un risque élevé d'endommager votre application.
Si vous n'êtes pas sûr que votre application utilise des interfaces non SDK, vous pouvez tester votre application pour le savoir. Si votre application repose sur des interfaces non SDK, vous devriez commencer à planifier une migration vers des alternatives SDK. Nous comprenons néanmoins que certaines applications ont des cas d'utilisation valides pour utiliser des interfaces non SDK. Si vous ne trouvez pas d'alternative à l'utilisation d'une interface non SDK pour une fonctionnalité de votre application, vous devriez demander une nouvelle API publique.
Pour en savoir plus sur les modifications apportées à cette version d'Android, consultez la section Mises à jour des restrictions d'interface non SDK dans Android 14. Pour en savoir plus sur les interfaces non SDK en général, consultez la section Restrictions concernant les interfaces non SDK.