quinta-feira, 21 de novembro de 2013

Notificações

Olá à todos.

Uma notificação de sistema possibilita que seu aplicativo mantenha o usuário informado sobre eventos, como uma nova mensagem de um chat ou um evento de calendário. Pense em notificações como um novo canal que alerta o usuário para importantes eventos enquanto eles ocorrerem, ou um registro que narra eventos enquanto o usuário não está prestando atenção.

O layout de uma notificação é mostrado abaixo:


No mínimo, todas as notificações possuem um layout base, incluindo:

  • Ícone de notificação do pedido de envio, ou a foto do remetente.
  •  Título de notificação e mensagem.
  • Uma hora ou data.
  • Um ícone secundário para identificar a aplicação de envio quando a imagem do remetente for mostrada no ícone principal.


Notificações também são conhecidas como “Push Notifications”.

Abaixo podemos ver uma imagem que demonstra o que é uma notificação.





Criando notificações simples


A partir da API 17 (Android 4.2, Jelly Bean), as notificações mudaram. Até está versão, as notificações eram bem mais simples. A partir da API 17, as notificações passaram a ter mais de um ícone, e à mostrar mais informações.

Para mostrar tais mudanças, criaremos um exemplo de notificações em Android, que utiliza basicamente duas telas e uma classe utilitária de Notificações.

Na primeira tela, temos basicamente a chamada para a classe utilitária de notificações, que de fato cria a notificação. Quando a notificação for clicada pelo usuário, chamaremos a segunda tela. Logo, teremos a tela que chama a notificação, e a tela que é chamada pelo clique da notificação. E entre elas, uma classe que implementa a chamada da notificação.

Em nossa tela principal, temos:


No evento onCreate(), preparamos o título, mensagem e tickerText da notificação, e chamamos o método createNotification(). Nele, verificamos a versão da nossa API, e chamamos o utilitário NotificationHelper, e o método que implementa a notificação para a versão corrente.

O quarto argumento do método createsNotification() é uma Activity. Repare que no método createsNotification() esta Activity é inserida em uma Intent, que por sua vez, nos métodos da classe NotificationHelper, será utilizada para redirecionar o fluxo da nossa aplicação. Ou seja, quando clicarmos na notificação, será aberta esta Activity (que é o 4º argumento citado acima).

Isso será melhor explicado ao longo deste capítulo.

Parte da implementação da NotificationHelper é mostrada abaixo:


O método createSimpleNotification() cria notificações simples (mais comumente usado em API’s inferiores à 17). Notificações simples possuem apenas um ícone, um título, um texto de notificação, e o horário em que ela foi chamada.

Repare como este método é personalizado: dependendo da API do dispositivo Android, a criação da uma notificação é feita de forma específica. Porém, alguns método como setContentTitle(), setContentText(), setSmallIcon() e setContentIntent() são comuns à todas as API’s. E, é claro, a PendingIntent, que é o componente que nos redirecionará para outra tela quando clicarmos na notificação.

Podemos ver na nossa NotificationHelper uma constante chamada NOTIFICATION_ID (que é a constante que identificará o ID da nossa notificação), um atributo chamado mBigText (que será usado mais adiante), e o método já citado acima.

A chamada do método createSimpleNotification() gera o seguinte resultado:


Ao clicarmos na notificação, seremos redirecionado à tela ExecuteNotificationActivity. É neste tela que cancelaremos a notificação acima (senão ela será mostrada eternamente).

Eis a tela ExecuteNotificationActivity:


Ela apenas cancela a notificação, e seta um texto na tela.

O método de cancelamento de uma notificação (que é implementado na NotificationHelper) é mostrado abaixo:


Este método funciona para qualquer tipo de notificação (“simples” ou “sofisticada”), e para qualquer tipo de API.

Já o método createImprovedNotification(), que cria uma notificação “sofisticada”,  implementa as novas propriedades de notificações que foram introduzidas na versão 4.2. Dentre elas, podemos citar setLargeIcon(), setProgress() e o método Notification.InboxStyle, que é completado através do método setStyle().

Adicionando ícones às notificações



