Gli aggiornamenti apportati a queste aree specifiche per la visualizzazione sono disponibili in questa pagina.
Decorazioni di sistema
Android 10 aggiunge il supporto per la configurazione di display secondari per mostrare determinate decorazioni di sistema, come sfondo, barra di navigazione e launcher. Per impostazione predefinita, il display principale mostra tutte le decorazioni del sistema, mentre i display secondari mostrano quelle attivate facoltativamente. Puoi impostare il supporto per un editor del metodo di input (IME) separatamente dalle altre decorazioni di sistema.
Utilizza DisplayWindowSettings#setShouldShowSystemDecorsLocked()
per aggiungere il supporto per le decorazioni di sistema su un display specifico o fornire
un valore predefinito in /data/system/display_settings.xml
. Per alcuni esempi,
vedi Impostazioni della finestra di visualizzazione.
Implementazione
DisplayWindowSettings#setShouldShowSystemDecorsLocked()
è esposto anche in
WindowManager#setShouldShowSystemDecors()
per i test. L'attivazione di questo metodo
con l'intento di abilitare le decorazioni di sistema non aggiunge finestre di decorazione
precedentemente mancanti né le rimuove se erano presenti. Nella maggior parte
dei casi, la modifica del supporto delle decorazioni di sistema ha effetto solo dopo il
riavvio del dispositivo.
I controlli per il supporto delle decorazioni di sistema nella base di codice di WindowManager
di solito passano attraverso DisplayContent#supportsSystemDecorations()
, mentre
i controlli per i servizi esterni (come l'interfaccia utente di sistema per verificare se la barra di navigazione
deve essere mostrata) utilizzano WindowManager#shouldShowSystemDecors()
.
Per capire cosa controlla questa impostazione, esplora i punti di chiamata di questi metodi.
Finestre di decorazione dell'interfaccia utente di sistema
Android 10 aggiunge il supporto della finestra di decorazione del sistema
per la barra di navigazione solo, perché la barra di navigazione è essenziale
per spostarsi tra attività e app. Per impostazione predefinita, la barra di navigazione mostra
i pulsanti Indietro e Home. Questo valore è incluso solo se il display di destinazione supporta
le decorazioni di sistema (vedi
DisplayWindowSettings
).
La barra di stato è una finestra di sistema più complessa, perché contiene anche l'area notifiche, le impostazioni rapide e la schermata di blocco. In Android 10, la barra di stato non è supportata sui display secondari. Pertanto, notifiche, impostazioni e tastierino completo sono disponibili solo sul display principale.
La finestra di sistema Panoramica/Recenti non è supportata sugli schermi secondari. In Android 10, AOSP mostra solo Recenti sul display predefinito e contiene attività di tutti i display. Quando viene avviata da Recenti, un'attività che si trovava su un display secondario viene portata in primo piano su quel display, per impostazione predefinita. Questo approccio presenta alcuni problemi noti, ad esempio l'aggiornamento non immediato quando le app vengono visualizzate su altre schermate.
Implementazione
Per implementare funzionalità aggiuntive dell'interfaccia utente di sistema, i produttori di dispositivi devono utilizzare un singolo componente dell'interfaccia utente di sistema che rileva l'aggiunta o la rimozione di display e presenta contenuti appropriati.
Un componente dell'interfaccia utente di sistema che supporta il multi-display (MD) deve gestire i seguenti casi:
- Inizializzazione di più display all'avvio
- Display aggiunto in fase di esecuzione
- Display rimosso in fase di runtime
Quando l'interfaccia utente di sistema rileva l'aggiunta di un display prima di WindowManager, crea
una condizione di competizione. Puoi evitare questo problema implementando un callback personalizzato da WindowManager a System UI quando viene aggiunto un display, anziché abbonarti agli eventi DisplayManager.DisplayListener
. Per un'implementazione di riferimento,
vedi CommandQueue.Callbacks#onDisplayAddSystemDecorations
per il supporto della barra di navigazione
e WallpaperManagerInternal#onDisplayAddSystemDecorations
per gli sfondi.
Inoltre, Android 10 fornisce i seguenti aggiornamenti:
- La classe
NavigationBarController
controlla tutte le funzionalità specifiche delle barre di navigazione. - Per visualizzare una barra di navigazione personalizzata, vedi
CarStatusBar
. TYPE_NAVIGATION_BAR
non è più limitato a una singola istanza e può essere utilizzato per ogni display.IWindowManager#hasNavigationBar()
è stato aggiornato per includere il parametrodisplayId
solo per l'interfaccia utente di sistema.
Avvio applicazioni
In Android 10, ogni display configurato per supportare
le decorazioni di sistema ha uno stack home dedicato per le attività di avvio con tipo
WindowConfiguration#ACTIVITY_TYPE_HOME
, per impostazione predefinita. Ogni display
utilizza un'istanza separata dell'attività di avvio:
Figura 1. Esempio di avvio di più display per platform/development/samples/MultiDisplay.
La maggior parte dei launcher esistenti non supporta più istanze e non è ottimizzata
per le dimensioni dello schermo più grandi. Inoltre, spesso ci si aspetta un'esperienza diversa
sui display secondari/esterni. Per fornire un'attività dedicata per gli schermi secondari, Android 10 ha introdotto la categoria SECONDARY_HOME
nei filtri degli intent. Le istanze di questa attività vengono utilizzate su tutti i display che supportano le decorazioni di sistema, una per display.
<activity> ... <intent-filter> <category android:name="android.intent.category.SECONDARY_HOME" /> ... </intent-filter> </activity>
L'attività deve avere una modalità di avvio che non impedisca più istanze e deve adattarsi a diverse dimensioni dello schermo. La modalità di avvio
non può essere singleInstance
o singleTask
.
Implementazione
In Android 10, RootActivityContainer#startHomeOnDisplay()
seleziona automaticamente il componente e l'intent desiderati a seconda del display
in cui viene avviata la schermata Home. RootActivityContainer#resolveSecondaryHomeActivity()
contiene la logica per cercare il componente di attività del launcher a seconda del launcher attualmente
selezionato e può utilizzare quello predefinito del sistema, se necessario (vedi
ActivityTaskManagerService#getSecondaryHomeIntent()
).
Limitazioni di sicurezza
Oltre alle limitazioni che si applicano alle attività sui display secondari, per evitare la possibilità che un'app dannosa crei un display virtuale con le decorazioni di sistema attive e legga informazioni sensibili dell'utente dalla superficie, il launcher viene visualizzato solo sui display virtuali di proprietà del sistema. Il launcher non mostra contenuti su display virtuali non di sistema.
Sfondi
In Android 10 e versioni successive, gli sfondi sono supportati sui display secondari:
Figura 2. Sfondo animato sui display interno (in alto) ed esterno (in basso).
Gli sviluppatori possono dichiarare il supporto della funzionalità di sfondo fornendo
android:supportsMultipleDisplays="true"
nella
definizione XML WallpaperInfo
. Gli sviluppatori di sfondi devono anche
caricare gli asset utilizzando il contesto di visualizzazione in
WallpaperService.Engine#getDisplayContext()
.
Il framework crea un'istanza WallpaperService.Engine
per display, quindi ogni motore ha la propria superficie e il proprio contesto di visualizzazione. Lo
sviluppatore deve assicurarsi che ogni motore possa disegnare in modo indipendente, a
frequenze dei fotogrammi diverse, rispettando VSync.
Selezionare sfondi per singoli schermi
Android 10 non fornisce supporto diretto della piattaforma per la selezione di sfondi
per singoli schermi. Per farlo, è necessario un identificatore di visualizzazione stabile
per mantenere le impostazioni dello sfondo per ogni display.
Display#getDisplayId()
è dinamico, quindi non vi è alcuna garanzia che un
display fisico abbia lo stesso ID dopo il riavvio.
Tuttavia, Android 10 ha aggiunto DisplayInfo.mAddress
,
che contiene identificatori stabili per i display fisici e può essere utilizzato per un'implementazione
completa in futuro. Purtroppo è troppo tardi per implementare la logica
per Android 10. Soluzione suggerita:
- Utilizza la classe
WallpaperManager
per impostare gli sfondi.WallpaperManager
viene ottenuto da un oggettoContext
e ogni oggettoContext
contiene informazioni sulla visualizzazione corrispondente (Context#getDisplay()/getDisplayId()
). Pertanto, puoi otteneredisplayId
da un'istanzaWallpaperManager
senza aggiungere nuovi metodi. - Sul lato framework, utilizza
displayId
ottenuto da un oggettoContext
e mappalo a un identificatore statico (ad esempio una porta di un display fisico). Utilizza l'identificatore statico per mantenere lo sfondo scelto.
Questa soluzione alternativa utilizza le implementazioni esistenti per i selettori di sfondi. Se è stata aperta su un display specifico e utilizza il contesto giusto, quando chiama per impostare uno sfondo, il sistema può identificare automaticamente il display.
Se è necessario impostare lo sfondo per un display diverso da quello attuale, crea un nuovo oggetto Context
per il display di destinazione (Context#createDisplayContext
) e ottieni l'istanza WallpaperManager
da quel display.
Limitazioni di sicurezza
Il sistema non mostrerà sfondi su display virtuali di cui non è proprietario. Ciò è dovuto a un problema di sicurezza: un'app dannosa potrebbe creare un display virtuale con il supporto delle decorazioni di sistema abilitato e leggere informazioni sensibili dell'utente dalla superficie (ad esempio una foto personale).
Implementazione
In Android 10, le interfacce IWallpaperConnection#attachEngine()
e IWallpaperService#attach()
accettano il
parametro displayId
per creare connessioni per display.
WallpaperManagerService.DisplayConnector
incapsula un motore e una connessione
per ogni display. In WindowManager, i controller dello sfondo vengono
creati per ogni oggetto DisplayContent
durante la costruzione anziché un
singolo WallpaperController
per tutti i display.
Alcune implementazioni del metodo WallpaperManager
pubblico (ad esempio
WallpaperManager#getDesiredMinimumWidth()
) sono state aggiornate per calcolare
e fornire informazioni per le visualizzazioni corrispondenti.
Sono stati aggiunti WallpaperInfo#supportsMultipleDisplays()
e un attributo risorsa corrispondente, in modo che gli sviluppatori di app possano segnalare quali sfondi sono pronti per più schermi.
Se il servizio di sfondi mostrato sul display predefinito non supporta più display, il sistema mostra lo sfondo predefinito sui display secondari:
Figura 3. Logica di fallback dello sfondo per i display secondari.