Os widgets de apps são visualizações em miniatura que podem ser incorporadas em outros apps, como a tela inicial, e receber atualizações periódicas. Essas visualizações são chamadas de widgets na interface do usuário, e é possível publicar uma com um provedor de widgets de app (ou provedor de widgets). Um componente de app que contém outros widgets é chamado de host de widgets de app (ou host de widgets). A Figura 1 mostra um exemplo de widget de música:

Este documento descreve como publicar um widget usando um provedor de widget. Para
detalhes sobre como criar seu próprio AppWidgetHost
para
hospedar widgets de apps, consulte Criar um host de widgets.
Para saber como criar seu widget, consulte Visão geral dos widgets de apps.
Componentes de widget
Para criar um widget, você precisa dos seguintes componentes básicos:
- Objeto
AppWidgetProviderInfo
- Descreve os metadados de um widget, como o layout, a frequência de atualização e a classe
AppWidgetProvider
.AppWidgetProviderInfo
é definido em XML, conforme descrito neste documento. - Classe
AppWidgetProvider
- Define os métodos básicos que permitem interagir programaticamente com o
widget. Por meio dela, você recebe transmissões quando o widget é atualizado, ativado, desativado ou excluído. Você declara
AppWidgetProvider
no manifesto e depois implementa, conforme descrito neste documento. - Layout de visualização
- Define o layout inicial do widget. O layout é definido em XML, conforme descrito neste documento.
A Figura 2 mostra como esses componentes se encaixam no fluxo geral de processamento de widgets de app.

