Criar um widget avançado

Experimente trabalhar com o Compose
O Jetpack Compose é o kit de ferramentas de UI recomendado para Android. Aprenda a criar widgets usando APIs no estilo Compose.

Esta página explica as práticas recomendadas para criar um widget mais avançado e melhorar a experiência do usuário.

Otimizações para atualizar o conteúdo do widget

Atualizar o conteúdo do widget pode ser computacionalmente caro. Para economizar bateria, otimize o tipo, a frequência e o tempo de atualização.

Tipos de atualizações de widgets

Há três maneiras de atualizar um widget: uma atualização completa, uma atualização parcial e, no caso de um widget de coleção, uma atualização de dados. Cada um tem custos computacionais e ramificações diferentes.

A seguir, descrevemos cada tipo de atualização e fornecemos snippets de código para cada um deles.

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)

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)

É possível chamar esses métodos de qualquer lugar no app, desde que ele tenha o mesmo UID da classe AppWidgetProvider correspondente.

Determinar a frequência de atualização de um widget

Os widgets são atualizados periodicamente, dependendo do valor fornecido para o atributo updatePeriodMillis. O widget pode ser atualizado em resposta à interação do usuário, transmitir atualizações ou ambos.

Atualizar periodicamente

É possível controlar a frequência da atualização periódica especificando um valor para AppWidgetProviderInfo.updatePeriodMillis no XML appwidget-provider. Cada atualização aciona o método AppWidgetProvider.onUpdate(), que é onde você pode colocar o código para atualizar o widget. No entanto, considere as alternativas para atualizações de broadcast receiver descritas em uma seção a seguir se o widget precisar carregar dados de forma assíncrona ou levar mais de 10 segundos para atualizar. Isso porque, após 10 segundos, o sistema considera um BroadcastReceiver como não responsivo.

updatePeriodMillis não aceita valores menores que 30 minutos. No entanto, se você quiser desativar as atualizações periódicas, especifique 0.

Você pode permitir que os usuários ajustem a frequência das atualizações em uma configuração. Por exemplo, talvez queiram que um mostrador de ações seja atualizado a cada 15 minutos ou apenas quatro vezes por dia. Nesse caso, defina o updatePeriodMillis como 0 e use WorkManager.

Atualizar em resposta a uma interação do usuário

Confira algumas maneiras recomendadas de atualizar o widget com base na interação do usuário:

  • De uma atividade do app:chame diretamente AppWidgetManager.updateAppWidget em resposta a uma interação do usuário, como um toque.

  • Em interações remotas, como uma notificação ou um widget de app:construa um PendingIntent e atualize o widget usando o Activity, Broadcast ou Service invocado. Você pode escolher sua própria prioridade. Por exemplo, se você selecionar um Broadcast para o PendingIntent, poderá escolher uma transmissão em primeiro plano para dar ao BroadcastReceiver prioridade.

Atualização em resposta a um evento de transmissão

Um exemplo de evento de transmissão que exige a atualização de um widget é quando o usuário tira uma foto. Nesse caso, você quer atualizar o widget quando uma nova foto for detectada.

É possível programar o trabalho com WorkManager e especificar um gatilho de URI de conteúdo usando o método Constraints.Builder.addContentUriTrigger.

Você também pode registrar um BroadcastReceiver para a transmissão. Por exemplo, detectar ACTION_LOCALE_CHANGED. No entanto, como isso consome recursos do dispositivo, use com cuidado e ouça apenas a transmissão específica. Com a introdução das limitações de transmissão no Android 7.0 (nível da API 24) e no Android 8.0 (nível da API 26), os apps não podem registrar transmissões implícitas nos manifestos, com algumas exceções.

Considerações ao atualizar um widget de um BroadcastReceiver

Se o widget for atualizado de um BroadcastReceiver, incluindo AppWidgetProvider, fique atento às seguintes considerações sobre a duração e a prioridade de uma atualização de widget.

Duração da atualização

Como regra geral, o sistema permite que os broadcast receivers, que geralmente são executados na linha de execução principal do app, funcionem por até 10 segundos antes de serem considerados sem resposta e acionarem um erro de O app não está respondendo (ANR). Para evitar o bloqueio da thread principal ao processar a transmissão, use o método goAsync. Se a atualização do widget demorar mais, considere programar uma tarefa usando WorkManager.

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

Consulte Considerações de segurança e práticas recomendadas para mais informações.

Prioridade da atualização

Por padrão, as transmissões, incluindo as feitas usando AppWidgetProvider.onUpdate, são executadas como processos em segundo plano. Isso significa que recursos de sistema sobrecarregados podem causar um atraso na invocação do broadcast receiver. Para priorizar a transmissão, faça dela um processo em primeiro plano.

Por exemplo, adicione a flag Intent.FLAG_RECEIVER_FOREGROUND ao Intent transmitido ao PendingIntent.getBroadcast quando o usuário tocar em uma determinada parte do widget.