Changements de comportement: applications ciblant Android 15 ou version ultérieure

Comme les versions précédentes, Android 15 inclut des modifications de comportement susceptibles d'affecter votre application. Les modifications de comportement suivantes ne s'appliquent qu'aux applications ciblant Android 15 ou version ultérieure. Si votre application cible Android 15 ou une version ultérieure, vous devez modifier votre application pour prendre en charge ces comportements correctement, applicables.

N'oubliez pas de consulter également la liste des modifications de comportement qui affectent toutes les applications fonctionnant sous Android 15, quelle que soit la targetSdkVersion de votre application.

Fonctionnalité de base

Android 15 modifie ou étend diverses fonctionnalités de base du système Android.

Modifications apportées aux services de premier plan

Nous apportons les modifications suivantes aux services de premier plan avec Android 15.

Comportement du délai avant expiration du service de synchronisation des données de premier plan

Android 15 introduit un nouveau comportement de délai d'inactivité dans dataSync pour le ciblage des applications Android 15 (niveau d'API 35) ou version ultérieure Ce comportement s'applique également Type de service de premier plan mediaProcessing.

Le système autorise les services dataSync d'une application à s'exécuter pendant six heures au total dans une période de 24 heures, après quoi le système appelle Méthode Service.onTimeout(int, int) (introduite dans Android) 15). Pour l'instant, le service dispose de quelques secondes pour appeler Service.stopSelf() Lorsque Service.onTimeout() est appelé, le n'est plus considéré comme un service de premier plan. Si ce n'est pas le cas, appelez Service.stopSelf(), le système génère une exception interne. La est consignée dans Logcat avec le message suivant:

Fatal Exception: android.app.RemoteServiceException: "A foreground service of
type dataSync did not stop within its timeout: [component name]"

Pour éviter tout problème lié à ce changement de comportement, vous pouvez effectuer une ou plusieurs des suivantes:

  1. Demandez à votre service d'implémenter la nouvelle méthode Service.onTimeout(int, int). Lorsque votre application reçoit le rappel, veillez à appeler stopSelf() dans un en quelques secondes. Si vous n'arrêtez pas l'application immédiatement, le système génère un d'échec.)
  2. Assurez-vous que les services dataSync de votre appli ne s'exécutent pas pendant plus de 6 heures par période de 24 heures (sauf si l'utilisateur interagit avec l'application, en réinitialisant le minuteur).
  3. Démarrer uniquement les services de premier plan dataSync à la suite d'un utilisateur direct d'interaction ; puisque votre application est exécutée au premier plan lorsque le service démarre, votre service dispose des six heures complètes après la mise en arrière-plan de l'application.
  4. Au lieu d'utiliser un service de premier plan dataSync, utilisez un API alternative.

Si les dataSync services de premier plan de votre appli ont été exécutés pendant six heures au cours des dernières 24, vous ne pouvez pas démarrer un autre service de premier plan dataSync à moins que l'utilisateur a mis votre application au premier plan (ce qui réinitialise le minuteur). Si vous essayez de démarrer un autre service de premier plan dataSync, le système génère ForegroundServiceStartNotAllowedException avec un message d'erreur du type : "Time limit already exceeded pour le service de premier plan" "dataSync".

Tests

