Tutorial Android #25 – Fazendo Ligações (Chamadas)

Olá pessoal! Tudo bem?

Sei que é triste a dor da partida, mas esse é o último tutorial dessa primeira série de tutoriais sobre Android. Mas como disse no último post, isso não significa que o tema não será mais abordado aqui no blog. Estou considerando seriamente a possibilidade de, em breve, voltar a falar de Android e as novidades que temos ao utilizar a versão 4.

Mas por enquanto, vamos fechar essa primeira série com chave de ouro. Como toda a série foi voltada para Android, um sistema utilizado massivamente em aparelhos celulares, vamos ver hoje como realizar chamadas.

Nesta última sessão de modificações em nosso aplicativo, vamos adicionar um campo chamado telefone aos nossos restaurantes e, a partir dele, vamos possibilitar que o usuário faça uma chamada diretamente do nosso aplicativo. Bacana, não?

Bom, começando, temos inicialmente que atualizar o nosso modelo de dados para que armazene o novo dado necessário (o número de telefone). Primeiramente, modifique o método onCreate() da classe GerenciadorRestaurantes para abrigar o novo campo:

Em seguida, altere o método onUpgrade() para atualizar o modelo de dados do banco, caso o usuário esteja vindo de uma versão anterior:

Pronto. Agora, vamos procurar pelos métodos inserir(), atualizar(), obterTodos() e obterPorId() para adicionar o campo telefone a eles também.

Para concluir as alterações nesta classe, crie o método obterTelefone():

Pronto. Com relação a persistência, já estamos aptos a prosseguir. Vamos agora adicionar o campo telefone aos nossos formulários. Como devem estar lembrados, temos 2 layouts, um para o modo retrato, outro para o modo paisagem. Primeiro no modo retrato, adicione o seguinte trecho logo após o campo de endereço, no arquivo res/layout/form_detalhes.xml.

Agora no res/layout-land/form_detalhes.xml. Também, logo depois do trecho do campo de endereço.

Pronto. Nossas modificações agora serão na classe FormularioDetalhes. Primeiramente adicione o atributo telefone à classe:

Agora, precisamos atualizar os métodos onCreate(), salvar(), carregar(), onSaveInstanceState() e onRestoreInstanceState(). Pode parecer bastante coisa, mas são apenas ajustes leves para adicionar o novo campo.

Ufa! Perceberam como as alterações foram mínimas? 😀

Prosseguindo, precisamos dizer ao Android que nossa aplicação deseja realizar chamadas. Para isso, adicione a seguinte linha às permissões no arquivo AndroidManifest.xml.

Agora, vamos criar a opção ao menu para realizar as chamadas. Edite o arquivo res/menu/opcao_detalhes.xml para acomodar a nova opção (é… vai ficar meio espremido em telas pequenas…).

O arquivo de ícone utilizado foi o ic_menu_call.png encontrado na pasta de instalação do Android e devidamente renomeado para chamada.png.

Agora precisamos definir as novas strings utilizadas no formulário e no menu. Adicione-as ao arquivo res/values/strings.xml

… e no res/values-es/strings.xml.

Por fim, vamos fazer com que a opção de menu realize a chamada. Adicione o seguinte trecho aos encadeamentos de ifs no método onOptionsItemSelected().

Execute a aplicação para conferir as modificações.

Caso queira que a ligação seja realizada diretamente, sem exibir o discador, modifique, na linha 158 do trecho ali em cima, ACTION_DIAL por ACTION_CALL.

Bom pessoal, é isso! Como não podia deixar de ser, para baixar o projeto, basta clicar aqui.

Agradeço a todos que vem acompanhando o blog. Continuem sempre por aqui, pois sempre tem coisa nova! Comentem, critiquem, cliquem nos banners e enviem sugestões!

Até logo!!!

Tutorial Android #24 – Widgets (II)

Olá pessoal! Como estão?

No último post, vimos como criar um widget simples com o nome do restaurante. Hoje, vamos incrementá-lo em dois pontos principais: (1) ele terá um botão que mudará o restaurante que é exibido, mostrando outro aleatoriamente e; (2) ao tocar sobre o nome do restaurante no widget, é aberto o formulário para que você possa ver as outras informações sobre aquele restaurante.

Então, mãos à massa!

O primeiro passo é adicionarmos o botão ao layout de nosso widget. Dessa forma, abra o arquivo widget.xml que está em res/layout e faça a adição da imagem do botão, do tipo ImageButton:

Os atributos, no ponto em que estamos, não devem ser nenhuma surpresa. Neste ponto, já deve ser possível vê-lo no layout ao recompilar a aplicação.

O arquivo de imagem do ícone pode ser baixado junto com o projeto no final deste post.

No post anterior, toda a nossa lógica de consulta ao banco estava dentro do método onUpdate() do nosso widget. Isso funciona bem, mas, caso a lógica se expanda muito, corremos o risco da atualização demorar mais que o esperado e comprometer o desempenho da aplicação, já que o método é chamado em nossa thread principal.

Para melhorar isso, vamos novamente fazer uso de um IntentService que nos possibilita a realizar a consulta de modo assíncrono, sem comprometer o sistema. Portanto, crie uma classe chamada WidgetService e coloque-a no pacote net.rafaeltoledo.restaurante. Esta classe, que estenderá IntentService abrigará a lógica que estávamos executando no widget.

Basicamente o que fizemos foi passar a lógica para o nosso WidgetService. O próximo passo é adicionar esse nosso serviço lá no arquivo AndroidManifest.xml para que ele possa funcionar. Assim, adicione ao fim do nó application a seguinte linha:

Agora, vamos atualizar a classe WidgetAplicativo para que faça uso do nosso serviço.

Pronto. A parte mais “complicada” está feita. Agora precisamos apenas gerenciar os toques no botão e no nome do restaurante. Primeiramente, vamos fazer com que um novo restaurante seja exibido caso seja acionado o botão. Para esse processo, utilizaremos um PendingIntent para acionar a nossa Intent quando o “clique” for realizado.

Para isso, adicione as seguintes linhas ao final do método onHandleEvent() da classe WidgetService:

Com isso, toda vez que o botão for acionado, o nosso serviço de carregamento será executado novamente.

Por fim, precisamos agora gerenciar para que, ao tocar sobre o nome do restaurante, seja aberta a tela com o formulário. Para isso, precisaremos de realizar algumas mudanças sutis no método onHandleIntent(). As principais são que, além do nome, precisaremos também do identificador, pois através dele iremos carregar os dados no formulário. Além disso, também utilizaremos um PendingIntent para acionar a exibição do formulário.

E… prontinho! É isso. Como sempre, para baixar o código do aplicativo, só clicar aqui.

O próximo tutorial de Android muito provavelmente será o último. Não porque eu ache que não há mais o que ser tratado, mas porque a ideia dos tutoriais era mostrar uma visão geral, com alguns conceitos básicos. 25 tutoriais é um bom número. E isso também me permitirá abordar outros assuntos. (estou com ideia de pelo menos mais 6 séries de tutoriais!)

Então… aguardem pelo gran finale Android! Até lá! 🙂

Tutorial Android #23 – Widgets (I)

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:

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.

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

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.

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.

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).

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á!

Tutorial Android #22 – Internacionalização (i18n)

Olá pessoal! No tutorial de hoje, vamos ver como traduzir nossa aplicação para que ela se torne multi-linguagem. Isso é bastante interessante caso você tenha a intenção de colocar sua aplicação lá no Google Play.

Bom, o grande “segredo” da internacionalização consiste na pasta values do projeto. Nessa pasta, no caso do nosso projeto, temos hoje o arquivo arrays.xml e strings.xml. Esses arquivos irão conter valores correspondentes a cada um dos idiomas que nossa aplicação suportará. Hoje, temos nossa aplicação com o idioma padrão Português. Como o emulador do Android 2.2 não tem o idioma português, vamos deixá-lo como padrão mesmo, e adicionar suporte ao idioma Espanhol. (nota: se você sabe espanhol, releve as sentenças que eu vou mostrar. Foram todas traduzidas com o auxílio do Google Translator. Eu não falo espanhol!)

Para início de conversa, vamos preparar nosso aplicativo para a internacionalização. Modifique o arquivo strings.xml para que contenha os seguintes valores:

Basicamente, definimos alguns alias para as strings do nosso aplicativo. Porém, em alguns trechos do código, ainda temos strings como constantes de texto. Para isso, vamos alterá-los para utilizar os resources deste arquivo. Primeiramente, nos formulários e menus em XML, vamos alterar os arquivos form_detalhes.xml, tanto na pasta layout

… quanto na pasta layout-land

… além dos arquivos opcao.xml

e opcao_detalhes.xml, da pasta menu