Para adicionar um ícone à uma notificação, precisamos declarar um NotificationBuilder, e setar as propriedades setSmallIcon() e setLargeIcon(). A primeira recebe como argumento um int, que representa um id de Drawable. A segunda recebe como argumento um Bitmap.

Notificações sofisticadas


Executando agora o método createImprovedNotification(), também constante na NotificationHelper, criamos uma notificação que só rodará em dispositivos Android com API igual ou superior à 4.2.


Podemos notar neste método que utilizamos a Notification.InboxStyle, e colocamos nela algumas linhas de texto. O resultado da execução deste método é mostrado abaixo, onde temos duas imagens: na primeira, temos a notificação com as linhas mostradas, e na segunda temos estas linhas minimizadas.

Para minimizar as linhas, basta utilizarmos um double touchscreen, onde um dos dedos ficaria acima das linhas, e o outro, como um compasso, empurrariam-nas para cima.

Esta minimização é mostrada logo abaixo.

Podemos ver abaixo, também, um ícone grande e um ícone pequeno, além do estilo e da barra de progresso, que é chamada pelo método: builder.setProgress(0, 0, true)

Com certeza, nossa notificação se tornou bem mais sofisticada!


Em nosso próximo exemplo, também usaremos uma notificação sofisticada. Porém, aprofundaremos mais um pouco o uso da propriedade builder.setProgress().

Simulando um download


Agora, será mostrado um outro exemplo de notificação. Neste exemplo, simularemos o download de uma imagem. Ao fim deste “download”, será mudado o título da notificação, e também a barra de progresso.


Podemos ver que a lógica toda fica na Thread parelela: ao fim do processamento simulado pelo comando For e pelocomando Thread.sleep(), atualizamos o conteúdo da notificação (setContextText()) e seu progresso (setProgress()).

Abaixo é mostrada a notificação em “processo de download”, e a notificação “ao fim do download”.



Notificações com botões


Por fim, será mostrado como incluir botões em uma notificação.

Para isto, basicamente precisamos utilizar a propriedade addAction() do Notification.Builder.


Acima vemos que a propriedade addAction() é utilizada duas vezes, para incluir os botões “View” e “Edit”. A primeira possui um ícone (R.drawable.ic_google), e a segunda, não possui (então setamos seu atributo com o valor “0”).

O último argumento desta propriedade é a Intent que abriremos caso os botões sejam clicados. Repare que podemos abrir três diferentes Intent’s com esta notificação: clicando nela, clicando no botão “View”, e clicando no botão “Edit”.

O que podemos notar acima, também, é a inclusão de um som quando a notificação tocar, através do propriedade setSound().

Abaixo do comentário “Calls the notification” temos três diferentes construtores de “notification”. Abaixo demonstramos três diferentes execuções, com cada um dos construtores:

  • Notification notification = builder.build();
  • Notification notification = builder.setStyle(new Notification.BigTextStyle().bigText(
    mBigText.
    toString())).build();
  • Notification notification = new Notification.BigPictureStyle(builder).bigPicture(
    BitmapFactory.
    decodeResource(context.getResources(), R.drawable.ic_google)).build();


Por fim, repare que em quase todos os exemplos deste capítulo utilizamos a tag notification.vibrate(). Com ela, podemos fazer o celular vibrar.

Para isto, precisamos declarar uma tag específica em nosso AndroidManifest.xml, como é mostrado abaixo.



E isto é tudo! Com este capítulo, conseguimos criar quase todos os tipos de notificações que uma aplicação em Android vá necessitar.

-----

Caso alguém tenha uma dúvida, crítica ou sugestão, sinta-se à vontade.

quarta-feira, 20 de novembro de 2013

Webservices

Olá à todos.

Em Android, não é complicado de obter dados da Internet. Neste tópico, mostraremos basicamente 2 exemplos de como conseguir isso: primeiramente, baixando um texto de uma URL da Internet; e por fim, obtendo dados de um webservice em formato JSON, de uma URL específica.

Obtendo uma informação simples da rede


Utilizaremos um exemplo bem simples para mostrar como baixar informações da rede. Em nosso exemplo, baixaremos o código-fonte de uma URL da Internet. Para isso, utilizaremos um layout com um botão, uma ProgressBar (uma View que sinaliza ao usuário que um processamento está sendo feito), e um TextView (onde colocaremos o código-fonte que acabamos de baixar).

