Auf dieser Seite finden Sie Empfehlungen für die Arbeit mit mehreren Displays.
Apps für faltbare Geräte und Geräte mit mehreren Bildschirmen
Im Allgemeinen sollten sich Apps nicht auf statische IDs oder Logik verlassen, die von bestimmten Display-IDs abhängt. In den meisten Fällen sollten Apps die Größe an verschiedene Displays anpassen und auf diesen funktionieren. Das System sollte steuern, wo Apps platziert werden. Beispielsweise können Sie eine neue und einzigartige Benutzeroberfläche für faltbare Geräte entwickeln und eine spezielle App auf dem externen Bildschirm starten, wenn das Gerät zusammengeklappt ist.
In diesem Fall sollte die System-UI oder eine andere Systemkomponente das Zusammenklappen erkennen, feststellen, ob eine Aktion ausgeführt werden soll, und dann die Zielaktivität starten und eine externe Display-ID als Startziel angeben. Apps sollten diese Aktion nicht erkennen oder darauf reagieren und dann den Start auf einem bestimmten Display ausführen. Gehen Sie also nicht davon aus, dass das, was auf einem Gerät funktioniert, auch auf anderen Geräten funktioniert. Kurz gesagt: Gerätespezifischer Code erhöht die Fragmentierung.
Zugriff auf Displays einschränken
Wenn die Gerätekonfiguration eine Einschränkung des Zugriffs auf ein oder mehrere Displays erfordert, empfehlen wir, das Flag Display#FLAG_PRIVATE zu verwenden, um das Display als privat zu kennzeichnen. Durch diese Kennzeichnung wird verhindert, dass alle außer dem Inhaber Inhalte zum Display hinzufügen können. Wenn eine andere Person als der Inhaber versucht, eine Aktivität zu starten oder ein Fenster hinzuzufügen, wird SecurityException ausgelöst.
Wenn das System der Inhaber des Displays ist, kann es Fenster hinzufügen und Aktivitäten starten.
Außerdem können Entitäten, die auf einem Display platziert werden, immer auf dieses Display zugreifen. Wenn der Inhaber eine Aktivität auf einem Display startet, kann die Aktivität andere Aktivitäten auf diesem Display starten. Daher ist der Inhaber dafür verantwortlich, den Zugriff einzuschränken und nur vertrauenswürdigen Apps den Zugriff zu erlauben.
Darüber hinaus werden virtuelle Displays stärker eingeschränkt, da jede App ein virtuelles Display erstellen kann, ohne es für den Nutzer sichtbar zu machen. Wenn das virtuelle Display nicht dem System gehört, sind nur Aktivitäten mit allowEmbedded zulässig und der Aufrufer muss die Berechtigung ACTIVITY_EMBEDDING haben.
Weitere Informationen finden Sie unter:
ActivityStackSupervisor#isCallerAllowedToLaunchOnDisplayActivityDisplay#isUidPresentDisplayManagerService#isUidPresentOnDisplay
Verwenden Sie LaunchParamsController, um Aktivitätsstarts bedingt zu steuern. Diese Komponente fängt alle Aktivitätsstarts ab und ermöglicht es einer Systemkomponente, die für den Start verwendeten Parameter zu ändern. Sie ist in system_server verfügbar.
Einstellungen für Displayfenster und Systemdekorationen konfigurieren
Systemdekorationen können
in DisplayWindowSettings pro Display konfiguriert werden. Eine Geräteimplementierung kann eine Standardkonfiguration in /data/system/display_settings.xml bereitstellen.
Dieser Wert bestimmt, ob Systemdekorationen (Launcher, Hintergrundbild, Navigationsleiste und andere Dekorfenster) und die IME auf einem Display angezeigt werden.
Weitere Informationen finden Sie unter DisplayWindowSettings#shouldShowSystemDecorsLocked und DisplayWindowSettings#shouldShowImeLocked.
Verwenden Sie entweder eine eindeutige ID (standardmäßig wird DisplayInfo#uniqueId verwendet) oder eine physische Port-ID für Hardware-Displays (siehe DisplayInfo#address), um das Display zu identifizieren.
Das folgende Beispiel für die Displaykonfiguration aktiviert Systemdekorationen und die IME auf einem simulierten Display:
<?xml version='1.0' encoding='utf-8' standalone='yes' ?> <display-settings> <config identifier="0" /> <display name="overlay:1" shouldShowSystemDecors="true" shouldShowIme="true" /> </display-settings>
Im obigen Beispiel wird uniqueId zur Display-ID im Attribut „name“ verwendet. Für ein simuliertes Display ist das overlay:1.
Für ein integriertes Display könnte ein Beispielwert "local:45354385242535243453" sein.
Eine weitere Möglichkeit besteht darin, Informationen zum Hardware-Port zu verwenden und identifier="1"
so festzulegen, dass es DisplayWindowSettings#IDENTIFIER_PORT entspricht. Aktualisieren Sie dann den
Namen im 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>
Weitere Informationen finden Sie unter Statische Display-IDs.
Weitere Informationen finden Sie unter:
Displays zwischen Spiegeln und Hosten von Aufgaben wechseln
In Android 17 und höher verwendet DisplayManager das
FLAG_ALLOWS_CONTENT_MODE_SWITCH Flag, um zu steuern, ob ein Display zur Laufzeit
zwischen Spiegeln und Hosten von Aufgaben wechselt. Standardmäßig ist dieses Flag für externe Displays aktiviert und für alle anderen Displays deaktiviert.
Wenn FLAG_ALLOWS_CONTENT_MODE_SWITCH vorhanden ist, überwacht DisplayManager die sichere Einstellung android.provider.Settings.Secure.MIRROR_BUILT_IN_DISPLAY, um zu bestimmen, ob Aufgaben gespiegelt oder gehostet werden sollen. Dies ist die Standardlogik, aber OEMs können dieses Verhalten anpassen.
Displaytopologie und Mauszeigerbewegung
In Android 17 und höher definiert die Displaytopologie die relativen Positionen von Displays und beschränkt die Mauszeigerbewegung auf die spezifische Gruppe von Displays in der Topologie.
WindowManager entscheidet, ob ein Display in die Topologie aufgenommen werden soll, und ruft DisplayManagerInternal.onDisplayBelongToTopologyChanged auf. DisplayManager
prüft DisplayTopologyCoordinator.isDisplayAllowedInTopology, bevor das Display hinzugefügt wird. Wenn lokale Displays Aufgaben hosten können, werden sie standardmäßig vom System hinzugefügt.
Wenn mehrere öffentliche Displays vorhanden sind, die Aufgaben hosten können, wird die Entscheidung, das Standarddisplay einzubeziehen, vom booleschen Anbieter shouldIncludeDefaultDisplayInTopology getroffen, der an DisplayTopologyCoordinator übergeben wird. Wenn das Standarddisplay das einzige öffentliche Display ist, das Aufgaben hosten kann, ist es immer in der Topologie enthalten. In AOSP gibt der boolesche Anbieter nur dann true zurück, wenn das Standarddisplay Desktopfenster unterstützt oder wenn die sichere Einstellung Settings.Secure.INCLUDE_DEFAULT_DISPLAY_IN_TOPOLOGY auf true gesetzt ist.
Apps fragen die aktuelle Topologie mit DisplayManager.getDisplayTopology ab und reagieren auf Änderungen an der Topologie, indem sie einen Listener mit DisplayManager.registerTopologyListener registrieren.