Aplikacje na urządzenia składane i wielomonitorowe
Zasadniczo aplikacje nie powinny korzystać ze statycznych identyfikatorów ani logiki, która zależy od niektórych identyfikatorów wyświetlania. W większości przypadków aplikacje powinny zmieniać rozmiar i działać na różnych wyświetlaczach, a system powinien kontrolować, gdzie mają się znajdować. Możesz na przykład stworzyć nowe, unikalne rozwiązanie dla urządzeń składanych i uruchamiać specjalną aplikację na ekranie zewnętrznym, gdy urządzenie jest złożone.
W takim przypadku interfejs SystemUI (lub inny komponent systemu) powinien wykryć złożenie, określić, czy należy wykonać działanie, a następnie uruchomić docelową aktywność i określić zewnętrzny identyfikator wyświetlacza jako miejsce docelowe uruchomienia. Aplikacje nie powinny wykrywać tego działania ani wykonywać żadnych działań w odpowiedzi na nie, a następnie uruchamiać się na konkretnym wyświetlaczu. Innymi słowy, nie zakładaj, że to, co działa na jednym urządzeniu, będzie działać na innych. Krótko mówiąc, kod specyficzny dla urządzenia zwiększa fragmentację.
Ograniczanie dostępu do wyświetlaczy
Jeśli konfiguracja urządzenia wymaga ograniczenia dostępu do co najmniej jednego wyświetlacza, zalecamy użycie flagi Display#FLAG_PRIVATE, aby oznaczyć takie wyświetlacze jako prywatne. W ten sposób uniemożliwisz dodawanie treści na wyświetlaczu wszystkim osobom oprócz właściciela. Każda próba uruchomienia aktywności lub dodania okna przez osobę inną niż właściciel kończy się SecurityException.
Jeśli wyświetlacz jest własnością systemu, może on dodawać okna i uruchamiać aktywności.
Ponadto podmioty umieszczone na wyświetlaczu zawsze mają do niego dostęp. Jeśli właściciel uruchomi aktywność na wyświetlaczu, może ona uruchamiać inne aktywności na tym wyświetlaczu. W związku z tym właściciel jest odpowiedzialny za ograniczenie dostępu i zezwalanie na korzystanie tylko z zaufanych aplikacji.
Dodatkowo na wyświetlacze wirtualne nałożono więcej ograniczeń, ponieważ każda aplikacja może utworzyć taki wyświetlacz bez udostępniania go użytkownikowi. Jeśli wirtualny wyświetlacz nie jest własnością systemu, dozwolone są tylko działania z allowEmbedded, a wywołujący musi mieć uprawnienie ACTIVITY_EMBEDDING.
Aby dowiedzieć się więcej, zobacz:
ActivityStackSupervisor#isCallerAllowedToLaunchOnDisplay()ActivityDisplay#isUidPresent()DisplayManagerService#isUidPresentOnDisplay()
Aby warunkowo kontrolować uruchamianie działań, użyj LaunchParamsController, które przechwytuje wszystkie uruchomienia działań i umożliwia komponentowi systemu modyfikowanie parametrów używanych do uruchamiania. Jest ona dostępna w system_server.
Konfigurowanie ustawień okien wyświetlania i dekoracji systemowych
Dekoracje systemowe można skonfigurować dla każdego wyświetlacza w DisplayWindowSettings. Implementacja urządzenia może udostępniać domyślną konfigurację w /data/system/display_settings.xml.
Ta wartość określa, czy na wyświetlaczu mają się pojawiać elementy dekoracyjne systemu (launcher, tapeta, pasek nawigacyjny i inne okna dekoracyjne) oraz IME.
Więcej informacji znajdziesz w sekcjach DisplayWindowSettings#shouldShowSystemDecorsLocked() i DisplayWindowSettings#shouldShowImeLocked().
Aby zidentyfikować wyświetlacz, użyj unikalnego identyfikatora (domyślnie używany jest identyfikator DisplayInfo#uniqueId) lub identyfikatora portu fizycznego w przypadku wyświetlaczy sprzętowych (patrz DisplayInfo#address).
Na przykład poniższa konfiguracja wyświetlania włącza dekoracje systemowe i edytor IME na symulowanym wyświetlaczu:
<?xml version='1.0' encoding='utf-8' standalone='yes' ?> <display-settings> <config identifier="0" /> <display name="overlay:1" shouldShowSystemDecors="true" shouldShowIme="true" /> </display-settings>
W powyższym przykładzie w atrybucie name do identyfikacji wyświetlacza użyto znaku uniqueId, który w przypadku symulowanego wyświetlacza ma wartość overlay:1.
W przypadku wbudowanego wyświetlacza przykładowa wartość może wynosić "local:45354385242535243453".
Możesz też użyć informacji o porcie sprzętowym i ustawić identifier="1", aby odpowiadało DisplayWindowSettings#IDENTIFIER_PORT, a następnie zaktualizować nazwę, aby używać formatu "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>
Więcej informacji znajdziesz w sekcji Statyczne identyfikatory wyświetlania.
Aby dowiedzieć się więcej, zobacz:
Przełączanie wyświetlaczy między klonowaniem a wykonywaniem zadań
W Androidzie 17 i nowszych wersjach DisplayManager używa flagi FLAG_ALLOWS_CONTENT_MODE_SWITCH, aby określić, czy wyświetlacz ma przełączać się w czasie działania między klonowaniem a hostowaniem zadań. Domyślnie ta flaga jest włączona w przypadku wyświetlaczy zewnętrznych i wyłączona w przypadku wszystkich innych wyświetlaczy.
Gdy występuje FLAG_ALLOWS_CONTENT_MODE_SWITCH, DisplayManager monitoruje android.provider.Settings.Secure.MIRROR_BUILT_IN_DISPLAY bezpieczne ustawienie, aby określić, czy ma dublować zadania, czy je hostować. Jest to domyślna logika, ale producenci OEM mogą dostosować to zachowanie.
Wyświetlanie topologii i ruchu wskaźnika
W Androidzie 17 i nowszych wersjach topologia wyświetlaczy określa względne położenie wyświetlaczy i ogranicza ruch wskaźnika myszy do określonego zestawu wyświetlaczy w topologii.
Menedżer okien decyduje o uwzględnieniu wyświetlacza w topologii i wywołuje funkcję
DisplayManagerInternal.onDisplayBelongToTopologyChanged. DisplayManager sprawdza DisplayTopologyCoordinator.isDisplayAllowedInTopology przed dodaniem wyświetlacza. Domyślnie, jeśli wyświetlacze lokalne mogą obsługiwać zadania, system je dodaje.
Jeśli jest wiele wyświetlaczy publicznych, na których można wykonywać zadania, decyzję o uwzględnieniu wyświetlacza domyślnego podejmuje shouldIncludeDefaultDisplayInTopology dostawca wartości logicznej przekazywany do DisplayTopologyCoordinator. Jeśli wyświetlacz domyślny jest jedynym wyświetlaczem publicznym, który może obsługiwać zadania, zawsze znajduje się w topologii. W AOSP wartość logiczna
dostawcy jest zwracana jako true tylko wtedy, gdy domyślny wyświetlacz obsługuje tryb okien na pulpicie
lub gdy bezpieczne ustawienie Settings.Secure.INCLUDE_DEFAULT_DISPLAY_IN_TOPOLOGY
ma wartość true.
Aplikacje wysyłają zapytania o bieżącą topologię za pomocą DisplayManager.getDisplayTopology i reagują na zmiany w topologii, rejestrując odbiornik za pomocą DisplayManager.registerTopologyListener.