Eis a representação deste layout:


Inicialmente, será mostrada apenas o botão “Load Webpage”. Ao clicarmos nele, será mudada a visibilidade da ProgressBar para Visible, e então começaremos a realizar o download do código-fonte da URL.

Uma vez realizado este download, a visibilidade da ProgressBar será mudada para Gone, e o conteúdo que baixamos da URL populará a TextView.

Basicamente é isto que nosso aplicativo de testes fará.

E eis o código-fonte da nossa tela principal:


Em nossa tela principal, temos nenhum método sendo chamando pelo evento onCreate().Porém, em nosso XML, temos a tag “onClick”, que  chama o método readWebpage(). Neste método, setamos a visibilidade da ProgressBar para Visible, e chamamos a DownloadWebPageTask, a AsyncTask que realiza o download da URL da Internet.

Nesta AsyncTask, no método doInBackground(), temos de fato o download do conteúdo da Internet. E no método onPostExecute() (que é chamado ao fim do download dos dados), a ProgressBar é ocultada, e o conteúdo da TextView é atualizado com o valor do código-fonte da URL baixada da Internet.

E é isso! Neste exemplo, conseguimos, de forma bem simplificada, obter dados da Internet.

Lendo dados de um webservice JSON 


O download de dados de um webservice JSON é um pouco mais complexo que o exemplo anterior. Utilizaremos como exemplo um aplicativo complementar ao aplicativo mostrado neste tópico do Blog. Porém, em nosso aplicativo, teremos também os pacotes api e utils.

No pacote api, temos 3 classes, que nos ajudarão na leitura do webservice JSON da Internet. Já no pacote utils, temos alguns métodos que auxiliam em tarefas básicas ao longo do nosso aplicativo. Por exemplo, o método StringUtils.isEmpty() verifica se uma String está vazia ou nula; já o método ActivityUtils.openActivity() chama uma Activity. E assim por diante.

O que importa estudarmos é o pacote api. Vamos à ele, então.

Neste pacote temos 3 classes:

  • ApiMapper Nesta classe convertemos o Object lido da Internet para uma List de nosso model. No caso do nosso aplicativo, nosso model é a classe Bean.java.
  • ApiRequest Nesta classe, obtemos o Object lido da Internet, e, chamando a classe ApiMapper, o convertemos para uma List de model.
  • OperationResult Nesta classe verificamos, detalhadamente, se o download dos dados da Internet foi realizado corretamente (verificando 14 status diferentes), e também montamos a estrutura de retorno destes dados, através de métodos como getEntityList() e setEntityList(), que obtém e inicializam listas do model que mapeamos o Object advindo da Internet.


A parte mais importante da classe ApiMapper é mostrada abaixo:


Nela, podemos ver claramente como um dado é mapeado para nosso model de Bean. Os métodos getInt() e getString() (que basicamente fazem cast de tipos) são mostrados abaixo:


E o método data.get() é um método básico do tipo Map. Um Map associa uma chave à um dado. Neste caso, a chave é Bean.KEY_ID e Bean.KEY_NAME, e o dado é o valor advindo do webservice. Para entender bem isso, basta darmos uma olhada em nosso webservice em JSON:


Repare que temos os campos “id” e “nome”. Repare agora, abaixo, o valor das constantes Bean.KEY_ID e Bean.KEY_NAME, advindos da classe Bean.java, do pacote model:


Logo, o método data.get() faz a comparação entre o nome dos campos do webservice em JSON, e o nome das constante do nosso model. Uma vez encontrando uma correspondência, joga os dados do webservice em nossa variável data.

Já a parte mais importante da classe ApiRequest é a mostrada abaixo:


Inicialmente, no método getBeanList(), vemos que é montada a String url que nada mais é do que a URL de origem dos dados do webservice.

Então, é feita uma tentativa de se obter os dados da Internet, através do método executeHttpGetWithRetry(). Como a obtenção destes dados está sujeita a erros, o executamos dentro da cláusula try.

