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 einigen 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. Beispiel: Sie möchten eine neue und einzigartige Nutzererfahrung 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 SystemUI (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 den Start dann auf einem bestimmten Display ausführen. Mit anderen Worten: Gehen Sie nicht davon aus, dass das, was auf einem Gerät funktioniert, auch auf anderen Geräten funktioniert. Gerätespezifischer Code erhöht die Fragmentierung.
Zugriff auf Displays einschränken
Wenn die Gerätekonfiguration die Einschränkung des Zugriffs auf ein oder mehrere Displays erfordert, empfehlen wir, das Flag Display#FLAG_PRIVATE zu verwenden, um diese Displays als privat zu kennzeichnen. Dadurch wird verhindert, dass alle außer dem Eigentümer Inhalte zum Display hinzufügen können. Jeder Versuch, eine Aktivität zu starten oder ein Fenster hinzuzufügen, der nicht vom Eigentümer ausgeführt wird, führt zu einer SecurityException.
Wenn das System Eigentümer 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 Eigentümer eine Aktivität auf einem Display startet, kann die Aktivität andere Aktivitäten auf diesem Display starten. Daher ist der Eigentümer dafür verantwortlich, den Zugriff einzuschränken und nur vertrauenswürdigen Apps den Zugriff zu erlauben.
Außerdem 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#isCallerAllowedToLaunchOnDisplay()ActivityDisplay#isUidPresent()DisplayManagerService#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 kann 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, um das "port:<port_id>" Format zu verwenden:
<?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 Hosting 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 Hosting 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 Desktop-Freiform-Fenster 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.