Questa guida spiega come rendere la tua app sempre attiva, come reagire alle transizioni dello stato di alimentazione e come gestire il comportamento dell'applicazione per offrire una buona esperienza utente, risparmiando batteria.
Rendere un'app costantemente visibile ha un impatto significativo sulla durata della batteria, quindi valuta l'impatto sul consumo energetico quando aggiungi questa funzionalità.
Concetti principali
Quando un'app per Wear OS viene visualizzata a schermo intero, si trova in uno dei due stati di alimentazione:
- Interattivo: uno stato di elevato consumo energetico in cui lo schermo è alla massima luminosità, consentendo la piena interazione dell'utente.
- Ambient: uno stato di basso consumo energetico in cui il display si attenua per risparmiare energia. In questo stato, la UI della tua app occupa ancora l'intero schermo, ma il sistema potrebbe alterarne l'aspetto sfocandolo o mostrando contenuti di overlay come l'ora. Questa funzionalità è nota anche come modalità Ambient.
Il sistema operativo controlla la transizione tra questi stati.
Un'app sempre attiva è un'applicazione che mostra contenuti sia nello stato interattivo che in quello ambient.
Quando un'app sempre attiva continua a mostrare la propria UI mentre il dispositivo è in modalità Ambient a basso consumo energetico, viene descritta come in modalità ambiactive.
Transizioni di sistema e comportamento predefinito
Quando un'app è in primo piano, il sistema gestisce le transizioni dello stato di alimentazione in base a due timeout attivati dall'inattività dell'utente.
- Timeout 1: stato interattivo a stato Ambient:dopo un periodo di inattività dell'utente, il dispositivo entra nello stato Ambient.
- Timeout n. 2: ritorno al quadrante. Dopo un ulteriore periodo di inattività, il sistema potrebbe nascondere l'app corrente e mostrare il quadrante.
Subito dopo il primo passaggio del sistema allo stato Ambient, il comportamento predefinito dipende dalla versione di Wear OS e dalla configurazione dell'app:
- Su Wear OS 5 e versioni precedenti, il sistema mostra uno screenshot sfocato dell'applicazione in pausa, con l'ora sovrapposta. Questo stato è rappresentato dal nodo "AOD Lite" nel seguente diagramma di flusso.
- Su Wear OS 6 e versioni successive, se un'app ha come target SDK 36 o versioni successive, viene considerata sempre attiva. Il display è oscurato, ma l'applicazione continua a essere eseguita e rimane visibile. Gli aggiornamenti potrebbero essere eseguiti anche una volta al minuto. Questo stato è rappresentato dal nodo "AOD globale" nel seguente diagramma di flusso.
Personalizzare il comportamento per lo stato Ambient
Indipendentemente dal comportamento predefinito del sistema, in tutte le versioni di Wear OS puoi
personalizzare l'aspetto o il comportamento dell'app nello stato Ambient utilizzando
LocalAmbientModeManager per osservare le transizioni di stato in
Jetpack Compose su Wear OS. Questo stato è rappresentato dal nodo "Modalità Ambiactive"
nel seguente diagramma di flusso.
Osservare lo stato Ambient
Per reagire agli eventi della modalità Ambient in Jetpack Compose su Wear OS:
Utilizza
LocalAmbientModeManagerper osservare le modifiche allo stato della modalità Ambient del sistema e regolare di conseguenza i composable. Configura il componente in modo che si adatti a una modalità a basso consumo energetico nello statoAmbientMode.Ambiente ripristinalo in una visualizzazione interattiva completa nello statoAmbientMode.Interactive.// In a production application, the AmbientModeManager should be instantiated and provided at // the highest level of the Compose hierarchy (typically in the host Activity's setContent // block) using a CompositionLocalProvider. This ensures proper lifecycle management and // broad accessibility. // For this self-contained demo, AmbientModeManager is created and provided locally: val activityAmbientModeManager = rememberAmbientModeManager() CompositionLocalProvider(LocalAmbientModeManager provides activityAmbientModeManager) { val ambientModeManager = LocalAmbientModeManager.current val ambientMode = ambientModeManager?.currentAmbientMode if (ambientModeManager != null) { ambientModeManager.AmbientTickEffect { // While device is in ambient mode, update properties every minute or so // ... } } // ... val ambientModeName = when (ambientMode) { is AmbientMode.Interactive -> "Interactive" is AmbientMode.Ambient -> "Ambient" else -> "Unknown" } Text(text = "$ambientModeName Mode") // ... }
Diagramma di flusso del comportamento ambientale
Il seguente diagramma di flusso illustra come il sistema determina il comportamento
ambientale in base alla versione di Wear OS del dispositivo, al targetSdkVersion dell'app
e se osserva le transizioni di stato ambientale (utilizzando
LocalAmbientModeManager o AmbientLifecycleCallback).
Controllare la durata di accensione dello schermo
Le sezioni seguenti descrivono come gestire la durata di visualizzazione dell'app sullo schermo.
Impedire il ritorno al quadrante con un'attività in corso o un aggiornamento live
Dopo un periodo di tempo nello stato Ambientale (Timeout n. 2), il sistema tornerà in genere al quadrante orologio. L'utente può configurare la durata del timeout nelle impostazioni di sistema. Per alcuni casi d'uso, ad esempio quando un utente monitora un allenamento, un'app potrebbe dover rimanere visibile più a lungo.
Su Wear OS 5 e versioni successive, puoi impedirlo implementando un'attività in corso. Se la tua app mostra informazioni su un'attività utente in corso, come una sessione di allenamento, puoi utilizzare l'API Ongoing Activity per mantenere la tua app visibile fino al termine dell'attività. Se un utente torna manualmente al quadrante, l'indicatore dell'attività continua gli consente di tornare alla tua app con un solo tocco.
In alternativa, su Wear OS 7 e versioni successive, puoi utilizzare un aggiornamento live al posto di un'attività in corso. Per la compatibilità con le versioni precedenti, continua a supportare Attività in corso sui dispositivi con Wear OS 6 o versioni precedenti.
Per implementare questa funzionalità, l'intent tocco della notifica continua deve puntare all'attività sempre attiva, come mostrato nel seguente snippet di codice:
val activityIntent = Intent(this, AlwaysOnActivity::class.java).apply { flags = Intent.FLAG_ACTIVITY_SINGLE_TOP } val pendingIntent = PendingIntent.getActivity( this, 0, activityIntent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE, ) val notificationBuilder = NotificationCompat.Builder(this, CHANNEL_ID) // ... // ... .setOngoing(true) // ... val ongoingActivity = OngoingActivity.Builder(applicationContext, NOTIFICATION_ID, notificationBuilder) // ... // ... .setTouchIntent(pendingIntent) .build() ongoingActivity.apply(applicationContext) val notification = notificationBuilder.build()
Mantenere lo schermo attivo ed evitare lo stato Ambient
In rari casi, potrebbe essere necessario impedire completamente al dispositivo di entrare nello stato
Ambient. ovvero per evitare il timeout n. 1. Per farlo, puoi utilizzare il modificatore
keepScreenOn. Questa funzione funge da wakelock, mantenendo
il dispositivo nello stato Interattivo. Utilizza questa opzione con estrema cautela in quanto
influisce notevolmente sulla durata della batteria.
Suggerimenti per la modalità Ambient
Per offrire la migliore esperienza utente e risparmiare energia in modalità Ambient, segui queste linee guida di progettazione. Questi consigli danno la priorità a un'esperienza utente chiara, evitando informazioni fuorvianti e riducendo il disordine visivo, ottimizzando al contempo il consumo energetico del display.
- Ridurre il disordine visivo e la potenza del display. Un'interfaccia utente pulita e minimalista indica
all'utente che l'app è in stato di basso consumo energetico e consente di risparmiare
molta batteria limitando i pixel luminosi.
- Mantieni almeno l'85% dello schermo nero (un rapporto di pixel attivi del 15% o meno).
- Mostra solo le informazioni più importanti, spostando i dettagli secondari sul display interattivo.
- Utilizza contorni per icone o pulsanti di grandi dimensioni anziché riempimenti pieni, regolando il contrasto dei contorni in modo che gli elementi rimangano leggibili senza rischiare sfarfallio o burn-in dello schermo.
- Evita grandi blocchi di colore uniforme e immagini di branding o di sfondo non funzionali.
- Gestire dati dinamici e animazioni obsoleti
- Il callback
AmbientTickEffectviene richiamato solo periodicamente, in genere una volta al minuto, per risparmiare energia. A causa di questa limitazione, tutti i dati che cambiano di frequente, come un cronometro, il battito cardiaco o la distanza dell'allenamento, diventano obsoleti tra gli aggiornamenti. Per evitare di mostrare informazioni fuorvianti e errate, sostituisci questi valori live con contenuti segnaposto statici, ad esempio--. - Rimuovi gli indicatori di avanzamento che richiedono aggiornamenti frequenti per essere utili per il contesto o la situazione attuale dell'utente, ad esempio gli anelli di avanzamento per sessioni multimediali brevi. Puoi conservare gli indicatori di avanzamento nei casi in cui gli aggiornamenti una volta al minuto sono ancora utili, ad esempio per i timer lunghi.
- Metti in pausa o rimuovi tutte le animazioni in modalità Ambient, inclusi gli indicatori di avanzamento animati e il testo scorrevole.
- Il callback
- Mantenere un layout coerente
- Mantieni gli elementi nella stessa posizione nelle modalità Interattiva e Ambientale per creare una transizione fluida. Gli elementi interattivi dell'interfaccia utente, come i pulsanti, possono rimanere visibili perché i moderni dispositivi Wear OS supportano l'input tattile durante le sessioni ambientali.
- Mostra sempre l'ora corrente. In Jetpack Compose per Wear OS,
TimeText(incluso per impostazione predefinita inScreenScaffold) è compatibile con la modalità Ambient e si aggiorna automaticamente una volta al minuto in questa modalità.
- Essere consapevole del contesto
- Se l'utente si trovava in una schermata di impostazioni o configurazione quando il dispositivo entra in modalità Ambient, valuta la possibilità di mostrare una schermata più pertinente della tua app anziché la visualizzazione delle impostazioni.
- Gestire i requisiti specifici per i dispositivi
- Quando
currentAmbientModerestituisceAmbientMode.Ambient:- Se
isLowBitAmbientSupportedètrue, il display supporta meno bit per colore in modalità Ambient. Disattiva l'anti-aliasing (ad esempio, nelle operazioni di disegno personalizzateCanvasoPaint) ed evita i gradienti di colore ove possibile. - Se
isBurnInProtectionRequiredètrue, il sistema sposta periodicamente i contenuti visualizzati per evitare il burn-in dei pixel. Non spostare manualmente gli elementi della UI nella tua app. Evita invece le aree bianche piene e posiziona gli elementi della UI critici ad almeno 10 pixel dal bordo dello schermo in modo che non vengano tagliati quando il sistema sposta il display. (I layout di Wear Compose standard comeScreenScaffoldforniscono già un padding dei bordi sufficiente.)
- Se
- Quando
Debug e test
Questi comandi adb possono essere utili durante lo sviluppo o il test del comportamento dell'app
quando il dispositivo è in modalità Ambient:
# put device in ambient mode if the always on display is enabled in settings
# (and not disabled by other settings, such as theatre mode)
$ adb shell input keyevent KEYCODE_SLEEP
# put device in interactive mode
$ adb shell input keyevent KEYCODE_WAKEUP
Esempio: app per l'allenamento
Prendi in considerazione un'app di allenamento che deve mostrare le metriche all'utente per l'intera durata della sessione di allenamento. L'app deve rimanere visibile durante le transizioni di stato Ambient ed evitare di essere sostituita dal quadrante.
Per farlo, lo sviluppatore deve:
- Utilizza
LocalAmbientModeManagerper gestire le modifiche dell'interfaccia utente tra gli stati Interattivo e Ambientale, ad esempio oscurando lo schermo e rimuovendo i dati non essenziali. - Crea un nuovo layout a basso consumo energetico per lo stato Ambient che segue le best practice.
- Utilizza l'API per le attività continue (o gli Aggiornamenti live su Wear OS 7 e versioni successive) per tutta la durata dell'allenamento per impedire al sistema di tornare al quadrante.
Per un'implementazione completa, consulta l'esempio di esercizio basato su Compose su GitHub. Questo esempio mostra anche l'utilizzo del
LocalAmbientModeManager componibile per semplificare la gestione della modalità Ambient
in Compose.