Repare que este método é um método da classe HttpManager, constante no pacote manager. Caso alguém queira dar uma olhada nesta classe, sinta-se à vontade. Porém, sua implementação é tão complexa que julgo ser desnecessário explicá-la em detalhes. Tudo que precisamos saber dela é que ela recebe como parâmetro uma URL, e, em caso de sucesso, retorna o conteúdo desta URL (em String), ou, caso contrário, retorna um dos tipos de retorno de status de uma requisição HTTP, conforme explicado no link http://en.wikipedia.org/wiki/List_of_HTTP_status_codes

Há de se salientar também que a classe HttpManager implementa o padrão Singleton, analogamente à nossa já conhecida classe ContentManager.

Continuando à explicação sobre o método getBeanList() da classe ApiRequest, logo após a execução do método executeHttpGetWithRetry(), temos a verificação do retorno do webservice, checando se ocorreram erros no retorno dos dados da Internet:


Caso tenham ocorrido erros, o método é finalizado. Caso não, seguimos no fluxo da nossa aplicação.

Em sequência (caso não tenham ocorrido erros que fecharam nosso método), temos a obtenção dos dados do webservice, através do método getResponseString(). Caso ele não seja vazio, seguimos o fluxo do nosso método:


Então, finalmente, realizamos a conversão dos dados do webservice para nosso model:


Tal conversão é realizada, basicamente, através de checagens de tipo Map (como explicado anteriormente, neste tópico).

Repare também que são verificadas várias exceções. Logo, com tantas verificações acerca dos dados do webservice, o método proposto neste tópico se caracteriza como um método bastante confiável.

Por fim, temos a classe OperationResult. Nela temos o mapeamento dos tipos de retorno de código de webservice (como o código 200, “Ok”; e o código 404, ”Not Found”), e também o retorno do OperationResult caso os dados tenham sido baixados sem problemas.

Dentre estes retornos, temos setEntity() e setEntityList(), e seus respectivos getters. O método setEntity() atribui à um OperationResult um dado, e apenas um dado, de um tipo específico. Já o método setEntityList() atribui uma lista à um OperationResult.

Todos estes métodos são utilizados principalmente pela classe BeanAsyncTask, que é a classe responsável pela obtenção dos dados, seja do banco de dados, seja do webservice. Ela já foi explicada anteriormente neste tópico do blog.

Sobre essa classe, mostraremos abaixo os métodos update() e getBeanFromServer(), que foram atualizados, e agora fazem uso de webservices:


Podemos notar acima que o método getBeanFromServer() é chamado. O que ele faz? Veremos abaixo:


Este é o método que, de fato, interage com o webservice, chamando o método ApiRequest.getBeanList(). Caso haja sucesso na obtenção do webservice, além se setarmos o seu resultado no OperationResult através do método setEntityList(), salvamos os dados no banco de dados, através do método persistBean() (que está dentro de uma thread, uma vez que salvar dados em um banco podem demorar além do previsto).

-----

E é isto. Agora já estamos aptos a criar aplicações que obtenham dados de um webservice.

Caso alguém tenha uma dúvida, crítica ou sugestão, sinta-se à vontade.

Mapas, V2

Olá à todos.

Até dezembro de 2012, Mapas em Android eram mostrados de maneira bem básica, inflados em 2 dimensões e visualizados apenas de um ângulo. E tudo que precisávamos fazer para acessá-lo era declarar um projeto na SDK de Google Maps (Google API’s):


E declarar permissões no arquivo AndroidManifest.xml, como a permissão de Internet: <uses-permission android:name="android.permission.INTERNET"/>; e também a tag <uses-library android:name="com.google.android.maps"/>, também no AndroidManifest.xml.

E por fim, criar uma classe que extendesse da classe MapView.

Porém, em dezembro de 2012, a Google descontinuou esta versão, tornando-a deprecated (obsoleta), e criando uma nova, que é conhecida como Google Maps V2, tornando a versão anterior obsoleta. Por este motivo, neste tópico da apostila, sempre que falarmos de Mapas, estaremos falando dos mapas do Google Maps V2.

Logo, este post do Blog NÃO É MAIS FUNCIONAL, uma vez que a versão anterior de mapas em Android foi descontinuada.


Mapas V2


