Tutorial Android #23 – Widgets (I)

Padrão

Olá pessoal! No post de hoje vamos ver a primeira parte sobre como criarmos widgets no Android.

Pra quem não sabe, widgets é uma espécie de miniatura do aplicativo que você pode deixar em uma das áreas de trabalho do Android, colocando à disposição do usuário informações de maneira mais rápida e prática. O widget também pode redirecionar o usuário para o aplicativo principal, funcionando como uma espécie de “atalho”.

Bom, vamos então começar a colocar a mão na massa!

Primeiramente, precisamos definir o layout do nosso widget. Para isso, crie o arquivo widget.xml dentro da pasta res/layout. Ele será bastante simples, inicialmente apenas exibindo o nome de um restaurante cadastrado. Sendo assim, ele terá apenas um TextView em sua estrutura:

&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;<br />
&lt;RelativeLayout xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;<br />
    android:layout_width=&quot;fill_parent&quot;<br />
    android:layout_height=&quot;fill_parent&quot;<br />
    android:background=&quot;@drawable/frame&quot;&gt;<br />
    &lt;TextView android:id=&quot;@+id/nome&quot;<br />
        android:layout_width=&quot;wrap_content&quot;<br />
        android:layout_height=&quot;wrap_content&quot;<br />
        android:layout_centerVertical=&quot;true&quot;<br />
        android:layout_alignParentLeft=&quot;true&quot;<br />
        android:textSize=&quot;10pt&quot;<br />
        android:textColor=&quot;#FFFFFF&quot;/&gt;<br />
&lt;/RelativeLayout&gt;

De diferente do que já fizemos das outras vezes, somente as propriedades que modificam o tamanho e a cor do texto. No mais, tudo dentro dos conformes. O arquivo frame.9.png pode ser baixado junto com o projeto no fim do post. Por que este 9? Porque a imagem é uma NinePatch, ideal para compor fundos de frames. Entenda melhor como funciona aqui.

O próximo passo é criarmos uma classe para gerenciar o conteúdo do widget. Inicialmente, apenas crie uma classe chamada WidgetAplicativo dentro do pacote net.rafaeltoledo.restaurante, estendendo AppWidgetProvider.

package net.rafaeltoledo.restaurante;</p>
<p>import android.appwidget.AppWidgetProvider;</p>
<p>public class WidgetAplicativo extends AppWidgetProvider {<br />
}

Continuando, vamos agora definir algumas propriedades do widget em um arquivo XML. Crie dentro da pasta res/xml o arquivo provedor_widget.xml.

&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;<br />
&lt;appwidget-provider xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;<br />
	android:minWidth=&quot;300dip&quot;<br />
	android:minHeight=&quot;79dip&quot;<br />
	android:updatePeriodMillis=&quot;1800000&quot;<br />
	android:initialLayout=&quot;@layout/widget&quot;<br />
/&gt;

Basicamente definimos a largura e altura mínimas, o tempo de atualização das informações do widget (no caso, dos restaurantes – a cada 30 minutos) e qual o layout a ser utilizado por ele (no caso, o que definimos no XML anterior).

Em seguida, precisamos atualizar o AndroidManifest.xml para que o nosso aplicativo suporte o widget. Adicione o seguinte nó receiver ao final do nó application.

&lt;receiver android:name=&quot;.WidgetAplicativo&quot;<br />
	android:label=&quot;@string/app_name&quot;<br />
	android:icon=&quot;@drawable/ic_launcher&quot;&gt;<br />
	&lt;intent-filter&gt;<br />
		&lt;action android:name=&quot;android.appwidget.action.APPWIDGET_UPDATE&quot; /&gt;<br />
	&lt;/intent-filter&gt;<br />
	&lt;meta-data android:name=&quot;android.appwidget.provider&quot;<br />
		android:resource=&quot;@xml/provedor_widget&quot; /&gt;<br />
&lt;/receiver&gt;

Neste trecho, definimos que a classe que representa o widget é a WidgetApp, que o nome e o ícone a serem exibidos nas opções são os mesmos da aplicação no menu (app_name e ic_launcher). Além disso, definimos que o widget realizará operações de atualização e que suas propriedades estão definidas no arquivo provedor_widget dentro da pasta xml.

Por fim, vamos implementar o método onUpdate() para a classe WidgetApp. É este método que fará a busca em nosso banco de dados para exibir o nome de um restaurante.

@Override<br />
public void onUpdate(Context context, AppWidgetManager appWidgetManager,<br />
		int[] appWidgetIds) {<br />
	ComponentName cn = new ComponentName(context, WidgetApp.class);<br />
	RemoteViews atualizarFrame = new RemoteViews(&quot;net.rafaeltoledo.restaurante&quot;, R.layout.widget);<br />
	GerenciadorRestaurantes gerenciador = new GerenciadorRestaurantes(context);</p>
<p>	try {<br />
		Cursor c = gerenciador.getReadableDatabase().rawQuery(&quot;SELECT COUNT(*) FROM restaurantes&quot;, null);<br />
		c.moveToFirst();<br />
		int count = c.getInt(0);<br />
		c.close();</p>
<p>		if (count &gt; 0) {<br />
			int offset = (int) (count * Math.random());<br />
			String args[] = {String.valueOf(offset)};<br />
			c = gerenciador.getReadableDatabase().rawQuery(&quot;SELECT nome FROM restaurantes LIMIT 1 OFFSET ?&quot;, args);<br />
			c.moveToFirst();<br />
			atualizarFrame.setTextViewText(R.id.nome, c.getString(0));<br />
		} else {<br />
			atualizarFrame.setTextViewText(R.id.nome, context.getString(R.string.vazio));<br />
		}<br />
	} finally {<br />
		gerenciador.close();<br />
	}</p>
<p>	appWidgetManager.updateAppWidget(cn, atualizarFrame);<br />
}

Resumidamente, esse trecho de código:

  • Cria um objeto RemoteView, que nos permite modificar o widget;
  • Estabelece uma conexão com o banco de dados;
  • Verifica quantos restaurantes salvos existem;
  • Carrega um restaurante aleatório (por isso o uso de Math.random());
  • Exibe o nome do restaurante, ou uma mensagem dizendo que não existem restaurantes cadastrados;
  • Atualiza o widget propriamente dito.

A mensagem “vazio” (R.string.vazio) deve ser definida nos seus arquivos string.xml nas pastas values que você tem. No meu caso, vou defini-la em português e em espanhol (idiomas que minha aplicação suporta).

<string name="vazio">Nenhum registro.</string>

<string name="vazio">Ningún registro.</string>

E pronto! Para ativar o widget, clique e segure sobre a área de trabalho para aparecer o menu e a opção de inserir widget.

Pra baixar o projeto, só clicar aqui.

Bom, é isso pessoal! No próximo post vamos melhorar esse widget! Até lá!