Nas nossas classes, também temos alguns trechos que precisam ser adaptados. Primeiramente na classe FormularioDetalhes

… na classe PreferenciaHorario

… na classe ReceptorAlarme

… e na classe TwitterService

Caso a aplicação seja executada agora, ela deve rodar normalmente como rodava antes. Agora, vamos criar os arquivos relativos ao novo idioma. Crie um novo diretório no projeto chamado values-es na pasta res. Dentro dele, teremos 2 arquivos XML, arrays.xml

e strings.xml

E pronto! Para ver seu aplicativo no idioma espanhol, siga até o menu principal, Settings -> Language & keyboard -> Select language e selecione Español.

Como de costume, pra baixar o aplicativo, basta clicar aqui.

Até a próxima!

Tutorial Android #21 – Notificações

Olá pessoal! No último post vimos como utilizar alarmes em nossos aplicativos utilizando o AlarmManager. Porém, o alarme que definimos era exibido em tela cheia e, talvez, isso nem sempre é interessante. No tutorial de hoje, vamos adicionar a opção para o caso do usuário preferir uma notificação simples em vez de exibir ela em tela cheia.

O primeiro passo é adicionarmos mais essa opção no menu de opções. Assim, edite o arquivo preferencias.xml para adicionar um novo CheckBoxPreference.

Por fim, vamos editar o método onReceive da classe ReceptorAlarme para realizar a exibição da notificação, caso esta opção esteja selecionada.

Para essa operação, será necessário adicionarmos um atributo na classe, que é basicamente um número único para diferenciar esta notificação de outras que, eventualmente, venhamos utilizar em nosso aplicativo.

O ícone referenciado no aplicativo é o ícone de notificação do GTalk, que pode ser obtido no diretório de instalação da SDK sob o nome de stat_notify_chat. Caso deseje utilizar outro, fique à vontade.

E pronto! Já temos nosso aplicativo funcionando. Configure o alarme e realize seus testes.

Como de costume, para baixar o projeto, basta clicar aqui. Até logo! 🙂

Tutorial Android #20 – Alarmes

Olá pessoal! Aqui estamos nós com mais um tutorial de Android para alegria geral da nação. No episódio tutorial de hoje, vamos ver como criar um alarme para nos avisar a hora do almoço (tudo a ver com o aplicativo de restaurante, não?).

O primeiro passo é criarmos uma forma para o usuário configurar o horário em que ele deseja ser avisado do almoço. Poderíamos definir isto em uma Activity, mas esta opção soa mais como uma configuração. Dessa forma, vamos criar a classe PreferenciaHorario no pacote net.rafaeltoledo.restaurante, estendendo a classe DialogPreference. Logo em seguida explicarei os conceitos principais dela.

Bastante coisa, não? Vamos por partes.

Os métodos obterHora() e obterMinuto() servem para extrair a parte inteira do horário que será armazenado como uma string “00:00“. Temos três versões do construtor da classe, que no final sempre referenciam o terceiro. Isso é devido à superclasse. Ainda no construtor, definimos os nomes dos botões na janela de configuração de horário. onCreateDialogView() devolve um objeto View com a tela criada. Poderíamos aqui definirmos um layout, mas simplesmente devolvemos um widget TimePicker. O método onBindDialogView() é chamado após o onCreateDialogView() é encarregado de preencher a caixa de diálogo. onDialogClose(), como o próprio nome diz, é chamado quando a janelinha é encerrada. Caso o usuário pressione o botão de confirmar (condição positiveResult), o valor é armazenado em SharedPreferences. O método onGetDefaultValue() é utilizado para a conversão interna do Android para o tipo do objeto. Por último, o método onSetInitialValue(), como o próprio nome diz, atribui um valor padrão. Ele verifica se há algum valor já salvo, ou padrão ou então atribui 00:00.

O próximo passo é adicionar a opção para a configuração do alarme pelo usuário. Dessa forma, edite o arquivo preferencias.xml da seguinte forma:

A primeira opção adicionada, do tipo CheckBoxPreference não tem muito segredo… a segunda, foi a que definimos na classe PreferenciaH0rario. Configuramos seu valor padrão para 12:00 e definimos que ela depende da opção alarme, ou seja, ela só estará habilitada caso alarme também esteja habilitada.