Com a nova versão de mapas, muitas melhorias foram realizadas. Ela possui mais funcionalidades, como: utilizar vetores para suportar visualizações 2D e 3D, o que torna a transição de renderização de mapas menos custosa; possibilitar a visualização de mapas por diversos ângulos; dentre outras, que veremos neste tópico.

E agora, ao invés de utilizarmos uma View (a MapView),  utilizaremos Fragments, que nada mais é do que uma View reutilizável que funciona em qualquer lugar de um layout.

Antes de criarmos um projeto que utilize Mapas em Android, precisamos: baixar o projeto Google Play Services; configurar nosso AndroidManifest.xml para as novas permissões advindas da V2; criar um projeto no Google API’s Console; obter uma chave de acesso ao Google Maps.

Na V2, o projeto Google Play Services é a classe que contém a API de mapas. Essa biblioteca é instalado pelo SDK Manager, na pasta Extras, no item Google Play Services:


Após o download deste projeto, é necessário importa-lo para o Eclipse. Para isto, basta clicarmos com o botão direito do mouse no Package Explorer, e depois em Import Android Existing Android Code Into Workspace, e então achar o projeto Google Play Services, que se localiza em /android-sdk/extras/google/google_play_services.


Então, precisamos criar um projeto para testar nossos mapas, e referenciar a biblioteca google-play-services_lib neste projeto:


O próximo passo é configurar as permissões do AndroidManifest.xml:



Repare os trechos de código circulados em vermelho. Para que nossos mapas funcionem, tudo que precisamos são esses trechos em nosso arquivo AndroidManifest.xml.

O primeiro trecho é a permissão para utilizarmos os mapas em Android. Repare que o prefixo do atributo android:name é o caminho do pacote da nossa aplicação. Esta permissão é bem específica.

O segundo trecho compreende mais permissões, sendo que apenas a primeira delas é análoga a permissão do primeiro trecho, uma vez que utiliza como prefixo o caminho do pacote da nossa aplicação.

O terceiro trecho compreende uma definição realizada para utilizarmos uma renderização melhorada para mapas em 3D.


O quarto trecho sinaliza uma mudança realizada pela Google em novembro de 2013. A partir deste mês, mapas em Android sem esta tag pararam de funcionar. Junto com esta mudança, veio a necessidade de se atualizar a biblioteca google-play-services_lib, e também mudou o layout do cadastro do nosso projeto do Google Maps, no site do Google Cloud Console.

O trecho final é a chave do Google Maps que precisamos ter para executar qualquer mapa. A obtenção deste chave será apresentada mais adiante, neste mesmo tópico.

Após a configuração do AndroidManifest.xml, o próximo passo é criar um projeto no Google Cloud Console.

Conforme mencionado no início desta página, em novembro de 2013 a Google mudou o layout do Google Cloud Console. Agora, para criar um projeto no Google Cloud Console, precisamos fazer login com uma conta de e-mail em https://cloud.google.com/console/

Então, será mostrada uma tela com o botão Create Project. Nesta página, criamos o projeto no servidor da Google (por exemplo, um projeto chamado “GoogleMapsProject”). Depois da criação do projeto, a página será redirecionada para um novo endereço, onde o nome do projeto faz parte da URL: https://cloud.google.com/console#/project/apps~steam-aria-415


Depois da criação do projeto, será mostrada uma tela parecida com a tela abaixo:



Agora, precisamos dar ao nosso aplicativo permissão para o Google Maps Android API v2. Para ativá-la, precisaríamos entrar no menu APIs & auth, e rolar a barra de rolagem até encontrar a opção Google Maps Android API v2. Então, mudar o checkbox do status para ON.

Após isto, o próximo passo seria clicar na aba Registered apps e então clicar no botão vermelho Register App. Então, será mostrada uma tela pedindo o nome do aplicativo de Android que queremos criar, e um rabio button pedindo a plataforma, ao qual marcaremos a opção “Android”.


Ao clicarmos no radio button “Android”, será pedido o “Package name” do nosso projeto, e o “SHA1 fingerprint”. No campo “Package name”, digitamos o caminho completo do nosso projeto (por exemplo, br.example.mapasv2). E no campo “SHA1 fingerprint” digitamos um valor que pode ser obtido tal qual é descrito abaixo.

Chaves Google Maps


