Im Folgenden finden Sie die Änderungen an diesen anzeigespezifischen Bereichen:
Systemdekorationen
Android 10 unterstützt die Konfiguration sekundärer Displays, um bestimmte Systemdekorationen wie Hintergrund, Navigationsleiste und Launcher anzuzeigen. Auf dem primären Display werden standardmäßig alle Systemdekorationen angezeigt, auf sekundären Displays nur die optional aktivierten. Die Unterstützung für einen Eingabemethoden-Editor (IME) kann getrennt von anderen Systemdekorationen festgelegt werden.
Verwenden Sie DisplayWindowSettings#setShouldShowSystemDecorsLocked()
, um die Unterstützung für Systemdekorationen auf einem bestimmten Display hinzuzufügen, oder geben Sie einen Standardwert in /data/system/display_settings.xml
an. Beispiele finden Sie unter Einstellungen für das Anzeigefenster.
Implementierung
DisplayWindowSettings#setShouldShowSystemDecorsLocked()
ist auch in WindowManager#setShouldShowSystemDecors()
für Tests verfügbar. Wenn Sie diese Methode auslösen, um Systemdekorationen zu aktivieren, werden keine zuvor fehlenden Dekorfenster hinzugefügt und keine zuvor vorhandenen entfernt. In den meisten Fällen werden die Änderungen an der Unterstützung von Systemdekorationen erst nach einem Neustart des Geräts vollständig wirksam.
Prüfungen der Unterstützung von Systemdekorationen in der WindowManager-Codebasis erfolgen in der Regel über DisplayContent#supportsSystemDecorations()
, während Prüfungen externer Dienste (z. B. der System-UI, um zu prüfen, ob die Navigationsleiste angezeigt werden soll) über WindowManager#shouldShowSystemDecors()
erfolgen.
Sehen Sie sich die Aufrufpunkte dieser Methoden an, um zu verstehen, was durch diese Einstellung gesteuert wird.
Dekorfenster der System-UI
In Android 10 wird die Unterstützung von Systemdekorfenstern nur für die Navigationsleiste hinzugefügt, da diese für die Navigation zwischen Aktivitäten und Apps unerlässlich ist. Standardmäßig werden in der Navigationsleiste die Optionen „Zurück“ und „Startseite“ angezeigt. Dieser Wert ist nur enthalten, wenn das Zieldisplay Systemdekorationen unterstützt (siehe DisplayWindowSettings
).
Die Statusleiste ist ein komplexeres Systemfenster, da sie auch die Benachrichtigungsleiste, die Schnelleinstellungen und den Sperrbildschirm enthält. Unter Android 10 wird die Statusleiste auf sekundären Displays nicht unterstützt. Daher sind Benachrichtigungen, Einstellungen und ein vollständiger Keyguard nur auf dem Hauptdisplay verfügbar.
Das Systemfenster Übersicht/Letzte wird auf sekundären Bildschirmen nicht unterstützt. In Android 10 zeigt AOSP nur die letzten Aktivitäten auf dem Standarddisplay an und enthält Aktivitäten von allen Displays. Wenn Sie die App über die letzten Aktivitäten starten, wird eine Aktivität, die sich auf einem sekundären Display befand, standardmäßig auf diesem Display angezeigt. Dieser Ansatz hat einige bekannte Probleme, z. B. dass die Daten nicht sofort aktualisiert werden, wenn Apps auf anderen Bildschirmen angezeigt werden.
Implementierung
Wenn Gerätehersteller zusätzliche System-UI-Funktionen implementieren möchten, sollten sie eine einzelne System-UI-Komponente verwenden, die das Hinzufügen oder Entfernen von Displays überwacht und entsprechende Inhalte präsentiert.
Eine System-UI-Komponente, die Multi-Display (MD) unterstützt, sollte die folgenden Fälle behandeln:
- Mehrere Displays beim Start initialisieren
- Zur Laufzeit hinzugefügtes Display
- Anzeige wird bei Laufzeit entfernt
Wenn die System-UI das Hinzufügen eines Displays vor dem WindowManager erkennt, entsteht eine Race-Condition. Sie können dies vermeiden, indem Sie einen benutzerdefinierten Callback vom WindowManager an die System-UI implementieren, wenn ein Display hinzugefügt wird, anstatt DisplayManager.DisplayListener
-Ereignisse zu abonnieren. Eine Referenzimplementierung für die Navigationsleiste finden Sie unter CommandQueue.Callbacks#onDisplayReady
und für Hintergründe unter WallpaperManagerInternal#onDisplayReady
.
Außerdem bietet Android 10 folgende Updates:
- Mit der Klasse
NavigationBarController
werden alle Funktionen gesteuert, die speziell für Navigationsleisten gelten. - Eine benutzerdefinierte Navigationsleiste finden Sie unter
CarStatusBar
. TYPE_NAVIGATION_BAR
ist nicht mehr auf eine einzelne Instanz beschränkt und kann pro Display verwendet werden.IWindowManager#hasNavigationBar()
wird aktualisiert, um den ParameterdisplayId
nur für die Systemoberfläche zu enthalten.
Startbildschirm
In Android 10 hat jedes Display, das für die Unterstützung von Systemdekorationen konfiguriert ist, standardmäßig einen eigenen Start-Stack für Launcher-Aktivitäten vom Typ WindowConfiguration#ACTIVITY_TYPE_HOME
. Für jedes Display wird eine separate Instanz der Launcher-Aktivität verwendet.
Abbildung 1: Beispiel für einen Launcher für mehrere Displays für platform/development/samples/MultiDisplay
Die meisten vorhandenen Launcher unterstützen keine mehrere Instanzen und sind nicht für große Bildschirme optimiert. Außerdem wird auf sekundären/externen Displays oft eine andere Art von Darstellung erwartet. Um eine spezielle Aktivität für sekundäre Bildschirme bereitzustellen, wird in Android 10 die Kategorie SECONDARY_HOME
in Intent-Filtern eingeführt. Instanzen dieser Aktivität werden auf allen Displays verwendet, die Systemdekorationen unterstützen, jeweils eine pro Display.
<activity> ... <intent-filter> <category android:name="android.intent.category.SECONDARY_HOME" /> ... </intent-filter> </activity>
Die Aktivität muss einen Startmodus haben, der mehrere Instanzen nicht verhindert und sich an unterschiedliche Bildschirmgrößen anpassen kann. Der Startmodus darf nicht singleInstance
oder singleTask
sein.
Implementierung
Unter Android 10 wird die gewünschte Komponente und Intent von RootActivityContainer#startHomeOnDisplay()
automatisch ausgewählt, je nachdem, auf welchem Display der Startbildschirm gestartet wird. RootActivityContainer#resolveSecondaryHomeActivity()
enthält die Logik zum Abrufen der Launcher-Aktivitätskomponente je nach aktuell ausgewähltem Launcher und kann bei Bedarf die Standardeinstellung des Systems verwenden (siehe ActivityTaskManagerService#getSecondaryHomeIntent()
).
Sicherheitseinschränkungen
Zusätzlich zu den Einschränkungen, die für Aktivitäten auf sekundären Displays gelten, wird der Launcher nur auf virtuellen Displays angezeigt, die dem System gehören. So soll verhindert werden, dass eine schädliche App ein virtuelles Display mit aktivierten Systemdekorationen erstellt und nutzersensible Informationen von der Oberfläche liest. Der Launcher zeigt keine Inhalte auf nicht systemeigenen virtuellen Displays an.
Hintergründe
Unter Android 10 und höher werden Hintergründe auf sekundären Displays unterstützt:
Abbildung 2: Live-Hintergrund auf dem internen (oben) und externen Display (unten)
Entwickler können die Unterstützung für die Hintergrundfunktion angeben, indem sie android:supportsMultipleDisplays="true"
in der WallpaperInfo
-XML-Definition angeben. Entwickler von Hintergründen müssen außerdem Assets mit dem Displaykontext in WallpaperService.Engine#getDisplayContext()
laden.
Das Framework erstellt eine WallpaperService.Engine
-Instanz pro Display, sodass jede Engine eine eigene Oberfläche und einen eigenen Displaykontext hat. Der Entwickler muss dafür sorgen, dass jede Engine unabhängig und mit unterschiedlichen Frameraten gezeichnet werden kann, wobei VSYNC berücksichtigt werden muss.
Hintergründe für einzelne Bildschirme auswählen
Android 10 bietet keine direkte Plattformunterstützung für die Auswahl von Hintergründen für einzelne Bildschirme. Dazu ist eine stabile Display-ID erforderlich, um die Hintergrundeinstellungen pro Display beizubehalten.
Display#getDisplayId()
ist dynamisch. Es kann also nicht garantiert werden, dass ein physisches Display nach dem Neustart dieselbe ID hat.
In Android 10 wurde jedoch DisplayInfo.mAddress
hinzugefügt, das stabile IDs für physische Displays enthält und in Zukunft für eine vollständige Implementierung verwendet werden kann. Leider ist es zu spät, die Logik für Android 10 zu implementieren. Vorgeschlagene Lösung:
- Verwenden Sie die
WallpaperManager
API, um die Hintergründe festzulegen. WallpaperManager
wird aus einemContext
-Objekt abgerufen. JedesContext
-Objekt enthält Informationen zum entsprechenden Display (Context#getDisplay()/getDisplayId()
). Daher können SiedisplayId
aus einerWallpaperManager
-Instanz abrufen, ohne neue Methoden hinzuzufügen.- Verwenden Sie auf Framework-Seite
displayId
, das aus einemContext
-Objekt stammt, und ordnen Sie es einer statischen Kennung zu (z. B. einem Anschluss eines physischen Displays). Verwenden Sie die statische Kennung, um den ausgewählten Hintergrund beizubehalten.
Bei dieser Problemumgehung werden vorhandene Implementierungen für Hintergrundauswahlen verwendet. Wenn die App auf einem bestimmten Display geöffnet wurde und den richtigen Kontext verwendet, kann das System das Display automatisch erkennen, wenn es darum gebeten wird, einen Hintergrund festzulegen.
Wenn Sie den Hintergrund für ein anderes Display als das aktuelle Display festlegen möchten, erstellen Sie ein neues Context
-Objekt für das Zieldisplay (Context#createDisplayContext
) und rufen Sie die WallpaperManager
-Instanz von diesem Display ab.
Sicherheitseinschränkungen
Das System zeigt auf virtuellen Displays keine Hintergrundbilder an, die nicht zu ihm gehören. Dies liegt an einem Sicherheitsrisiko, da eine schädliche App ein virtuelles Display mit aktivierter Unterstützung für Systemdekorationen erstellen und nutzerbezogene Informationen von der Oberfläche lesen könnte, z. B. ein privates Foto.
Implementierung
Unter Android 10 akzeptieren die IWallpaperConnection#attachEngine()
- und IWallpaperService#attach()
-Benutzeroberflächen den Parameter displayId
, um pro Display Verbindungen herzustellen.
WallpaperManagerService.DisplayConnector
umschließt eine pro Display konfigurierte Hintergrund-Engine und -Verbindung. Im WindowManager werden bei der Erstellung für jedes DisplayContent
-Objekt Hintergrundcontroller erstellt, anstatt ein einzelnes WallpaperController
für alle Displays.
Einige der öffentlichen Implementierungen der WallpaperManager
-Methode (z. B. WallpaperManager#getDesiredMinimumWidth()
) wurden aktualisiert, um Informationen für entsprechende Displays zu berechnen und bereitzustellen.
WallpaperInfo#supportsMultipleDisplays()
und ein entsprechendes Ressourcenattribut wurden hinzugefügt, damit App-Entwickler angeben können, welche Hintergründe für mehrere Bildschirme geeignet sind.
Wenn der Hintergrunddienst, der auf dem Standarddisplay angezeigt wird, keine mehreren Displays unterstützt, zeigt das System auf den sekundären Displays den Standardhintergrund an.
Abbildung 3. Fallback-Logik für Hintergrundbilder auf sekundären Displays