Se o widget precisar de configuração do usuário, implemente a atividade de configuração do widget de app. Com essa atividade, os usuários podem modificar as configurações do widget, por exemplo, o fuso horário de um widget de relógio.
- No Android 12 (nível 31 da API) e versões mais recentes, é possível fornecer uma configuração padrão e permitir que os usuários reconfigurem o widget depois. Consulte Usar a configuração padrão do widget e Permitir que os usuários reconfigurem widgets posicionados para mais detalhes.
- No Android 11 (nível da API 30) ou versões anteriores, essa atividade é iniciada sempre que o usuário adiciona o widget à tela inicial.
Também recomendamos as seguintes melhorias: layouts de widgets flexíveis, melhorias diversas, widgets avançados, widgets de coleção e criação de um host de widgets.
Declarar o XML AppWidgetProviderInfo
O objeto AppWidgetProviderInfo
define as qualidades essenciais de um widget.
Defina o objeto AppWidgetProviderInfo
em um arquivo de recurso XML usando um único elemento
<appwidget-provider>
e salve-o na pasta res/xml/
do projeto.
Isso é mostrado neste exemplo:
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:minWidth="40dp"
android:minHeight="40dp"
android:targetCellWidth="1"
android:targetCellHeight="1"
android:maxResizeWidth="250dp"
android:maxResizeHeight="120dp"
android:updatePeriodMillis="86400000"
android:description="@string/example_appwidget_description"
android:previewLayout="@layout/example_appwidget_preview"
android:initialLayout="@layout/example_loading_appwidget"
android:configure="com.example.android.ExampleAppWidgetConfigurationActivity"
android:resizeMode="horizontal|vertical"
android:widgetCategory="home_screen"
android:widgetFeatures="reconfigurable|configuration_optional">
</appwidget-provider>
Atributos de dimensionamento de widgets
A tela inicial padrão posiciona widgets na janela com base em uma grade de células com altura e largura definidas. A maioria das telas iniciais só permite que os widgets assumam tamanhos que são múltiplos inteiros das células da grade. Por exemplo, duas células horizontalmente por três células verticalmente.
Com os atributos de dimensionamento de widget, é possível especificar um tamanho padrão para o widget e fornecer limites inferiores e superiores para o tamanho dele. Nesse contexto, o tamanho padrão de um widget é o tamanho que ele assume quando é adicionado à tela inicial pela primeira vez.
A tabela a seguir descreve os atributos <appwidget-provider>
relacionados
ao dimensionamento de widgets:
Atributos e descrição | |
---|---|
targetCellWidth e
targetCellHeight (Android 12),
minWidth e minHeight |
targetCellWidth e
targetCellHeight , e minWidth e
minHeight . Assim, seu app pode usar
minWidth e minHeight se o dispositivo do usuário
não for compatível com targetCellWidth e
targetCellHeight . Se compatíveis, os atributos
targetCellWidth e targetCellHeight
terão precedência sobre os atributos minWidth e minHeight .
|
minResizeWidth e
minResizeHeight |
Especifique o tamanho mínimo absoluto do widget. Esses valores especificam o tamanho abaixo do qual o widget fica ilegível ou inutilizável. Usar esses atributos permite que o usuário redimensione o widget para um tamanho menor que o padrão. O atributo minResizeWidth é ignorado se for maior que minWidth ou se o redimensionamento horizontal não estiver ativado. Confira
resizeMode . Da mesma forma, o atributo
minResizeHeight é ignorado se for maior que
minHeight ou se o redimensionamento vertical não estiver ativado. |
maxResizeWidth e
maxResizeHeight |
Especifique o tamanho máximo recomendado do widget. Se os valores não forem múltiplos das dimensões da célula da grade, eles serão arredondados para cima até o tamanho de célula mais próximo. O atributo maxResizeWidth é ignorado se for menor que minWidth ou se o redimensionamento horizontal não estiver ativado. Consulte resizeMode . Da mesma forma, o atributo maxResizeHeight será ignorado se for maior que minHeight ou se o redimensionamento vertical não estiver ativado.
Introduzido no Android 12. |
resizeMode |
Especifica as regras pelas quais um widget pode ser redimensionado. É possível usar esse atributo para permitir o redimensionamento dos widgets da tela inicial: na horizontal, vertical ou nos dois eixos. Os usuários tocam e mantêm pressionado um widget para mostrar as alças de redimensionamento e arrastam as alças horizontais ou verticais para mudar o tamanho na grade de layout. Os valores para o atributo resizeMode incluem
horizontal , vertical e none . Para
declarar um widget como redimensionável na horizontal e na vertical, use
horizontal|vertical . |
Exemplo
Para ilustrar como os atributos na tabela anterior afetam o dimensionamento do widget, considere as seguintes especificações:
- Uma célula da grade tem 30 dp de largura e 50 dp de altura.
- A seguinte especificação de atributo é fornecida:
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:minWidth="80dp"
android:minHeight="80dp"
android:targetCellWidth="2"
android:targetCellHeight="2"
android:minResizeWidth="40dp"
android:minResizeHeight="40dp"
android:maxResizeWidth="120dp"
android:maxResizeHeight="120dp"
android:resizeMode="horizontal|vertical" />
A partir do Android 12:
Use os atributos targetCellWidth
e targetCellHeight
como o tamanho padrão do widget.
O tamanho padrão do widget é 2x2. O widget pode ser redimensionado para 2x1 ou até 4x3.
Android 11 e versões anteriores:
Use os atributos minWidth
e minHeight
para calcular o tamanho padrão do widget.
A largura padrão = Math.ceil(80 / 30)
= 3
A altura padrão = Math.ceil(80 / 50)
= 2
O tamanho padrão do widget é 3x2. O widget pode ser redimensionado para 2x1 ou para tela cheia.
Outros atributos do widget
A tabela a seguir descreve os atributos <appwidget-provider>
relacionados a qualidades que não sejam o dimensionamento de widgets.
Atributos e descrição | |
---|---|
updatePeriodMillis |
Define a frequência com que o framework de widget solicita uma atualização do
AppWidgetProvider chamando o método de callback onUpdate() . Não há garantias de que a atualização real ocorra no momento exato com esse valor. Recomendamos atualizar do modo mais infrequente possível, talvez não mais do que uma vez por hora, para conservar a bateria.
Para conferir a lista completa de considerações para escolher um período de atualização adequado, consulte Otimizações para atualizar o conteúdo do widget. |
initialLayout |
Aponta para o recurso de layout que define o layout do widget. |
configure |
Define a atividade que é iniciada quando o usuário adiciona o widget, permitindo que ele configure as propriedades do widget. Consulte Permitir que os usuários configurem widgets. A partir do Android 12, seu app pode pular a configuração inicial. Consulte Usar a configuração padrão do widget para mais detalhes. |
description |
Especifica a descrição que o seletor de widgets vai mostrar para seu widget. Introduzido no Android 12. |
previewLayout (Android 12)
e previewImage (Android 11 e versões anteriores) |
previewImage
e previewLayout para que o app possa usar
previewImage se o dispositivo do usuário não for compatível com
previewLayout . Para mais detalhes, consulte
Compatibilidade com versões anteriores usando visualizações de widgets escalonáveis.
|
autoAdvanceViewId |
Especifica o ID de visualização da subexibição do widget que é avançada automaticamente pelo host do widget. |
widgetCategory |
Declara se o widget pode ser exibido na tela inicial (home_screen ), na tela de bloqueio (keyguard ) ou nas duas. Para o Android 5.0 e versões posteriores, apenas home_screen é válido.
|
widgetFeatures |
Declara os recursos compatíveis com o widget. Por exemplo, se quiser que o widget use a configuração padrão quando um usuário o adicionar, especifique as flags
configuration_optional
e
reconfigurable . Isso evita a inicialização da atividade de configuração depois que um usuário
adiciona o widget. O usuário ainda poderá
reconfigurar o widget
depois. |
Usar a classe AppWidgetProvider para processar transmissões de widgets
A classe AppWidgetProvider
processa transmissões de widgets e atualiza o widget
em resposta a eventos do ciclo de vida do widget. As seções a seguir descrevem como
declarar AppWidgetProvider
no manifesto e implementá-lo.
Declarar um widget no manifesto
Primeiro, declare a classe AppWidgetProvider
no arquivo AndroidManifest.xml
do app, conforme mostrado no exemplo a seguir:
<receiver android:name="ExampleAppWidgetProvider"
android:exported="false">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data android:name="android.appwidget.provider"
android:resource="@xml/example_appwidget_info" />
</receiver>
O elemento <receiver>
requer o atributo android:name
, que especifica
o AppWidgetProvider
usado pelo widget. O componente não pode ser exportado, a menos que um processo separado precise transmitir para seu AppWidgetProvider
, o que geralmente não acontece.
O elemento <intent-filter>
precisa incluir um elemento <action>
com o atributo android:name
. Esse atributo especifica que o AppWidgetProvider
aceita a transmissão de ACTION_APPWIDGET_UPDATE
. Essa é a única transmissão que precisa ser declarada explicitamente. O
AppWidgetManager
envia automaticamente todas as outras transmissões de widget para o AppWidgetProvider
conforme
necessário.
O elemento <meta-data>
especifica o recurso AppWidgetProviderInfo
e requer os seguintes atributos:
android:name
: especifica o nome dos metadados. Useandroid.appwidget.provider
para identificar os dados como o descritorAppWidgetProviderInfo
.android:resource
: especifica o local do recursoAppWidgetProviderInfo
.
Implementar a classe AppWidgetProvider
A classe AppWidgetProvider
estende BroadcastReceiver
como uma classe de conveniência para lidar com transmissões de widgets. Ele recebe apenas as transmissões de eventos relevantes para o widget, como quando ele é atualizado, excluído, ativado e desativado. Quando esses eventos de transmissão ocorrem, os seguintes métodos
AppWidgetProvider
são chamados:
onUpdate()
- É chamado para atualizar o widget em intervalos definidos pelo atributo
updatePeriodMillis
noAppWidgetProviderInfo
. Consulte a tabela que descreve outros atributos de widget nesta página para mais informações. - Esse método também é chamado quando o usuário adiciona o widget. Por isso, ele realiza a
configuração essencial, como definir manipuladores de eventos para objetos
View
ou iniciar jobs para carregar dados a serem mostrados no widget. No entanto, se você declarar uma atividade de configuração sem a flagconfiguration_optional
, esse método não será chamado quando o usuário adicionar o widget, mas será chamado para as atualizações subsequentes. É responsabilidade da atividade de configuração realizar a primeira atualização quando a configuração for concluída. Consulte Permitir que os usuários configurem widgets de apps para mais informações. - O callback mais importante é
onUpdate()
. Consulte Processar eventos com a classeonUpdate()
nesta página para mais informações. onAppWidgetOptionsChanged()
Esse método é chamado quando o widget é posicionado pela primeira vez e sempre que ele é redimensionado. Use esse callback para mostrar ou ocultar conteúdo com base nas variações de tamanho do widget. Para receber as variações de tamanho e, a partir do Android 12, a lista de tamanhos possíveis que uma instância de widget pode ter, chame
getAppWidgetOptions()
, que retorna umBundle
que inclui o seguinte:OPTION_APPWIDGET_MIN_WIDTH
: contém o limite inferior da largura, em unidades dp, de uma instância de widget.OPTION_APPWIDGET_MIN_HEIGHT
: contém o limite inferior da altura, em unidades dp, de uma instância de widget.OPTION_APPWIDGET_MAX_WIDTH
: contém o limite superior da largura, em unidades dp, de uma instância de widget.OPTION_APPWIDGET_MAX_HEIGHT
: contém o limite superior da altura, em unidades dp, de uma instância de widget.OPTION_APPWIDGET_SIZES
: contém a lista de tamanhos possíveis (List<SizeF>
), em unidades dp, que uma instância de widget pode ocupar. Introduzido no Android 12.
onDeleted(Context, int[])
É chamado toda vez que um widget é excluído do host de widgets.
onEnabled(Context)
Isso é chamado quando uma instância do widget é criada pela primeira vez. Por exemplo, se o usuário adicionar duas instâncias do seu widget, ele só será chamado na primeira vez. Se você precisar abrir um novo banco de dados ou realizar outra configuração que só precise ocorrer uma vez para todas as instâncias de widget, esse é um bom lugar para fazer isso.
onDisabled(Context)
É chamado quando a última instância do widget é excluída do host de widgets. Aqui é onde você precisa limpar todo o trabalho feito em
onEnabled(Context)
, por exemplo, excluir um banco de dados temporário.onReceive(Context, Intent)
Isso é chamado para cada transmissão e antes de cada um dos métodos de callback anteriores. Normalmente, não é necessário implementar esse método, porque a implementação padrão do
AppWidgetProvider
filtra todas as transmissões de widget e chama os métodos anteriores conforme apropriado.
É necessário declarar sua implementação da classe AppWidgetProvider
como um broadcast
receiver usando o elemento <receiver>
no AndroidManifest
. Consulte Declarar um
widget no manifesto nesta página para mais informações.
Processar eventos com a classe onUpdate()
O callback AppWidgetProvider
mais importante é onUpdate()
, porque ele é
chamado quando cada widget é adicionado a um host, a menos que você use uma atividade de configuração
sem a flag configuration_optional
. Se o widget aceitar eventos de interação do usuário, registre os manipuladores de eventos nesse callback. Se o widget não criar arquivos ou bancos de dados temporários nem realizar outro trabalho que exija limpeza, onUpdate()
poderá ser o único método de callback que você precisa definir.
Por exemplo, se você quiser um widget com um botão que inicie uma atividade quando
tocado, use a seguinte implementação de AppWidgetProvider
:
Kotlin
class ExampleAppWidgetProvider : AppWidgetProvider() { override fun onUpdate( context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray ) { // Perform this loop procedure for each widget that belongs to this // provider. appWidgetIds.forEach { appWidgetId -> // Create an Intent to launch ExampleActivity. val pendingIntent: PendingIntent = PendingIntent.getActivity( /* context = */ context, /* requestCode = */ 0, /* intent = */ Intent(context, ExampleActivity::class.java), /* flags = */ PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE ) // Get the layout for the widget and attach an onClick listener to // the button. val views: RemoteViews = RemoteViews( context.packageName, R.layout.appwidget_provider_layout ).apply { setOnClickPendingIntent(R.id.button, pendingIntent) } // Tell the AppWidgetManager to perform an update on the current // widget. appWidgetManager.updateAppWidget(appWidgetId, views) } } }
Java
public class ExampleAppWidgetProvider extends AppWidgetProvider { public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { // Perform this loop procedure for each widget that belongs to this // provider. for (int i=0; i < appWidgetIds.length; i++) { int appWidgetId = appWidgetIds[i]; // Create an Intent to launch ExampleActivity Intent intent = new Intent(context, ExampleActivity.class); PendingIntent pendingIntent = PendingIntent.getActivity( /* context = */ context, /* requestCode = */ 0, /* intent = */ intent, /* flags = */ PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE ); // Get the layout for the widget and attach an onClick listener to // the button. RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.example_appwidget_layout); views.setOnClickPendingIntent(R.id.button, pendingIntent); // Tell the AppWidgetManager to perform an update on the current app // widget. appWidgetManager.updateAppWidget(appWidgetId, views); } } }
Esse AppWidgetProvider
define apenas o método onUpdate()
, usando-o para
criar um PendingIntent
que inicia
um Activity
e o anexa ao
botão do widget usando setOnClickPendingIntent(int,
PendingIntent)
. Ele inclui um loop que é iterado em cada entrada em appWidgetIds
, que é uma matriz de IDs que identificam cada widget criado por esse provedor. Se o usuário criar mais de uma instância do widget, todas elas serão atualizadas simultaneamente. No entanto, apenas uma programação de updatePeriodMillis
é gerenciada para todas as instâncias do widget. Por exemplo, se a programação de atualização
estiver definida para ser a cada duas horas, e uma segunda instância do widget for adicionada
uma hora depois da primeira, as duas serão atualizadas no período definido pela
primeira, e o segundo período de atualização será ignorado. Ambos são atualizados a cada duas horas, não a cada hora.
Consulte a
classe de exemplo ExampleAppWidgetProvider.java
para mais detalhes.
Receber intents de transmissão de widgets
AppWidgetProvider
é uma classe de conveniência. Se você quiser receber as transmissões de widgets diretamente, implemente seu próprio BroadcastReceiver
ou modifique o callback onReceive(Context,Intent)
. Os intents com os quais você precisa se preocupar são os seguintes:
ACTION_APPWIDGET_UPDATE
ACTION_APPWIDGET_DELETED
ACTION_APPWIDGET_ENABLED
ACTION_APPWIDGET_DISABLED
ACTION_APPWIDGET_OPTIONS_CHANGED
Criar o layout do widget
É necessário definir um layout inicial para seu widget em XML e salvá-lo no diretório res/layout/
do projeto. Consulte as diretrizes de design para mais detalhes.
Criar o layout do widget é simples se você conhecer os layouts. No entanto, os layouts de widgets são baseados em RemoteViews
, que não é compatível com todos os tipos de layout ou widget de visualização. Não é possível usar visualizações personalizadas ou subclasses das visualizações compatíveis com RemoteViews
.
O RemoteViews
também é compatível com ViewStub
,
que é um View
invisível e de tamanho zero que pode ser usado para inflar lentamente os recursos de layout
no momento da execução.
Suporte para comportamento com estado
O Android 12 adiciona suporte a comportamentos com estado usando os seguintes componentes atuais:
O widget ainda não tem estado. O app precisa armazenar o estado e se registrar para eventos de mudança de estado.

O exemplo de código a seguir mostra como implementar esses componentes.
Kotlin
// Check the view. remoteView.setCompoundButtonChecked(R.id.my_checkbox, true) // Check a radio group. remoteView.setRadioGroupChecked(R.id.my_radio_group, R.id.radio_button_2) // Listen for check changes. The intent has an extra with the key // EXTRA_CHECKED that specifies the current checked state of the view. remoteView.setOnCheckedChangeResponse( R.id.my_checkbox, RemoteViews.RemoteResponse.fromPendingIntent(onCheckedChangePendingIntent) )
Java
// Check the view. remoteView.setCompoundButtonChecked(R.id.my_checkbox, true); // Check a radio group. remoteView.setRadioGroupChecked(R.id.my_radio_group, R.id.radio_button_2); // Listen for check changes. The intent has an extra with the key // EXTRA_CHECKED that specifies the current checked state of the view. remoteView.setOnCheckedChangeResponse( R.id.my_checkbox, RemoteViews.RemoteResponse.fromPendingIntent(onCheckedChangePendingIntent));
Forneça dois layouts: um direcionado a dispositivos com Android 12 ou
versões mais recentes em res/layout-v31
e o outro direcionado a versões anteriores
do Android 11 ou versões anteriores na pasta res/layout
padrão.
Implementar cantos arredondados
O Android 12 introduz os seguintes parâmetros de sistema para definir o raio dos cantos arredondados do widget:
system_app_widget_background_radius
: o raio do canto do plano de fundo do widget, que nunca é maior que 28 dp.Raio interno, que pode ser calculado com base no raio externo e no padding. Confira o snippet a seguir:
/** * Applies corner radius for views that are visually positioned [widgetPadding]dp inside of the * widget background. */ @Composable fun GlanceModifier.appWidgetInnerCornerRadius(widgetPadding: Dp): GlanceModifier { if (Build.VERSION.SDK_INT < 31) { return this } val resources = LocalContext.current.resources // get dimension in float (without rounding). val px = resources.getDimension(android.R.dimen.system_app_widget_background_radius) val widgetBackgroundRadiusDpValue = px / resources.displayMetrics.density if (widgetBackgroundRadiusDpValue < widgetPadding.value) { return this } return this.cornerRadius(Dp(widgetBackgroundRadiusDpValue - widgetPadding.value)) }
Para calcular um raio adequado para o conteúdo interno do widget, use a seguinte fórmula: systemRadiusValue - widgetPadding
Os widgets que cortam o conteúdo em formas não retangulares devem usar o
@android:id/background
como o ID da visualização em segundo plano que tem
android:clipToOutline
definido como true
.
Considerações importantes sobre cantos arredondados
- Telas de início de terceiros e fabricantes de dispositivos podem substituir o
parâmetro
system_app_widget_background_radius
para ser menor que 28 dp. Se o widget não usar
@android:id/background
ou definir um plano de fundo que corte o conteúdo com base no contorno (comandroid:clipToOutline
definido comotrue
), a tela de início vai identificar automaticamente o plano de fundo e cortar o widget usando um retângulo com cantos arredondados definidos como o raio do sistema.As formas não retangulares precisam estar contidas no contêiner de redimensionamento retangular arredondado para não serem cortadas.
No Android 16 e versões mais recentes, o valor do sistema AOSP para
system_app_widget_background_radius
é24dp
. Os launchers e fabricantes de dispositivos podem cortar o widget nosystem_app_widget_background_radius
.O conteúdo interno de um widget precisa ter padding suficiente para oferecer suporte a valores de raio
system_app_widget_background_radius
de até28dp
e evitar o corte do conteúdo pelos cantos arredondados.
Para garantir a compatibilidade do widget com versões anteriores do Android, recomendamos definir atributos personalizados e usar um tema personalizado para substituí-los no Android 12, conforme mostrado nos exemplos de arquivos XML a seguir:
/values/attrs.xml
<resources>
<attr name="backgroundRadius" format="dimension" />
</resources>
/values/styles.xml
<resources>
<style name="MyWidgetTheme">
<item name="backgroundRadius">@dimen/my_background_radius_dimen</item>
</style>
</resources>
/values-31/styles.xml
<resources>
<style name="MyWidgetTheme" parent="@android:style/Theme.DeviceDefault.DayNight">
<item name="backgroundRadius">@android:dimen/system_app_widget_background_radius</item>
</style>
</resources>
/drawable/my_widget_background.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="?attr/backgroundRadius" />
...
</shape>
/layout/my_widget_layout.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
...
android:background="@drawable/my_widget_background" />