Para gerar esta chave, primeiramente, precisamos o SHA-1 fingerprint de certificado para compilar o projeto. Para obtermos isso, precisamos primeiramente localizar o arquivo debug.keystore do nosso SDK do Android. Seu caminho pode ser encontrado através dos menus Window Preferences Android Build, do Eclipse.

Após obter o caminho deste arquivo, precisamos baixar um plugin do Eclipse para gerar o SHA-1. Para baixarmos este plugin, precisamos acessar o menu Help Install New Software, e então em “Work with:”, clicar em “Add...” e em “Location:” digitar http://keytool.sourceforge.net/update

E então realizar o download do plugin. Após isso, o Eclipse será reiniciado, e após isto, será mostrado um novo menu, chamando Keytool. Agora, precisamos abrir este menu, e clicar em “Open keystore”. Então, será mostrada a seguinte tela:


Em “Filename:”, precisamos passar o caminho do arquivo debug.keystore. Já em “Password:”, precisamos digitar android.

Após isto, será aberta uma nova aba no Eclipse, conforme mostrado abaixo.


Então, precisamos clicar em androiddebugkey, e será mostrada a seguinte tela:


E pronto! Conseguimos nosso SHA-1.

O próximo passo para obter a chave do Google Maps é copiar o valor do SHA-1, voltar para o Google Cloud Console, e colar o valor do SHA-1, e então no botão Register.


Então, será aberta uma nova janela (mostrada abaixo), e abrir a opção “Android Key”.


Após isto, será aberta uma nova tela, com o valor da nossa chave do Google Maps.



Agora, basta colarmos o valor desta chave em nosso AndroidManifest.xml, e executar nossa aplicação de mapas.

Exibindo um mapa


Então vamos lá, criar nossa primeira aplicação de mapas.

Um mapa da API V2 não utiliza mais uma MapView, mas sim um Fragment. Fragments foram introduzidos no Android a partir da API 11 (Android 3.0, Honeycomb). Por isso, a fim de que API’s tanto inferiores como superiores ao Honeycomb utilizem estes mapas, utilizaremos a classe SupportMapFragment, que possibilita que versões inferiores à Honeycomb consigam rodar os mapas da V2.

Nosso exemplo simplesmente mostrará um mapa, e para isso tudo que precisamos (além do nosso já configurado AndroidManifest.xml) é definir nosso mapa em um layout de XML, e que a tela principal da nossa aplicação extenda de FragmentActivity.

Eis o layout que inflará nosso mapa:


O mapa será inflado no fragment, que referencia a tela principal através do atributo class.

Eis a tela principal ao qual este fragment referencia:


Antes desse projeto ser executado, algo precisa ser esclarecido. A API V2 de mapas não suporta o emulador de Android. Logo, precisamos executar este projeto (e qualquer projeto que utilize mapas) em um dispositivo Android com depuração USB.

O resultado gerado pela execução do nosso projeto é mostrado na figura abaixo.

Repare que, automaticamente, nos é dado um controle de zoom. Em Android, o zoom varia de 2 até 21. A partir do zoom 17, começamos a obter renderizações de mapas em 3D.



Modos de visualização


Podemos visualizar um mapa em Android através do método setMapType da classe GoogleMap, onde podemos informar as seguintes constantes:

  • GoogleMap.MAP_TYPE_NONE → Modo de visualização mais simples do mapa, de forma que nenhuma informação extra será exibida.
  • GoogleMap.MAP_TYPE_NORMAL → Modo de visualização padrão nos mapas, onde podemos visualizar as ruas, estradas e rios.
  • GoogleMap.MAP_TYPE_SATELLITE → Modo de visualização com os dados de satélite.
  • GoogleMap.MAP_TYPE_HYBRID → Modo de visualização com os dados fotográficos do satélite, com os mapas das ruas. Este é o modo de satélite mais detalhado.
  • GoogleMap.MAP_TYPE_TERRAIN → Modo de visualização que exibe os dados topográficos do mapa.

Trabalhando com coordenadas


Para trabalharmos com coordenadas de um mapa, precisamos obter a instância do nosso mapa, e então utilizar esta instância na classe CameraUpdate.

Para obter a instância, utilizamos as linhas de código abaixo:


