Zalecane metody

Na tej stronie znajdziesz rekomendacje dotyczące pracy z wieloma wyświetlaczami.

Aplikacje na urządzenia składane i urządzenia z wieloma ekranami

Aplikacje nie powinny opierać się na statycznych identyfikatorach ani logice, która zależy od identyfikatorów wyświetlaczy. 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 i unikalne wrażenia na urządzeniach składanych oraz uruchomić specjalną aplikację na ekranie zewnętrznym, gdy urządzenie jest złożone.

W takim przypadku interfejs systemowy 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ć identyfikator wyświetlacza zewnętrznego jako cel uruchomienia. Aplikacje nie powinny wykrywać tego działania ani wykonywać żadnego działania w odpowiedzi, a następnie uruchamiać aplikacji na określonym wyświetlaczu. Nie zakładaj więc, ż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 1 wyświetlacza, zalecamy użycie flagi Display#FLAG_PRIVATE, aby oznaczyć wyświetlacz jako prywatny. To oznaczenie uniemożliwia dodawanie treści do wyświetlacza wszystkim użytkownikom oprócz właściciela. Jeśli ktoś inny niż właściciel spróbuje uruchomić aktywność lub dodać okno, zostanie wywołany wyjątek SecurityException. Jeśli wyświetlacz jest własnością systemu, system może dodawać okna i uruchamiać aktywności.

Ponadto encje umieszczone na wyświetlaczu zawsze mają do niego dostęp. Jeśli właściciel uruchomi aktywność na wyświetlaczu, aktywność ta może uruchamiać inne aktywności na tym wyświetlaczu. W rezultacie właściciel jest odpowiedzialny za ograniczenie dostępu i zezwolenie tylko zaufanym aplikacjom.

Dodatkowo do wyświetlaczy wirtualnych dodano więcej ograniczeń, ponieważ każda aplikacja może utworzyć taki wyświetlacz bez udostępniania go użytkownikowi. Jeśli wyświetlacz wirtualny nie jest własnością systemu, dozwolone są tylko aktywności z flagą allowEmbedded, a wywołujący powinien mieć uprawnienie ACTIVITY_EMBEDDING.

Więcej informacji znajdziesz w tych artykułach:

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

Aby warunkowo kontrolować uruchamianie aktywności, użyj LaunchParamsController, który przechwytuje wszystkie uruchomienia aktywności i umożliwia komponentowi systemu modyfikowanie parametrów używanych do uruchamiania. Jest to dostępne w system_server.

Konfigurowanie ustawień okien wyświetlacza i dekoracji systemowych

Dekoracje systemowe można skonfigurować dla każdego wyświetlacza w DisplayWindowSettings. Implementacja urządzenia może udostępniać konfigurację domyślną w pliku /data/system/display_settings.xml.

Ta wartość określa, czy na wyświetlaczu mają się pojawiać dekoracje systemowe (launcher, tapeta, pasek nawigacyjny i inne okna dekoracji) oraz IME. Więcej informacji znajdziesz w artykułach DisplayWindowSettings#shouldShowSystemDecorsLocked i DisplayWindowSettings#shouldShowImeLocked.

Aby zidentyfikować wyświetlacz, użyj unikalnego identyfikatora (domyślnie jest to DisplayInfo#uniqueId) lub identyfikatora portu fizycznego w przypadku wyświetlaczy sprzętowych (patrz DisplayInfo#address).

Na przykład poniższa konfiguracja wyświetlacza włącza dekoracje systemowe i 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 do identyfikacji wyświetlacza w atrybucie name używany jest uniqueId, który w przypadku symulowanego wyświetlacza ma wartość overlay:1. W przypadku wyświetlacza wbudowanego przykładowa wartość może wyglądać tak: "local:45354385242535243453". Możesz też użyć informacji o porcie sprzętowym i ustawić identifier="1" aby odpowiadał on 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 artykule Statyczne identyfikatory wyświetlaczy.

Więcej informacji znajdziesz w tych artykułach:

Przełączanie wyświetlaczy między zadaniami dublowania i hostowania

W Androidzie 17 i nowszych wersjach DisplayManager używa flagi FLAG_ALLOWS_CONTENT_MODE_SWITCH, aby kontrolować, czy wyświetlacz przełącza się między zadaniami dublowania i hostowania zadań w czasie działania. Domyślnie ta flaga jest włączona w przypadku wyświetlaczy zewnętrznych i wyłączona w przypadku wszystkich innych wyświetlaczy.

Gdy flaga FLAG_ALLOWS_CONTENT_MODE_SWITCH jest obecna, DisplayManager monitoruje bezpieczne ustawienie android.provider.Settings.Secure.MIRROR_BUILT_IN_DISPLAY, aby określić, czy dublować, czy hostować zadania. Jest to domyślna logika, ale producenci OEM mogą dostosować to zachowanie.

Topologia wyświetlacza i ruch wskaźnika

W Androidzie 17 i nowszych wersjach topologia wyświetlacza określa względne położenie wyświetlaczy i ogranicza ruch wskaźnika myszy do określonego zestawu wyświetlaczy w topologii.

WindowManager decyduje o uwzględnieniu wyświetlacza w topologii i wywołuje DisplayManagerInternal.onDisplayBelongToTopologyChanged. Przed dodaniem wyświetlacza DisplayManager sprawdza DisplayTopologyCoordinator.isDisplayAllowedInTopology. Domyślnie system dodaje wyświetlacze lokalne, jeśli mogą one hostować zadania.

Jeśli jest kilka wyświetlaczy publicznych, które mogą hostować zadania, decyzję o uwzględnieniu wyświetlacza domyślnego podejmuje dostawca wartości logicznej shouldIncludeDefaultDisplayInTopology, który jest przekazywany do DisplayTopologyCoordinator. Jeśli wyświetlacz domyślny jest jedynym wyświetlaczem publicznym, który może hostować zadania, zawsze znajduje się w topologii. W AOSP dostawca wartości logicznej zwraca wartość true tylko wtedy, gdy wyświetlacz domyślny 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.