Rendere un'app costantemente visibile influisce in modo significativo sulla durata della batteria, quindi tieni conto dell'impatto sull'alimentazione 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 alimentazione elevata in cui lo schermo è alla massima luminosità, consentendo la piena interazione dell'utente.
- Ambient: uno stato di alimentazione ridotta in cui il display si attenua per risparmiare energia. In questo stato, la UI dell'app occupa ancora l'intero schermo, ma il sistema potrebbe modificarne l'aspetto sfocandola o sovrapponendo contenuti come l'ora. Questo stato è detto anche 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 è nello stato Ambient a basso consumo energetico, si dice che è 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 n. 1: dallo stato Interattivo allo 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 che il sistema passa alla prima transizione 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 è attenuato, ma l'applicazione continua a essere eseguita e rimane visibile. (Gli aggiornamenti potrebbero essere poco frequenti, ad esempio una volta al minuto.) Questo stato è rappresentato dal nodo "Global AOD" 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 mentre è nello stato Ambient utilizzando
AmbientLifecycleObserver per ascoltare i callback sulle transizioni di stato. Questo stato è rappresentato dal nodo "Modalità ambiactive" in the
seguente diagramma di flusso.
Utilizzare AmbientLifecycleObserver
Per reagire agli eventi della modalità Ambient, utilizza la AmbientLifecycleObserver classe:
Implementa l'
AmbientLifecycleObserver.AmbientLifecycleCallbackinterfaccia. Utilizza il metodoonEnterAmbient()per regolare la UI per lo stato di alimentazione ridotta eonExitAmbient()per ripristinarla al display interattivo completo.val ambientCallback = object : AmbientLifecycleObserver.AmbientLifecycleCallback { override fun onEnterAmbient(ambientDetails: AmbientLifecycleObserver.AmbientDetails) { // ... Called when moving from interactive mode into ambient mode. // Adjust UI for low-power state: dim colors, hide non-essential elements. } override fun onExitAmbient() { // ... Called when leaving ambient mode, back into interactive mode. // Restore full UI. } override fun onUpdateAmbient() { // ... Called by the system periodically (typically once per minute) // to allow the app to update its display while in ambient mode. } }
Crea un
AmbientLifecycleObservere registralo con il ciclo di vita dell'attività o del composable.private val ambientObserver = AmbientLifecycleObserver(activity, ambientCallback) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) lifecycle.addObserver(ambientObserver) // ... }
Chiama
removeObserver()per rimuovere l'observer inonDestroy().override fun onDestroy() { super.onDestroy() lifecycle.removeObserver(ambientObserver) // ... }
Per gli sviluppatori che utilizzano Jetpack Compose, la libreria Horologist fornisce un'utilità utile, il AmbientAware composable, che semplifica l'implementazione
di questo pattern.
TimeText compatibile con la modalità Ambient
Come eccezione al requisito di un observer personalizzato, su Wear OS 6 il TimeText
widget è compatibile con la modalità Ambient. Si aggiorna automaticamente una volta al minuto quando il dispositivo è nello stato Ambient senza codice aggiuntivo.
Diagramma di flusso del comportamento in modalità Ambient
Il seguente diagramma di flusso illustra come il sistema determina il comportamento in modalità Ambient in base alla versione di Wear OS del dispositivo, a targetSdkVersion dell'app e al fatto che implementi o meno AmbientLifecycleCallback.
Controllare la durata di attivazione 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 Ambient (timeout n. 2), il sistema in genere torna al quadrante. 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, ad esempio una sessione di allenamento, puoi utilizzare l'API Attività in corso per mantenere l'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 l'attività in corso sui dispositivi che eseguono Wear OS 6 o versioni precedenti.
Per implementare questa funzionalità, l'intent di tocco della notifica in corso deve rimandare 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, potresti dover impedire completamente al dispositivo di entrare nello stato Ambient. Ovvero, evitare il timeout n. 1. Per farlo, puoi utilizzare il
FLAG_KEEP_SCREEN_ON flag della finestra. Questa funzionalità funge da wakelock, mantenendo il dispositivo nello stato Interattivo. Utilizza questa funzionalità con estrema cautela, in quanto influisce notevolmente sulla durata della batteria.
Consigli 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, impedendo informazioni fuorvianti e riducendo il disordine visivo, ottimizzando al contempo l'alimentazione del display.
- Riduci il disordine visivo e l'alimentazione del display. Una UI pulita e minimalista indica all'utente che l'app è in uno stato di alimentazione ridotta e consente di risparmiare una quantità significativa di batteria limitando i pixel luminosi.
- Mantieni almeno l'85% dello schermo nero.
- Mostra solo le informazioni più importanti, spostando i dettagli secondari sul display interattivo.
- Utilizza i contorni per le icone o i pulsanti di grandi dimensioni anziché i riempimenti pieni.
- Evita grandi blocchi di colore pieno e immagini di branding o di sfondo non funzionali.
- Gestisci i dati dinamici obsoleti
- Il callback
onUpdateAmbient()viene 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, la frequenza cardiaca o la distanza di allenamento, diventano obsoleti tra gli aggiornamenti. Per evitare di mostrare informazioni fuorvianti e errate, ascolta il callbackonEnterAmbiente sostituisci questi valori live con contenuti statici di segnaposto, ad esempio--.
- Il callback
- Mantieni un layout coerente
- Mantieni gli elementi nella stessa posizione nelle modalità Interattiva e Ambient per creare una transizione fluida.
- Mostra sempre l'ora.
- Tieni conto del contesto
- Se l'utente si trovava in una schermata di impostazioni o di 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.
- Gestisci i requisiti specifici del dispositivo
- Nell'oggetto
AmbientDetailspassato aonEnterAmbient():- Se
deviceHasLowBitAmbientètrue, disattiva l'anti-aliasing, se possibile. - Se
burnInProtectionRequiredètrue, sposta leggermente gli elementi della UI periodicamente ed evita le aree bianche piene per evitare il burn-in dello schermo.
- Se
- Nell'oggetto
Debug e test
Questi adb comandi 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 di allenamento
Considera 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 dello stato Ambient ed evitare di essere sostituita dal quadrante.
Per farlo, lo sviluppatore deve:
- Implementare un
AmbientLifecycleObserverper gestire le modifiche della UI tra gli stati Interattivo e Ambient, ad esempio attenuare lo schermo e rimuovere i dati non essenziali. - Creare un nuovo layout a basso consumo energetico per lo stato Ambient che segua le best practice.
- Utilizzare l'API Attività in corso (o gli aggiornamenti live su Wear OS 7 e versioni successive) per la durata dell'allenamento per impedire al sistema di tornare al quadrante.
Per un'implementazione completa, consulta l'esempio di allenamento basato su Compose su GitHub. Questo esempio mostra anche l'utilizzo del AmbientAware
composable della libreria Horologist per semplificare la gestione della modalità Ambient
in Compose.