Através do método getSupportFragmentManager(), e seu sub-método findFragmentById(), conseguimos obter o fragmento que infla o nosso map. E através do método getMap(), conseguimos obter o mapa que é inflado no fragmento.

Com esta instância, conseguimos, por exemplo, setar o modo de visualização do nosso mapa, através do método setMapType().

Uma vez que temos a instância do mapa, já podemos utilizar a classe CameraUpdate. Com ela, podemos setar o mapa em uma coordenada específica, tal qual mostrado abaixo:


Utilizando o método CameraUpdateFactory.newLatLngZoom(), ao mesmo tempo setamos a coordenada que desejamos centrar no mapa, e setamos o zoom em 15. O método que, de fato, centra o mapa na coordenada que especificamos, é o método moveCamera().

Outra maneira de trabalhar com coordenadas é da maneira mostrada abaixo:


Qual é a diferença entre estas 2 metodologias de centrar o mapa em uma coordenada específica? Pelo segundo método, conseguimos obter mais informações. Isto será melhor explicado ainda neste tópico.

Controle de zoom


Conseguimos controlar o zoom de nosso mapa através dos métodos:

  • CameraUpdateFactory().zoomIn() → Aumenta o zoom do mapa em 1.
  • CameraUpdateFactory().zoomOut() → Diminui o zoom do mapa em 1.
  • CameraUpdateFactory().zoomTo(zoom) → Configura o valor do zoom utilizado pelo mapa.
  • CameraUpdateFactory().zoomBy(zoom) → Aumenta ou diminui o zoom do mapa, conforme o valor informado.

Tilt e Bearing


Conforme explicado anteriormente, pelo segundo método conseguimos obter mais informações. Mas que informações seriam essas? Seriam o Tilt e o Bearing. Bearing é o deslocamento que o mapa pode ter, no plano horizontal. E Tilt é o deslocamento que o mapa pode ter, no sentido vertical. Ambos podem ser chamados da seguinte maneira:


Ou seja, através do construtor CameraPosition.Builder(). A melhor maneira de entender como as propriedades Bearing e Tilt funcionam é modificando os parâmetros deste construtor, e verificando como o mapa se comporta com a calibragem destes parâmetros.

GPS


Por fim, aprenderemos a utilizar um GPS.

Para obtermos informações sobre o GPS, precisamos definir uma classe que implementa um LocationSource. Esta classe será utilizada como atributo de classe da nossa classe MainActivity.java. Eis a implementação desta classe:


Esta é a classe que, de fato, utilizará o GPS em nossa aplicação.

Eis como ela é chamada na nossa tela principal, que agora passou a ser chamada MapaV2.java:


O que temos de novo em nossa tela principal é:


Porém, apenas definimos o LocationSource. De fato, a verificação do status do GPS (se está ligado ou não), e a atualização da posição em que o usuário se encontra, são feitos na classe abaixo, que extende de MapaV2.java:


O que podemos notar nesta classe é:
  • Primeiramente, verificamos se o GPS está ligado. Se estiver, chamamos o método requestLocationUpdates(), para obtermos as atualizações de posição do usuário, através do GPS.
  • Caso o GPS não esteja ligado, mostramos na tela um Dialog, e caso o usuário aceite ligar o GPS, o redirecionamos para a tela de configurações, onde ele poderá ativar o GPS.
  • Após estas verificações:
    • No evento onPause() (ou seja, se pausarmos ou sairmos do nosso aplicativo), removemos as requisições de atualização de posição do usuário.
    • No evento onLocationChanged() (ou seja, quando a localização do usuário mudar), atualizamos a posição central da tela, uma vez que o usuário se deslocou pelo mapa.
    • Implementamos nada nos eventos seguintes (onProviderDisabled(), onProviderEnabled() e onStatusChanged()), pois, por hora, suas funções não nos interessam.

Desta forma, conseguimos obter com bastante precisão a localização do usuário no mapa, mesmo que ele se desloque.

-----

Agora somos capazes de chamar mapas bem mais modernos em nossas aplicações de Android. Existem muitas outras opções de uso de mapas. Porém, elas serão vistas em outros tópicos deste blog.

Caso alguém tenha uma dúvida, crítica ou sugestão, sinta-se à vontade.