Neste projeto vamos utilizar o AlarmManager para gerenciar o nosso alarme. Porém, ele tem uma falha: toda vez que o celular é desligado, ao ligar novamente os alarmes não são configurados. Para resolver isso, vamos criar a classe ReceptorBoot para realizar essa configuração toda vez que o sistema for ligado. Crie-a no pacote net.rafaeltoledo.restaurante.

A tarefa do ReceptorBoot será realizado no método onReceive(). Por enquanto, coloque-o pra descansar. Já já voltamos nele.

Prosseguindo, precisamos adicionar o nó <receiver> no arquivo AndroidManifest.xml para que ele possa atuar no boot. Adicione-o ao final do nó application.

Além disso, adicione também a permissão para obter o sinal de boot completo do sistema.

Precisamos agora tratar as preferências do usuário para configurar o alarme. Quando o usuário ativar o checkbox do alarme, precisamos ativar o alarme no tempo selecionado. Quando o usuário modificar o alarme (por exemplo, para 11:00), devemos criar um novo alarme com o AlarmManager. Se ele desativar, precisamos cancelar o alarme existente. E, por fim, em um processo de boot, se o alarme estiver selecionado, precisamos criá-lo.

Para fazer todo esse trabalho, adicione os seguintes métodos na classe ReceptorBoot. Para corrigir os imports, só lembrar do Ctrl + Shift + O.

Também atualize o método onReceive():

Bem, no código listado acima, primeiramente, ao receber o sinal do boot (método onReceive()), configuramos o alarme, através do método configurarAlarme(). Neste método, obtemos o AlarmManager, e obtemos as preferências do usuário para o alarme (se existirem), e a montamos em um objeto do tipo Calendar. Caso alarme seja anterior ao horário atual, adicionamos um dia a ele e configuramos para repeti-lo diariamente. Já no método cancelarAlarme(), cancelamos o alarme vinculado ao contexto, obtendo o AlarmManager e obtendo um objeto PendingIntent (como se fosse uma tarefa pendente) com o método obterIntentPendente().

No código que temos até agora, o alarme só é armado na inicialização do sistema. Para que ele funcione da maneira como desejamos, precisamos adicionar alguns método a classe EdicaoPreferencias:

Lembre-se também de adicionar o membro privado da classe chamado preferencias:

O que nos falta fazer é criar um receptor que exiba o alarme na tela quando o alarme disparar. Para isso, primeiramente crie o arquivo alarme.xml na pasta res/layout:

Bastante simples, ele simplesmente exibirá bem grande na tela Hora do almoço!. Agora vamos criar a Activity que exibirá o aviso propriamente dito. Crie a classe AlarmeActivity no pacote net.rafaeltoledo.restaurante:

Crie também uma classe chamada ReceptorAlarme que será encarregada de iniciar a AlarmeActivity.

Encerrando (ufa!), falta somente adicionarmos esse último receptor no AndroidManifest.xml. Adicione-o no fim do nó application.

E é isso!

Como sempre, pra baixar o projeto, só clicar aqui.

Até logo!

Tutorial Android #19 – Integrando com o Google Maps

Olá pessoal! Como estão?

No tutorial de hoje, vamos aproveitar as coordenadas do GPS obtidas com o tutorial 17 e inseri-las em um mapa provido pelo Google Maps. Portanto, precisaremos que ele esteja instalado no emulador ou no seu celular para tal funcionalidade. Além disso, você também precisará de uma chave de desenvolvimento para que possa ocorrer a integração. Neste link, você obtém as informações necessárias sobre como conseguir esta chave.

Começando, vamos adicionar a opção para a visualização do mapa no FormularioDetalhes. Dessa forma, modifique o arquivo res/menu/opcao_detalhes.xml:

O ícone do menu (mapa.png) é o ícone ic_menu_mapmode.png, devidamente renomeado, que pode ser encontrado lá na pasta da sua instalação do Android SDK.

Em seguida, vamos modificar o método onPrepareOptionsMenu() no FormularioDetalhes para somente habilitar esta opção quando já houverem as informações básicas do restaurante (edição).

O próximo passo é criar uma Activity que será responsável por exibir o nosso mapa. Porém, antes disso, vamos informar ao arquivo AndroidManifest.xml que nossa aplicação fará uso da API do Google Maps. Dessa forma, dentro do nó application, adicione a seguinte linha:

Em seguida, vamos criar uma nova classe no pacote principal do projeto (net.rafaeltoledo.restaurante), com o nome de MapaRestaurante. Esta classe estenderá MapActivity. Inicialmente teremos o método onCreate(), onde simplesmente atribuiremos seu layout, e isRouteDisplayed(), método abstrato exigido. Neste segundo, por ora simplesmente retornaremos falso.