Pour tester le comportement de votre application, vous pouvez activer des délais avant expiration de la synchronisation des données même si votre application ne cible pas Android 15 (tant que l'application est exécutée sur un appareil Android 15) appareil). Pour activer les délais avant expiration, exécutez la commande adb suivante:

adb shell am compat enable FGS_INTRODUCE_TIME_LIMITS your-package-name

Vous pouvez également ajuster ce délai pour tester plus facilement l'application se comporte lorsque la limite est atteinte. Pour définir un nouveau délai d'expiration, exécutez la la commande adb suivante:

adb shell device_config put activity_manager data_sync_fgs_timeout_duration duration-in-milliseconds

Nouveau type de service de premier plan pour le traitement multimédia

Android 15 introduces a new foreground service type, mediaProcessing. This service type is appropriate for operations like transcoding media files. For example, a media app might download an audio file and need to convert it to a different format before playing it. You can use a mediaProcessing foreground service to make sure the conversion continues even while the app is in the background.

The system permits an app's mediaProcessing services to run for a total of 6 hours in a 24-hour period, after which the system calls the running service's Service.onTimeout(int, int) method (introduced in Android 15). At this time, the service has a few seconds to call Service.stopSelf(). If the service does not call Service.stopSelf(), the system throws an internal exception. The exception is logged in Logcat with the following message:

Fatal Exception: android.app.RemoteServiceException: "A foreground service of
type mediaProcessing did not stop within its timeout: [component name]"

To avoid having the exception, you can do one of the following:

  1. Have your service implement the new Service.onTimeout(int, int) method. When your app receives the callback, make sure to call stopSelf() within a few seconds. (If you don't stop the app right away, the system generates a failure.)
  2. Make sure your app's mediaProcessing services don't run for more than a total of 6 hours in any 24-hour period (unless the user interacts with the app, resetting the timer).
  3. Only start mediaProcessing foreground services as a result of direct user interaction; since your app is in the foreground when the service starts, your service has the full six hours after the app goes to the background.
  4. Instead of using a mediaProcessing foreground service, use an alternative API, like WorkManager.

If your app's mediaProcessing foreground services have run for 6 hours in the last 24, you cannot start another mediaProcessing foreground service unless the user has brought your app to the foreground (which resets the timer). If you try to start another mediaProcessing foreground service, the system throws ForegroundServiceStartNotAllowedException with an error message like "Time limit already exhausted for foreground service type mediaProcessing".

For more information about the mediaProcessing service type, see Changes to foreground service types for Android 15: Media processing.

Testing

To test your app's behavior, you can enable media processing timeouts even if your app is not targeting Android 15 (as long as the app is running on an Android 15 device). To enable timeouts, run the following adb command:

adb shell am compat enable FGS_INTRODUCE_TIME_LIMITS your-package-name

You can also adjust the timeout period, to make it easier to test how your app behaves when the limit is reached. To set a new timeout period, run the following adb command:

adb shell device_config put activity_manager media_processing_fgs_timeout_duration duration-in-milliseconds

Restrictions concernant les broadcast receivers BOOT_COMPLETED qui lancent des services de premier plan

There are new restrictions on BOOT_COMPLETED broadcast receivers launching foreground services. BOOT_COMPLETED receivers are not allowed to launch the following types of foreground services:

If a BOOT_COMPLETED receiver tries to launch any of those types of foreground services, the system throws ForegroundServiceStartNotAllowedException.

Testing

To test your app's behavior, you can enable these new restrictions even if your app is not targeting Android 15 (as long as the app is running on an Android 15 device). Run the following adb command:

adb shell am compat enable FGS_BOOT_COMPLETED_RESTRICTIONS your-package-name

To send a BOOT_COMPLETED broadcast without restarting the device, run the following adb command:

adb shell am broadcast -a android.intent.action.BOOT_COMPLETED your-package-name

Restrictions concernant le démarrage des services de premier plan lorsqu'une application détient l'autorisation SYSTEM_ALERT_WINDOW

Previously, if an app held the SYSTEM_ALERT_WINDOW permission, it could launch a foreground service even if the app was currently in the background (as discussed in exemptions from background start restrictions).

If an app targets Android 15, this exemption is now narrower. The app now needs to have the SYSTEM_ALERT_WINDOW permission and also have a visible overlay window. That is, the app needs to first launch a TYPE_APPLICATION_OVERLAY window and the window needs to be visible before you start a foreground service.

If your app attempts to start a foreground service from the background without meeting these new requirements (and it does not have some other exemption), the system throws ForegroundServiceStartNotAllowedException.

If your app declares the SYSTEM_ALERT_WINDOW permission and launches foreground services from the background, it may be affected by this change. If your app gets a ForegroundServiceStartNotAllowedException, check your app's order of operations and make sure your app already has an active overlay window before it attempts to start a foreground service from the background. You can check if your overlay window is currently visible by calling View.getWindowVisibility(), or you can override View.onWindowVisibilityChanged() to get notified whenever the visibility changes.

Testing

To test your app's behavior, you can enable these new restrictions even if your app is not targeting Android 15 (as long as the app is running on an Android 15 device). To enable these new restrictions on starting foreground services from the background, run the following adb command:

adb shell am compat enable FGS_SAW_RESTRICTIONS your-package-name

Modifications concernant les cas dans lesquels les applications peuvent modifier l'état général du mode Ne pas déranger

Les applications qui ciblent Android 15 ne peuvent plus modifier l'état ni la règle globaux du mode Ne pas déranger sur un appareil (en modifiant les paramètres utilisateur ou en désactivant le mode Ne pas déranger). À la place, les applications doivent contribuer à un AutomaticZenRule, que le système combine dans une règle globale avec le schéma "most-restrictive-policy-wins" existant. Les appels d'API existantes qui ont précédemment affecté l'état global (setInterruptionFilter, setNotificationPolicy) entraînent la création ou la mise à jour d'un AutomaticZenRule implicite, qui est activé ou désactivé en fonction du cycle d'appel de ces appels d'API.

Notez que cette modification n'affecte le comportement observable que si l'application appelle setInterruptionFilter(INTERRUPTION_FILTER_ALL) et s'attend à ce que cet appel désactive un AutomaticZenRule précédemment activé par ses propriétaires.

Modifications apportées à l'API OpenJDK

Android 15 continues the work of refreshing Android's core libraries to align with the features in the latest OpenJDK LTS releases.

Some of these changes can affect app compatibility for apps targeting Android 15 (API level 35):

  • Changes to string formatting APIs: Validation of argument index, flags, width, and precision are now more strict when using the following String.format() and Formatter.format() APIs:

    For example, the following exception is thrown when an argument index of 0 is used (%0 in the format string):

    IllegalFormatArgumentIndexException: Illegal format argument index = 0
    

    In this case, the issue can be fixed by using an argument index of 1 (%1 in the format string).

  • Changes to component type of Arrays.asList(...).toArray(): When using Arrays.asList(...).toArray(), the component type of the resulting array is now an Object—not the type of the underlying array's elements. So the following code throws a ClassCastException:

    String[] elements = (String[]) Arrays.asList("one", "two").toArray();
    

    For this case, to preserve String as the component type in the resulting array, you could use Collection.toArray(Object[]) instead:

    String[] elements = Arrays.asList("two", "one").toArray(new String[0]);
    
  • Changes to language code handling: When using the Locale API, language codes for Hebrew, Yiddish, and Indonesian are no longer converted to their obsolete forms (Hebrew: iw, Yiddish: ji, and Indonesian: in). When specifying the language code for one of these locales, use the codes from ISO 639-1 instead (Hebrew: he, Yiddish: yi, and Indonesian: id).

  • Changes to random int sequences: Following the changes made in https://bugs.openjdk.org/browse/JDK-8301574, the following Random.ints() methods now return a different sequence of numbers than the Random.nextInt() methods do:

    Generally, this change shouldn't result in app-breaking behavior, but your code shouldn't expect the sequence generated from Random.ints() methods to match Random.nextInt().

The new SequencedCollection API can affect your app's compatibility after you update compileSdk in your app's build configuration to use Android 15 (API level 35):

  • Collision with MutableList.removeFirst() and MutableList.removeLast() extension functions in kotlin-stdlib

    The List type in Java is mapped to the MutableList type in Kotlin. Because the List.removeFirst() and List.removeLast() APIs have been introduced in Android 15 (API level 35), the Kotlin compiler resolves function calls, for example list.removeFirst(), statically to the new List APIs instead of to the extension functions in kotlin-stdlib.

    If an app is re-compiled with compileSdk set to 35 and minSdk set to 34 or lower, and then the app is run on Android 14 and lower, a runtime error is thrown:

    java.lang.NoSuchMethodError: No virtual method
    removeFirst()Ljava/lang/Object; in class Ljava/util/ArrayList;
    

    The existing NewApi lint option in Android Gradle Plugin can catch these new API usages.

    ./gradlew lint
    
    MainActivity.kt:41: Error: Call requires API level 35 (current min is 34): java.util.List#removeFirst [NewApi]
          list.removeFirst()
    

    To fix the runtime exception and lint errors, the removeFirst() and removeLast() function calls can be replaced with removeAt(0) and removeAt(list.lastIndex) respectively in Kotlin. If you're using Android Studio Ladybug | 2024.1.3 or higher, it also provides a quick fix option for these errors.

    Consider removing @SuppressLint("NewApi") and lintOptions { disable 'NewApi' } if the lint option has been disabled.

  • Collision with other methods in Java

    New methods have been added into the existing types, for example, List and Deque. These new methods might not be compatible with the methods with the same name and argument types in other interfaces and classes. In the case of a method signature collision with incompatibility, the javac compiler outputs a build-time error. For example:

    Example error 1:

    javac MyList.java
    
    MyList.java:135: error: removeLast() in MyList cannot implement removeLast() in List
      public void removeLast() {
                  ^
      return type void is not compatible with Object
      where E is a type-variable:
        E extends Object declared in interface List
    

    Example error 2:

    javac MyList.java
    
    MyList.java:7: error: types Deque<Object> and List<Object> are incompatible;
    public class MyList implements  List<Object>, Deque<Object> {
      both define reversed(), but with unrelated return types
    1 error
    

    Example error 3:

    javac MyList.java
    
    MyList.java:43: error: types List<E#1> and MyInterface<E#2> are incompatible;
    public static class MyList implements List<Object>, MyInterface<Object> {
      class MyList inherits unrelated defaults for getFirst() from types List and MyInterface
      where E#1,E#2 are type-variables:
        E#1 extends Object declared in interface List
        E#2 extends Object declared in interface MyInterface
    1 error
    

    To fix these build errors, the class implementing these interfaces should override the method with a compatible return type. For example:

    @Override
    public Object getFirst() {
        return List.super.getFirst();
    }
    

Sécurité

Android 15 inclut des modifications qui renforcent la sécurité du système afin de protéger les applications et les utilisateurs des applications malveillantes.

Lancement de l'activité en arrière-plan sécurisée

Android 15 protège les utilisateurs des applications malveillantes et leur donne plus de contrôle sur leurs appareils en ajoutant des modifications qui empêchent les applications malveillantes en arrière-plan le fait de placer d'autres applications au premier plan, d'élever leurs privilèges et d'abuser l'interaction de l'utilisateur. Le lancement des activités en arrière-plan est limité depuis Android 10 (niveau d'API 29).

Empêcher les applications qui ne correspondent pas à l'UID supérieur de la pile de lancer des activités

Des applications malveillantes peuvent lancer l'activité d'une autre application au cours de la même tâche, puis se superposent, créant ainsi l'illusion d'être cette application. Cette « tâche détournement de contenu" contourne les restrictions de lancement actuelles en arrière-plan, se produit dans la même tâche visible. Pour atténuer ce risque, Android 15 ajoute indicateur qui empêche le lancement des applications ne correspondant pas à l'UID supérieur de la pile activités. Pour activer toutes les activités de votre application, mettez à jour le allowCrossUidActivitySwitchFromBelow dans le fichier AndroidManifest.xml de votre application:

<application android:allowCrossUidActivitySwitchFromBelow="false" >

Les nouvelles mesures de sécurité sont actives si toutes les conditions suivantes sont remplies:

  • L'application effectuant le lancement cible Android 15.
  • L'application située au-dessus de la pile de tâches cible Android 15.
  • Toutes les activités visibles sont activées pour les nouvelles protections

Si les mesures de sécurité sont activées, il est possible que les applis reviennent à l'écran d'accueil dernière application visible, s'il termine sa propre tâche.

Autres modifications

En plus de la restriction concernant la mise en correspondance des identifiants uniques, ces modifications inclus:

  • Modifiez les créateurs PendingIntent pour qu'ils bloquent les activités en arrière-plan en par défaut. Cela permet d'éviter que les applications ne créent accidentellement PendingIntent susceptibles d'être utilisés de manière abusive par des acteurs malveillants.
  • Ne mettez une application au premier plan que si l'expéditeur PendingIntent le permet. Ce changement vise à empêcher les applications malveillantes d'utiliser abusivement les Possibilité de démarrer des activités en arrière-plan Par défaut, les applications ne sont pas autorisé à faire passer la pile de tâches au premier plan, sauf si le créateur l'autorise droits de lancement de l'activité en arrière-plan ou si l'expéditeur a une activité en arrière-plan les droits de lancement.
  • Contrôlez la façon dont l'activité principale d'une pile de tâches peut terminer sa tâche. Si le l'activité principale termine une tâche, Android revient à la tâche dernière activité. De plus, si une activité non principale termine sa tâche, Android retournez à l'écran d'accueil, il ne bloquera pas l'arrivée activité.
  • Empêcher le lancement d'activités arbitraires provenant d'autres applications dans la vôtre tâche. Ce changement empêche les applications malveillantes d'hameçonnage des utilisateurs en créant activités qui semblent provenir d'autres applications.
  • Empêcher les fenêtres non visibles d'être prises en compte pour l'activité en arrière-plan lancements. Cela permet d'éviter que les applications malveillantes utilisent l'arrière-plan de manière abusive. se lance pour présenter du contenu indésirable ou malveillant aux utilisateurs.

Intents plus sécurisés

Android 15 introduit de nouvelles mesures de sécurité pour renforcer la sécurité des intents robustes. Ces changements visent à prévenir les vulnérabilités potentielles et usage abusif d'intents pouvant être exploités par des applications malveillantes. Il existe deux principaux Améliorations apportées à la sécurité des intents dans Android 15:

  • Faire correspondre les filtres d'intent cibles:les intents qui ciblent des composants spécifiques doivent correspondent précisément aux spécifications de filtre d'intent de la cible. Si vous envoyez une pour lancer l'activité d'une autre application, le composant d'intent cible doit s'aligner sur les filtres d'intent déclarés de l'activité de réception.
  • Les intents doivent comporter des actions:les intents sans action ne seront plus mis en correspondance. tous les filtres d'intent. Cela signifie que les intents utilisés pour démarrer des activités services doivent être clairement définis.
  • Intents en attente:le créateur de l'intent en attente est traité comme l'expéditeur de l'intent englobant, et non comme l'expéditeur de l'intent en attente intention

Kotlin


fun onCreate() {
    StrictMode.setVmPolicy(VmPolicy.Builder()
        .detectUnsafeIntentLaunch()
        .build()
    )
}

Java


public void onCreate() {
    StrictMode.setVmPolicy(new VmPolicy.Builder()
            .detectUnsafeIntentLaunch()
            .build());
}

Expérience utilisateur et UI du système

Android 15 inclut certaines modifications visant à créer un environnement plus cohérent, une expérience utilisateur intuitive.

Modifications de l'encart de la fenêtre

Il existe deux modifications liées aux encarts de fenêtre dans Android 15: l'application bord à bord est appliquée par défaut, et il existe également des modifications de configuration, telles que la configuration par défaut des barres système.

Application bord à bord

Les applications sont bord à bord par défaut sur les appareils équipés d'Android 15 si elles sont ciblant Android 15 (niveau d'API 35).

<ph type="x-smartling-placeholder">
</ph>
Une application qui cible Android 14 et qui n'est pas de bord à bord sur Appareil Android 15


<ph type="x-smartling-placeholder">
</ph>
Une application qui cible Android 15 (niveau d'API 35) et qui est de bord à bord sur un appareil Android 15. Cette application utilise principalement des composants Compose Material 3 qui appliquent automatiquement les encarts. Cet écran n'est pas affecté par le Application bord à bord Android 15

Il s'agit d'une modification destructive qui pourrait avoir un impact négatif sur l'interface utilisateur de votre application. La les modifications affectent les zones d'interface utilisateur suivantes:

  • Barre de navigation par gestes <ph type="x-smartling-placeholder">
      </ph>
    • Transparent par défaut.
    • Le décalage inférieur est désactivé afin que le contenu s'affiche derrière la navigation système sauf si des encarts sont appliqués.
    • setNavigationBarColor et R.attr#navigationBarColor sont obsolète et n'affectent pas la navigation par gestes.
    • setNavigationBarContrastEnforced et R.attr#navigationBarContrastEnforced n'ont toujours aucun effet sur la navigation par gestes.
  • Navigation à trois boutons <ph type="x-smartling-placeholder">
      </ph>
    • L'opacité est définie sur 80% par défaut, et la couleur peut correspondre à celle de la fenêtre. en arrière-plan.
    • Décalage inférieur désactivé afin que le contenu s'affiche derrière la barre de navigation système sauf si des encarts sont appliqués.
    • setNavigationBarColor et R.attr#navigationBarColor sont définie pour correspondre à l'arrière-plan de la fenêtre par défaut. Arrière-plan de la fenêtre doit être un drawable couleur pour que cette valeur par défaut s'applique. Cette API est obsolète mais continue à affecter la navigation à trois boutons.
    • setNavigationBarContrastEnforced et R.attr#navigationBarContrastEnforced est défini sur "true" par défaut, ce qui ajoute Arrière-plan opaque à 80% pour une navigation à trois boutons.
  • Barre d'état <ph type="x-smartling-placeholder">
      </ph>
    • Transparent par défaut.
    • Le décalage supérieur est désactivé afin que le contenu s'affiche derrière la barre d'état, sauf et des encarts sont appliqués.
    • setStatusBarColor et R.attr#statusBarColor sont obsolètes et n'ont aucun effet sur Android 15.
    • setStatusBarContrastEnforced et R.attr#statusBarContrastEnforced sont obsolètes, mais ont toujours une sur Android 15.
  • Encoche <ph type="x-smartling-placeholder">
      </ph>
    • layoutInDisplayCutoutMode des fenêtres non flottantes doivent être LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS SHORT_EDGES, NEVER et Les DEFAULT sont interprétés comme ALWAYS, de sorte que les utilisateurs ne voient pas causée par l'encoche et s'affiche de bord à bord.

L'exemple suivant présente une application avant et après le ciblage Android 15 (niveau d'API 35), et avant et après l'application des encarts.

<ph type="x-smartling-placeholder">
</ph>
Une application qui cible Android 14 et qui n'est pas de bord à bord sur Appareil Android 15
Une application qui cible Android 15 (niveau d'API 35) et qui est de bord à bord sur un appareil Android 15. Toutefois, de nombreux éléments sont désormais masqués par l'état la barre de navigation, la barre de navigation à trois boutons ou l'encoche du fait d'Android 15, les mesures d'application de bord à bord. L'interface utilisateur masquée inclut Material 2 la barre d'application supérieure, les boutons d'action flottants et les éléments de liste.
Une application qui cible Android 15 (niveau d'API 35) est bord à bord un appareil Android 15 et applique des encarts afin que l'UI ne soit pas masquées.
Comment vérifier si votre application est déjà de bord à bord ?

Si votre application est déjà bord à bord et applique des encarts, n'ont quasiment aucun impact, sauf dans les cas suivants. Cependant, même si vous pensez vous n'êtes pas concerné, nous vous recommandons de tester votre application.

  • Vous disposez d'une fenêtre non flottante, telle qu'une Activity qui utilise SHORT_EDGES, NEVER ou DEFAULT au lieu de LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS Si votre application plante au lancement, en raison de votre écran de démarrage. Vous pouvez soit mettre à niveau le core splashscreen par rapport à 1.2.0-alpha01 ou une version ultérieure, ou définissez window.attributes.layoutInDisplayCutoutMode = WindowManager.LayoutInDisplayCutoutMode.always.
  • Il est possible que l'interface utilisateur soit masquée sur des écrans à faible trafic. Vérifier ces éléments les écrans moins consultés n'ont pas d'interface utilisateur obstruée. Les écrans qui affichent moins de trafic sont les suivants: <ph type="x-smartling-placeholder">
      </ph>
    • Écrans d'accueil ou de connexion
    • Pages de paramètres
Vérifier si votre application n'est pas déjà bord à bord

Si votre application n'est pas déjà bord à bord, vous êtes probablement affecté. Dans en plus des scénarios d'applications déjà bord à bord, tenez compte des éléments suivants:

  • Si votre application utilise des composants Material 3 ( androidx.compose.material3) dans Compose, par exemple TopAppBar, BottomAppBar et NavigationBar, il est probable que ces composants ne soient pas car ils gèrent automatiquement les encarts.
  • Si votre application utilise des composants Material 2 ( androidx.compose.material) dans Compose, ces composants ne gèrent pas automatiquement les encarts. Cependant, vous pouvez accéder aux encarts et les appliquer manuellement. Dans androidx.compose.material 1.6.0 puis utilisez le paramètre windowInsets pour appliquer les encarts manuellement BottomAppBar, TopAppBar BottomNavigation et NavigationRail. De même, utilisez le paramètre contentWindowInsets pour Scaffold
  • Si votre application utilise des vues et des composants Material (com.google.android.material), Material Design principalement basé sur les vues Des composants tels que BottomNavigationView, BottomAppBar, NavigationRailView ou NavigationView gèrent les encarts et ne nécessitent aucune travail supplémentaire. Cependant, vous devez ajouter android:fitsSystemWindows="true" si vous utilisez AppBarLayout.
  • Pour les composables personnalisés, appliquez manuellement les encarts en tant que marge intérieure. Si votre contenu dans un Scaffold, vous pouvez utiliser des encarts à l'aide de l'Scaffold les valeurs de marge intérieure. Sinon, appliquez une marge intérieure à l'aide de l'une des WindowInsets
  • Si votre application utilise des vues et des BottomSheet, SideSheet ou personnalisées des conteneurs, appliquez un remplissage à l'aide de ViewCompat.setOnApplyWindowInsetsListener Pour RecyclerView, appliquer une marge intérieure à l'aide de cet écouteur et ajouter clipToPadding="false"
Points à vérifier si votre application doit proposer une protection personnalisée en arrière-plan

Si votre application doit offrir une protection personnalisée en arrière-plan pour la navigation à trois boutons ou la barre d'état, votre application doit placer un composable ou une vue derrière la barre système avec WindowInsets.Type#tappableElement() pour obtenir les trois boutons hauteur de la barre de navigation ou WindowInsets.Type#statusBars.

Ressources de bord à bord supplémentaires

Consultez les vues Edge à Edge et Edge to Edge Compose. pour en savoir plus sur l'application d'encarts.

API obsolètes

Les API suivantes sont désormais obsolètes:

Configuration stable

Si votre application cible Android 15 (niveau d'API 35) ou une version ultérieure, Configuration non exclut plus longtemps les barres système. Si vous utilisez la taille de l'écran dans la classe Configuration pour le calcul de la mise en page, vous devez la remplacer par de meilleures alternatives, comme un ViewGroup, WindowInsets ou WindowMetricsCalculator approprié, en fonction de vos besoins.

Configuration est disponible depuis l'API 1. Elle est généralement obtenue à partir de Activity.onConfigurationChanged Il fournit des informations telles que la densité des fenêtres, l'orientation et les tailles. Une caractéristique importante des tailles de fenêtre renvoyées par Configuration est qu'elles excluaient auparavant les barres système.

La taille de configuration sert généralement à sélectionner des ressources, par exemple /res/layout-h500dp, et ce cas d'utilisation reste valide. Cependant, son utilisation pour le calcul de mise en page a toujours été déconseillé. Si c'est le cas, vous devez vous en éloigner immédiatement. Vous devez remplacer l'utilisation de Configuration par quelque chose plus adapté à votre cas d'utilisation.

Si vous l'utilisez pour calculer la mise en page, utilisez un ViewGroup approprié, tel que CoordinatorLayout ou ConstraintLayout. Si vous l'utilisez pour déterminer la hauteur de la barre de navigation du système, utilisez WindowInsets. Si vous voulez connaître la taille actuelle de la fenêtre de votre application, utilisez computeCurrentWindowMetrics.

La liste suivante décrit les champs concernés par cette modification :

  • Les tailles Configuration.screenWidthDp et screenHeightDp ne sont plus disponibles exclure les barres système.
  • Configuration.smallestScreenWidthDp est indirectement affecté par les modifications apportées à screenWidthDp et screenHeightDp.
  • Configuration.orientation est indirectement affecté par les modifications apportées à screenWidthDp et screenHeightDp sur les appareils presque carrés.
  • Display.getSize(Point) est indirectement affecté par les modifications apportées à Configuration Cette méthode a été abandonnée à partir du niveau d'API 30.
  • Display.getMetrics() fonctionne déjà de cette manière depuis le niveau d'API 33.

Par défaut, l'attribut élégantTextHeight est défini sur "true".

Pour les applications ciblant Android 15, l'attribut elegantTextHeight TextView devient true par défaut, en remplaçant la police compacte utilisée par défaut par certains scripts associés à de grandes métriques verticales par un autre plus lisible. La police compacte a été introduite pour éviter de perturber les mises en page. Android 13 (niveau d'API 33) empêche bon nombre de ces failles en permettant à la mise en page du texte d'étirer la hauteur verticale à l'aide de l'attribut fallbackLineSpacing.

Dans Android 15, la police compacte reste dans le système. Votre application peut donc définir elegantTextHeight sur false pour obtenir le même comportement qu'auparavant, mais elle ne sera probablement pas compatible avec les prochaines versions. Ainsi, si votre application est compatible avec les scripts suivants (arabe, laotien, birman, gujarati, kannada, malayalam, odia, télougou ou thaï), testez-la en définissant elegantTextHeight sur true.

Comportement elegantTextHeight pour les applications ciblant Android 14 (niveau d'API 34) ou version antérieure.
Comportement de elegantTextHeight pour les applications ciblant Android 15.

Modifications de la largeur de TextView pour les lettres complexes

In previous versions of Android, some cursive fonts or languages that have complex shaping might draw the letters in the previous or next character's area. In some cases, such letters were clipped at the beginning or ending position. Starting in Android 15, a TextView allocates width for drawing enough space for such letters and allows apps to request extra paddings to the left to prevent clipping.

Because this change affects how a TextView decides the width, TextView allocates more width by default if the app targets Android 15 (API level 35) or higher. You can enable or disable this behavior by calling the setUseBoundsForWidth API on TextView.

Because adding left padding might cause a misalignment for existing layouts, the padding is not added by default even for apps that target Android 15 or higher. However, you can add extra padding to preventing clipping by calling setShiftDrawingOffsetForStartOverhang.

The following examples show how these changes can improve text layout for some fonts and languages.

Standard layout for English text in a cursive font. Some of the letters are clipped. Here is the corresponding XML:

<TextView
    android:fontFamily="cursive"
    android:text="java" />
Layout for the same English text with additional width and padding. Here is the corresponding XML:

<TextView
    android:fontFamily="cursive"
    android:text="java"
    android:useBoundsForWidth="true"
    android:shiftDrawingOffsetForStartOverhang="true" />
Standard layout for Thai text. Some of the letters are clipped. Here is the corresponding XML:

<TextView
    android:text="คอมพิวเตอร์" />
Layout for the same Thai text with additional width and padding. Here is the corresponding XML:

<TextView
    android:text="คอมพิวเตอร์"
    android:useBoundsForWidth="true"
    android:shiftDrawingOffsetForStartOverhang="true" />

Hauteur de ligne par défaut en fonction des paramètres régionaux pour EditText

In previous versions of Android, the text layout stretched the height of the text to meet the line height of the font that matched the current locale. For example, if the content was in Japanese, because the line height of the Japanese font is slightly larger than the one of a Latin font, the height of the text became slightly larger. However, despite these differences in line heights, the EditText element was sized uniformly, regardless of the locale being used, as illustrated in the following image:

Three boxes representing EditText elements that can contain text from English (en), Japanese (ja), and Burmese (my). The height of the EditText is the same, even though these languages have different line heights from each other.

For apps targeting Android 15 (API level 35), a minimum line height is now reserved for EditText to match the reference font for the specified Locale, as shown in the following image:

Three boxes representing EditText elements that can contain text from English (en), Japanese (ja), and Burmese (my). The height of the EditText now includes space to accommodate the default line height for these languages' fonts.

If needed, your app can restore the previous behavior by specifying the useLocalePreferredLineHeightForMinimum attribute to false, and your app can set custom minimum vertical metrics using the setMinimumFontMetrics API in Kotlin and Java.

Appareil photo et contenus multimédias

Android 15 apporte les modifications suivantes au comportement de l'appareil photo et des contenus multimédias pour les applications qui ciblent Android 15 ou version ultérieure.

Restrictions concernant la demande de priorité audio

Les applications qui ciblent Android 15 doivent être l'application principale ou exécuter un service de premier plan pour demander la priorité audio. Si une application tente de demander la sélection alors qu'elle ne répond pas à l'une de ces exigences, l'appel renvoie AUDIOFOCUS_REQUEST_FAILED.

Pour en savoir plus sur la priorité audio, consultez Gérer la priorité audio.

Mise à jour des restrictions non SDK

Android 15 inclut des listes à jour de listes d'autorisations non SDK limitées grâce à une collaboration avec des développeurs Android 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 15, certaines de ces modifications ne vous affecteront peut-être pas immédiatement. Cependant, bien que votre application puisse accéder à 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 ne savez pas si votre application utilise des interfaces non SDK, vous pouvez Testez votre application pour le savoir. Si votre application repose sur un outil non SDK vous devez commencer à planifier une migration vers des alternatives SDK. Néanmoins, nous comprenons que certaines applications ont des cas d'utilisation valables interfaces non SDK. Si vous ne trouvez pas d'alternative à l'utilisation d'un autre SDK d'une fonctionnalité de votre application, vous devez demander une nouvelle API publique.

Pour en savoir plus sur les modifications apportées à cette version d'Android, consultez Mises à jour des restrictions des interfaces non SDK dans Android 15. Pour en savoir plus sur les interfaces non SDK de manière générale, consultez la section Restrictions concernant les interfaces non SDK.