Pratiques recommandées

Applications pour les appareils pliables et multi-écrans

En règle générale, les applications ne doivent pas s'appuyer sur des identifiants statiques ni sur une logique qui dépend de certains ID d'écran. Dans la plupart des cas, les applications doivent être redimensionnées et fonctionner sur différents écrans, et le système doit contrôler l'emplacement des applications. Par exemple, pour créer une expérience nouvelle et unique pour les appareils pliables et lancer une application spéciale sur l'écran externe lorsque l'appareil est plié.

Dans ce cas, SystemUI (ou un autre composant système) doit détecter le pli, déterminer s'il est approprié d'effectuer une action, puis lancer l'activité cible et spécifier un ID d'écran externe comme cible de lancement. Les applications ne doivent pas détecter cette action ni effectuer d'action en réponse, puis effectuer le lancement sur un écran spécifique. En d'autres termes, ne partez pas du principe que ce qui fonctionne sur un appareil fonctionnera sur d'autres. En bref, le code spécifique à l'appareil augmente la fragmentation.

Restreindre l'accès aux écrans

Si la configuration de l'appareil nécessite de restreindre l'accès à un ou plusieurs écrans, nous vous recommandons d'utiliser l'indicateur Display#FLAG_PRIVATE pour désigner ces écrans comme privés. Cela empêche tous les utilisateurs, à l'exception du propriétaire, d'ajouter du contenu à l'écran. Toute tentative de lancement d'une activité ou d'ajout d'une fenêtre par une personne autre que le propriétaire entraîne une SecurityException. Si le système est propriétaire de l'écran, il peut ajouter des fenêtres et lancer des activités.

De plus, les entités placées sur un écran peuvent toujours y accéder. Si le propriétaire lance une activité sur un écran, cette activité peut lancer d'autres activités sur cet écran. Par conséquent, le propriétaire est responsable de la restriction de l'accès et de l'autorisation des applications de confiance uniquement.

De plus, des restrictions supplémentaires sont ajoutées aux écrans virtuels, car n'importe quelle application peut en créer un sans le rendre visible pour l'utilisateur. Si l'écran virtuel n'appartient pas au système, seules les activités avec allowEmbedded sont autorisées et l'appelant doit disposer de l'autorisation ACTIVITY_EMBEDDING.

Pour en savoir plus, consultez les pages suivantes :

  • ActivityStackSupervisor#isCallerAllowedToLaunchOnDisplay()
  • ActivityDisplay#isUidPresent()
  • DisplayManagerService#isUidPresentOnDisplay()

Pour contrôler de manière conditionnelle les lancements d'activités, utilisez LaunchParamsController, qui intercepte tous les lancements d'activités et permet à un composant système de modifier les paramètres utilisés pour le lancement. Cette fonctionnalité est disponible dans system_server.

Configurer les paramètres de fenêtrage de l'écran et les décorations système

Les décorations système peuvent être configurées par écran dans DisplayWindowSettings. Une implémentation d'appareil peut fournir une configuration par défaut dans /data/system/display_settings.xml.

Cette valeur détermine si les décorations système (lanceur, fond d'écran, barre de navigation et autres fenêtres de décoration) et l'IME s'affichent sur un écran. Pour en savoir plus, consultez DisplayWindowSettings#shouldShowSystemDecorsLocked() et DisplayWindowSettings#shouldShowImeLocked().

Pour identifier l'écran, utilisez un ID unique (par défaut, DisplayInfo#uniqueId) ou un ID de port physique pour les écrans matériels (voir DisplayInfo#address).

Par exemple, la configuration d'écran suivante active les décorations système et l'IME sur un écran simulé :

<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<display-settings>
<config identifier="0" />
<display
  name="overlay:1"
  shouldShowSystemDecors="true"
  shouldShowIme="true" />
</display-settings>

Dans l'exemple ci-dessus, uniqueId est utilisé pour l'identification de l'écran dans l'attribut name, qui pour un écran simulé est overlay:1. Pour un écran intégré, un exemple de valeur peut être "local:45354385242535243453". Une autre option consiste à utiliser les informations du port matériel et à définir identifier="1" pour qu'il corresponde à DisplayWindowSettings#IDENTIFIER_PORT, puis à mettre à jour le nom pour utiliser le format "port:<port_id>" :

<?xmlversion='1.0' encoding='utf-8' standalone='yes' ?>
<display-settings>
<config identifier="1" />
<display
  name="port:12345"
  shouldShowSystemDecors="true"
  shouldShowIme="true" />
</display-settings>

Pour en savoir plus, consultez Identifiants d'écran statiques.

Pour en savoir plus, consultez les pages suivantes :

Basculer entre les tâches de mise en miroir et d'hébergement des écrans

Dans Android 17 et versions ultérieures, DisplayManager utilise l' FLAG_ALLOWS_CONTENT_MODE_SWITCH indicateur pour contrôler si un écran bascule entre les tâches de mise en miroir et d'hébergement au moment de l'exécution. Par défaut, cet indicateur est activé pour les écrans externes et désactivé pour tous les autres écrans.

Lorsque FLAG_ALLOWS_CONTENT_MODE_SWITCH est présent, DisplayManager surveille le paramètre sécurisé android.provider.Settings.Secure.MIRROR_BUILT_IN_DISPLAY pour déterminer s'il faut mettre en miroir ou héberger des tâches. Bien qu'il s'agisse de la logique par défaut, les OEM peuvent personnaliser ce comportement.

Topologie d'écran et mouvement du pointeur

Dans Android 17 et versions ultérieures, la topologie d'écran définit les positions relatives des écrans et limite le mouvement du pointeur de la souris à l'ensemble spécifique d'écrans de la topologie.

WindowManager décide d'inclure un écran dans la topologie et appelle DisplayManagerInternal.onDisplayBelongToTopologyChanged. DisplayManager vérifie DisplayTopologyCoordinator.isDisplayAllowedInTopology avant d'ajouter l'écran. Par défaut, si les écrans locaux peuvent héberger des tâches, le système les ajoute.

S'il existe plusieurs écrans publics pouvant héberger des tâches, la décision d'inclure l'écran par défaut est gérée par le fournisseur booléen shouldIncludeDefaultDisplayInTopology transmis à DisplayTopologyCoordinator. Si l'écran par défaut est le seul écran public pouvant héberger des tâches, il se trouve toujours dans la topologie. Dans AOSP, le fournisseur booléen ne renvoie true que si l'écran par défaut est compatible avec le fenêtrage du bureau ou si le paramètre sécurisé Settings.Secure.INCLUDE_DEFAULT_DISPLAY_IN_TOPOLOGY est true.

Les applications interrogent la topologie actuelle à l'aide de DisplayManager.getDisplayTopology et réagissent aux modifications de la topologie en enregistrant un écouteur avec DisplayManager.registerTopologyListener.