O próximo passo é modificar o método onOptionsItemSelected() para que  inicie a Activity MapaRestaurante.

O próximo passo é criarmos o XML que definirá o layout da Activity MapaRestaurante. Aqui vale a pena ressaltar dois pontos importantes:

  • Como o “layout” MapView não faz parte da biblioteca padrão de widgets do Android, é necessário especificar todo o seu caminho e;
  • Nesse ponto será necessária a chave para a API do Google Maps.

Prosseguindo, vamos criar um arquivo chamado mapa.xml que será salvo em res/layout:

Faça seu registro e substitua o valor pela sua própria chave (é gratuito!). Além disso, vale ressaltar que configuramos o atributo clickable como true para que o usuário possa movimentar o mapa, dar zoom, etc. Também devemos adicionar a nossa Activity no AndroidManifest.xml:

Para obter a latitude e longitude do FormularioDetalhes para o MapaRestaurantes, utilizaremos novamente os parâmetros extras possíveis de serem transferidos entre Acitivies através da classe Intent. Dessa forma, primeiramente vamos criar três atributos estáticos na classe MapaRestaurantes (nome do restaurante, latitude e longitude).

Porém, temos um pequeno problema. Atualmente em nossa aplicação, não estamos armazenando no formulário os valores de latitude e longitude do restaurante atual. Para resolver isso, vamos criar dois atributos do tipo double chamados latitude e longitude na classe FormularioDetalhes.

E então atribuir seus valores no método carregar().

Agora modificamos mais uma vez o método onOptionsItemSelected() para passar os valores para a Activity MapaRestaurantes, através dos atributos extras da classe Intent.

Na classe MapaRestaurantes, vamos obter os valores de latitude e longitude adicionando as duas linhas seguintes ao fim do método onCreate():

Precisamos agora de gerenciar a montagem do mapa, ajustando o zoom a um valor razoável, centralizando o marcador na tela e controlando o posicionamento das coordenadas, através de um GeoPoint. Para isso, vamos criar um membro na classe do tipo MapView chamado mapa.

E então, vamos adicionar mais algumas linhas ao fim do método onCreate() para criar o GeoPoint e adicionar as coordenadas a ele.

Vamos agora criar uma classe interna chamada SobreposicaoRestaurante que, como o próprio nome diz, será responsável por gerenciar a sobreposição do elemento no mapa.

Nela, gerenciamos para que aconteça a centralização do ponto, além de configurar o nosso ponto no mapa. Vamos agora adicionar mais algumas linhas ao final do método onCreate() para, aí sim, desenhar o ponto no mapa.

O arquivo do marcador (marcador.png) pode ser baixado juntamente com o projeto no fim do post.

Por fim, para finalizar, vamos gerenciar para que, quando o usuário toque na tela do mapa, ele exiba o nome do restaurante que foi marcado. Coisa simples, mas útil por questões de estética. Para fazer isso, implemente o método onTap() na classe interna SobreposicaoRestaurante.

Agora já podemos testar nossa aplicação.

Se o mapa não apareceu, provavelmente é porque você utilizou a minha chave de acesso ao Google Maps. 😛

A chave deve bater com a chave armazenada na sua máquina. Toda instalação da SDK do Android vem com uma chave que deve ser usada para gerar o MD5 requerido lá na página do Google Maps (link lá no começo do post, lembra?). Supondo que a pasta bin da sua JDK já esteja no Path do sistema, abra uma janela console a navegue até a pasta .android dentro da sua pasta pessoal (no meu caso, que estou usando o Ubuntu, /home/rafael/.android. No caso do Windows, seria C:UsersRafael.android). Dentro dessa pasta deve conter o arquivo debug.keystore. Digite então o seguinte comando no console:

Deve aparecer algo como androiddebugkey, Apr 3, 2012, PrivateKeyEntry,Certificate fingerprint (MD5): …, sendo que onde estão as reticências deve aparecer o que importa pra nós. Se caso estiver usando Java 7, adicione a opção -v ao comando. Ah, e eu vi bastante gente na Internet dizendo que não conseguiu executar o comando no Windows… talvez por algum bug?

Enfim, espero que tenham curtido mais esse tutorial. Como é de praxe, pra baixar o projeto, só clicar aqui.

Até logo!