Creare un widget avanzato

Prova Compose
Jetpack Compose è il toolkit per la UI consigliato per Android. Scopri come creare widget utilizzando API in stile Compose.

Questa pagina illustra le pratiche consigliate per creare un widget più avanzato per un'esperienza utente migliore.

Ottimizzazioni per l'aggiornamento dei contenuti dei widget

L'aggiornamento dei contenuti dei widget può essere oneroso dal punto di vista computazionale. Per risparmiare il consumo della batteria, ottimizza il tipo, la frequenza e la tempistica degli aggiornamenti.

Tipi di aggiornamenti dei widget

Esistono tre modi per aggiornare un widget: un aggiornamento completo, un aggiornamento parziale e, nel caso di un widget di raccolta, un aggiornamento dei dati. Ognuno ha costi e ramificazioni computazionali diversi.

Di seguito vengono descritti i singoli tipi di aggiornamento e vengono forniti gli snippet di codice per ciascuno.

val appWidgetManager = AppWidgetManager.getInstance(context)
val remoteViews = RemoteViews(context.packageName, R.layout.widgetlayout).apply {
    setTextViewText(R.id.textview_widget_layout1, "Updated text1")
    setTextViewText(R.id.textview_widget_layout2, "Updated text2")
}
appWidgetManager.updateAppWidget(appWidgetId, remoteViews)

  • Aggiornamento parziale: chiama AppWidgetManager.partiallyUpdateAppWidget per aggiornare parti del widget. In questo modo, il nuovo RemoteViews viene unito al RemoteViews fornito in precedenza. Questo metodo viene ignorato se un widget non riceve almeno un aggiornamento completo tramite updateAppWidget(int[], RemoteViews).

val appWidgetManager = AppWidgetManager.getInstance(context)
val remoteViews = RemoteViews(context.packageName, R.layout.widgetlayout).apply {
    setTextViewText(R.id.textview_widget_layout, "Updated text")
}
appWidgetManager.partiallyUpdateAppWidget(appWidgetId, remoteViews)

val appWidgetManager = AppWidgetManager.getInstance(context)
appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetId, R.id.widget_listview)

Puoi chiamare questi metodi da qualsiasi punto della tua app, purché l'app abbia lo stesso UID della classe AppWidgetProvider corrispondente.

Determina la frequenza di aggiornamento di un widget

I widget vengono aggiornati periodicamente in base al valore fornito per l'attributo updatePeriodMillis. Il widget può aggiornarsi in risposta all'interazione dell'utente, agli aggiornamenti di trasmissione o a entrambi.

Aggiorna periodicamente

Puoi controllare la frequenza dell'aggiornamento periodico specificando un valore per AppWidgetProviderInfo.updatePeriodMillis nel file XML appwidget-provider. Ogni aggiornamento attiva il metodo AppWidgetProvider.onUpdate(), in cui puoi inserire il codice per aggiornare il widget. Tuttavia, se il widget deve caricare i dati in modo asincrono o richiede più di 10 secondi per l'aggiornamento, prendi in considerazione le alternative per gli aggiornamenti del broadcast receiver descritte in una sezione successiva, perché dopo 10 secondi il sistema considera un BroadcastReceiver non reattivo.

updatePeriodMillis non supporta valori inferiori a 30 minuti. Tuttavia, se vuoi disattivare gli aggiornamenti periodici, puoi specificare 0.

Puoi consentire agli utenti di regolare la frequenza degli aggiornamenti in una configurazione. Ad esempio, potrebbero voler aggiornare un ticker azionario ogni 15 minuti o solo quattro volte al giorno. In questo caso, imposta updatePeriodMillis su 0 e utilizza WorkManager.

Aggiornamento in risposta a un'interazione dell'utente

Ecco alcuni modi consigliati per aggiornare il widget in base all'interazione dell'utente:

  • Da un'attività dell'app:chiama direttamente AppWidgetManager.updateAppWidget in risposta a un'interazione utente, ad esempio un tocco dell'utente.

  • Da interazioni remote, come una notifica o un widget dell'app:crea un PendingIntent, quindi aggiorna il widget dal Activity, Broadcast o Service richiamato. Puoi scegliere la tua priorità. Ad esempio, se selezioni un Broadcast per PendingIntent, puoi scegliere una trasmissione in primo piano per dare la priorità a BroadcastReceiver.

Aggiornamento in risposta a un evento di trasmissione

Un esempio di evento di trasmissione che richiede l'aggiornamento di un widget è quando l'utente scatta una foto. In questo caso, vuoi aggiornare il widget quando viene rilevata una nuova foto.

Puoi pianificare il lavoro con WorkManager e specificare un trigger dell'URI contenuto utilizzando il metodo Constraints.Builder.addContentUriTrigger.

Puoi anche registrare un BroadcastReceiver per la trasmissione, ad esempio ascoltando ACTION_LOCALE_CHANGED. Tuttavia, poiché questa operazione consuma risorse del dispositivo, utilizzala con cautela e ascolta solo la trasmissione specifica. Con l'introduzione delle limitazioni delle trasmissioni in Android 7.0 (livello API 24) e Android 8.0 (livello API 26), le app non possono registrare trasmissioni implicite nei propri manifest, con alcune eccezioni.

Considerazioni sull'aggiornamento di un widget da un BroadcastReceiver

Se il widget viene aggiornato da un BroadcastReceiver, incluso AppWidgetProvider, tieni presente le seguenti considerazioni relative alla durata e alla priorità di un aggiornamento del widget.

Durata dell'aggiornamento

In genere, il sistema consente ai broadcast receiver, che di solito vengono eseguiti nel thread principale dell'app, di essere eseguiti per un massimo di 10 secondi prima di considerarli non reattivi e attivare un errore L'applicazione non risponde (ANR). Per evitare di bloccare il thread principale durante la gestione della trasmissione, utilizza il metodo goAsync. Se l'aggiornamento del widget richiede più tempo, valuta la possibilità di pianificare un'attività utilizzando WorkManager.

Caution: Any work you do here blocks further broadcasts until it completes,
so it can slow the receiving of later events.

Per saperne di più, consulta Considerazioni sulla sicurezza e best practice.

Priorità dell'aggiornamento

Per impostazione predefinita, le trasmissioni, incluse quelle effettuate utilizzando AppWidgetProvider.onUpdate, vengono eseguite come processi in background. Ciò significa che le risorse di sistema sovraccariche possono causare un ritardo nell'attivazione del broadcast receiver. Per dare priorità alla trasmissione, impostala come processo in primo piano.

Ad esempio, aggiungi il flag Intent.FLAG_RECEIVER_FOREGROUND all'Intent passato all'PendingIntent.getBroadcast quando l'utente tocca una determinata parte del widget.