Por que eu devo ler este artigo:

Este artigo apresenta uma série de facilidades que permitem tornar sua aplicação ainda mais interativa. Recursos como uso de GPS, mapas e sintetização de voz serão discutidos, fornecendo uma série de ferramentas para criar um grande diferencial em suas aplicações mobile em Android.

GPS e mapas são recursos que normalmente são utilizados em conjunto para a criação de aplicações baseadas em localização. Já o uso da sintetização de voz permite o desenvolvimento de aplicações altamente interativas, incluindo a possibilidade de construção de facilidades para pessoas com limitações visuais.

Desde o surgimento do primeiro aparelho celular, até os dias de hoje, os esforços têm sido grandes para transformar, inovar, criar e aperfeiçoar tecnologias para facilitar e ajudar tarefas simples do dia a dia, como se comunicar com outras pessoas, pagar uma fatura em aberto no banco, e até mesmo nos momentos de entretenimento, como jogar, escutar música ou assistir a um filme.

Quase 60 anos se passaram e o aparelho que inicialmente pesava quase 40kgs, hoje pode pesar menos de 200 gramas, evoluindo principalmente em suas funcionalidades, pois inicialmente eram utilizados apenas para realizar ligações.

Hoje são utilizados como pequenos computadores, permitindo acesso a informações presentes na Internet, possuem sensores, GPS, mapas, reconhecimento e sintetização de voz, entre muitos outros recursos.

E a popularização do aparelho não para de crescer, segundo dados da consultora IDC, no segundo trimestre de 2013 foram vendidos 8,3 milhões de smartphones no Brasil, um aumento de 110% da comercialização desses equipamentos em relação ao mesmo período em 2012.

Com o aumento da procura desses aparelhos, também aumentou o número de aplicativos, entre eles se destacam aqueles que fazem uso das de tecnologias emergentes, como de o GPS (Global Position System), mapas e sintetização de voz.

O GPS é um complexo sistema de satélites que tem como função prestar informações precisas sobre o posicionamento de um dispositivo no globo terrestre. Os mapas representam em um plano a representação gráfica de um local, com ruas, relevos, recursos, entre outros. Já a sintetização de voz permite a reprodução em áudio de conteúdo digital, como textos.

Neste contexto, neste artigo veremos como fazer uso destas tecnologias em conjunto através do desenvolvimento de um projeto no Android.

Usando recursos de GPS em uma aplicação Android

Em uma aplicação Android, o uso de GPS é algo relativamente simples, entretanto, como foge dos recursos tradicionais da plataforma (já que não existe garantia de que todos os devices Android possuem GPS, por exemplo) é necessário que as aplicações que fazem uso destes recursos sejam assinadas.

Desta forma, no arquivo AndroidManifest.xml, é necessário colocar a permissão do usuário para utilizar estes recursos, por exemplo.

Para testar um aplicativo que utilize GPS, não existe a necessidade de um Device real, podendo este ser testado no emulador, utilizando os recursos da janela Emulator Control.

Para apresentar o recurso de GPS, foi desenvolvido um aplicativo Android tradicional (padrão HelloWorld). Após o projeto criado, algumas alterações são necessárias.

Para permitir que uma aplicação Android utilize o recurso de GPS, existe a necessidade de dar as permissões no arquivo AndroidManifest.xml, conforme Listagem 1.

 <uses-permission  android:name="android.permission.ACCESS_FINE_LOCATION"/>
Listagem 1. AndroidManifest.xml – Permissões para o uso do GPS

Obrigatoriamente, são necessárias as permissões para o acesso à localização.

Para apresentar os dados referentes aos geocódigos capturados do GPS: Latitude e Longitude, a interface gráfica apresentada na Listagem 2 deve ser codificada no arquivo de interface padrão activity_main.xml.


  <?xml version="1.0" encoding="utf-8"?>   
  <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    
    <TextView
      android:id="@+id/TextView01"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_marginLeft="10dip"
      android:layout_marginRight="5dip"
      android:text="Recuperando dados do GPS"
      android:textSize="20dip" >
    </TextView>
  
  </LinearLayout>
Listagem 2. activity_main.xml – Interface gráfica do aplicativo

A interface consiste basicamente em um gerenciador de layout LinearLayout, este configurado para orientação vertical, seguido de um TextView com a mensagem informativa “Recuperando dados do GPS”. Os dados recuperados (Longitude e Latitude) serão apresentados em um componente Toast.

Para tratar a interface gráfica, bem como recuperar os dados do GPS, foi desenvolvida a classe MainActivity.java, esta apresentada com detalhes na Listagem 3.


 public class MainActivity extends Activity implements LocationListener {
 
   @Override
   public void onCreate(Bundle savedInstanceState){
     super.onCreate(savedInstanceState);
     setContentView( R.layout.activity_main );
         
     LocationManager  locationManager = (LocationManager)
       this.getSystemService(Context.LOCATION_SERVICE);
         
     locationManager.requestLocationUpdates(
       LocationManager.GPS_PROVIDER,2000,0,this);
   }
 
   @Override    
   public void onLocationChanged(Location location){
     double latitude = location.getLatitude();
     double longitude = location.getLongitude();
         
     String msg = "Latitude: " + latitude + "\n" + "Longitude: " + longitude;
         
     Toast.makeText(this, msg, 1000).show();
   }
   
   @Override    
   public void onProviderDisabled(String provider){
         
   }
   
   @Override    
   public void onProviderEnabled(String provider){
         
   }
   
   @Override    
   public void onStatusChanged(String provider, int status, Bundle extras){
         
   }
 
 }
Listagem 3. MainActivity.java – Activity para tratamento do aplicativo

Esta classe consiste em um Activity normal, porém esta deve implementar a interface LocationListener para a recuperação dos dados do GPS, assim que acontece a mudança de posição do dispositivo.

A linha 04 codifica o método onCreate(), o qual executa o onCreate() da classe pai, assim como apresenta a interface gráfica do aplicativo.

As linhas que seguem são as mais importantes para o uso do GPS. Na linha 08 é instanciado um objeto do tipo LocationManager, o qual recuperará uma referência do hardware de GPS existente no device Android.

Já a linha 09 informa que a classe que receberá as informações do GPS é a classe atual (representada pela palavra this), ou seja, é esta classe que implementa o método onLocationChanged().

O método onLocationChanged() é codificado na linha 16, sendo que este é chamado toda vez que ocorre a mudança na longitude ou latitude do device. Estes dados são recuperados nas linhas 17 e 18, sendo armazenados em variáveis para utilização na linha 22.

Já o método onProviderDisable() é executado toda vez que o device perde o sinal com os satélites do GPS. O método onProviderEnabled() quando o dispositivo acha os satélites, e onStatusChanged toda vez que acontece mudança no estado do sinal.

Para permitir a simulação dos geocódigos, deve-se utilizar a ferramenta Emulator Control (Menu Window > Show View > Other > Android > Emulator Control). Após executar, o emulador é apresentado para o usuário, conforme Figura 1.

Emulador sendo executado 1
Figura 1. Emulador sendo executado 1

A Figura 2 mostra como a aplicação se comportara ao executar.

GPS 1
Figura 2. GPS 1

API Google Maps

Mapeamento digital é o processo pelo qual um conjunto de dados são compilados e formatados em uma imagem virtual. A função principal desta tecnologia é a produção de mapas que dão representações precisas de uma determinada área, detalhando os principais eixos rodoviários e outros pontos de interesse.

A tecnologia também permite o cálculo de distâncias de um lugar para o outro. Apesar de o mapeamento digital ser encontrado em uma variedade de aplicações computacionais, como o Google Earth, o principal uso desses mapas é com o Sistema de Posicionamento Global, ou a rede de satélites GPS, utilizado em sistemas de navegação automotivo padrão.

Com a API do Google Maps v2 para Android, é possível adicionar mapas com base em dados da Google. A API trata automaticamente o acesso aos servidores do Google Maps, download de dados, visualização do mapa, e resposta a gestos no mapa.

A seguir será mostrado um passo a passo para adicionar um mapa básico na aplicação.

O Google Maps API Android V2 é distribuído como parte do Google Play Services SDK, que trabalha como um gerenciador de pacotes e dispositivos virtuais no seu computador.

Então acesse o menu do Eclipse: Window > Android SDK Manager > Extras > Google Play Services, e instale-o, como pode ser visto na Figura 3.

Download Google Play Services 1
Figura 3. Download Google Play Services 1

Depois de instalado o Google play services, copie a biblioteca, que fica dentro da pasta: sdk\extras\google\google_play_services\libproject\google-play-services_lib para a pasta onde você criou seu projeto Android.

Agora é necessário importar essa biblioteca, para isso clique em File > Import, selecione Android > Existing Android Code into Workspace e vá para a cópia do projeto de biblioteca Google Play Service para importá-lo.

Vá em Properties do seu projeto (clique com o botão direito no seu projeto) e selecione o menu Android.

Clique no botão Add e na caixa de diálogo Project Selection selecione o projeto google-play-services-lib que foi importado anteriormente.

Chave de API

Para acessar as ferramentas do Google Maps, você precisa de uma chave de API, que pode ser obtida através de uma conta do Google. A chave é baseada em sua debug aplicativo Android ou certificado de aptidão.

Caso esteja utilizando Linux, execute o seguinte comando em um terminal:

keytool-list-v-keystore ~ ​​/ .android / debug.keystore-Alias ​​
androiddebugkey-storepass android android-keypass

Se estiver usando Windows, acesse um prompt de comando e informe:

cd C:\Program Files\Java\jdk1.6.0_10\bin -list -v -keystore 
"C:\Users\Meu Usuario\.android/debug.keystore" -alias androiddebugkey 
-storepass android -keypass android

Altere o caminho da debug.keystore, se necessário. Caso ocorra tudo certo, você terá um resultado como mostra a Figura 4.

SHA-1 fingerprint 1
Figura 4. SHA-1 fingerprint 1

O próximo passo é registrar sua SHA-1, acesse o site da API da Google https://code.google.com/apis/console/ logado com uma conta.

Crie um novo projeto e ative a API Google Maps Android API v2, acessando o item Services, como mostrado na Figura 5.

Ativando a API Google Maps 1
Figura 5. Ativando a API Google Maps 1

Posteriormente acesse o item API Access, e crie uma nova chave Android, informando o certificado fingerprints e o pacote da sua aplicação, como mostra a Figura 6.

Criando uma chave Android 1
Figura 6. Criando uma chave Android 1

Criando um novo projeto

Depois de obter a chave, crie um novo projeto Android na IDE Eclipse, e altere o arquivo Manifest da seguinte forma: antes de fechar a tag insira a chave gerada, conforme a Listagem 4.


 <meta-data
   android:name="com.google.android.maps.v2.API_KEY"
   android:value="AIzaSyA3JsSILPDK82LmvSntFEGiMzAov7mT3d4"  />
 <permission android:name="nome_do_pacote.permission.MAPS_RECEIVE"
   android:protectionLevel="signature"/>
 <uses-permission android:name="nome_do_pacote.permission.MAPS_RECEIVE"/>
    
 <uses-permission android:name="android.permission.INTERNET" />
 <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
 <uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/>
 <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
 <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> 
Listagem 4. AndroidManifest.xml – Permissões para o uso da API GoogleMaps

Onde a permissão:

  • INTERNET é usada pela API para baixar o mapa a partir de servidores do Google Maps;
  • ACCESS_NETWORK_STATE permite que a API verifique o status da conexão, a fim de determinar se os dados podem ser transferidos;
  • WRITE_EXTERNAL_STORAGE permite que a API armazene em cache dados do mapa na área de armazenamento externo do dispositivo;
  • providers.gsf.permission.READ_GSERVICES permite que a API acesse serviços baseados na web do Google;
  • ACCESS_COARSE_LOCATION permite à API usar Wi-Fi para determinar a localização do dispositivo.
  • ACCESS_FINE_LOCATION permite à API utilizar o Sistema de Posicionamento Global (GPS) para determinar a localização do dispositivo em uma área muito pequena.

Ainda dentro da tag adicione a biblioteca:


 "com.google.android.maps" />
 "true" android:name="com.google.android.maps">

Insira o código, conforme a Listagem 5.


 <?xml version="1.0" encoding="utf-8"?>
 <fragment xmlns:android="http://schemas.android.com/apk/res/android"
   android:id="@+id/map"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:name="com.google.android.gms.maps.MapFragment"/>
Listagem 5. activity_main.xml – Interface gráfica do aplicativo

A interface conta com o componente fragment, que é a maneira mais fácil de gerenciar um mapa em um aplicativo, onde ele trata automaticamente as necessidades do ciclo de vida – Listagem 6. A saída ficará como a Figura 7.


 public class MainActivity extends Activity {
  @Override
  protected void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   setContentView(R.layout.activity_main);
  }
 }
Listagem 6. Código da classe MainActivity
Google Maps 1
Figura 7. Google Maps 1

API TextToSpeech

Síntese de voz é o processo de produção artificial de voz humana. Para se desenvolver uma técnica de codificação eficiente, é necessário antes conhecer as características básicas do sinal de voz. O mecanismo de produção da voz apresenta uma resposta limitada em frequência, com limite por volta de 10kHz.

Como a maior parte da energia do sinal de voz está concentrada na faixa de frequência entre 300 e 3400 Hz, pode-se limitar o canal a esta banda com uma perda tolerável em qualidade. Para codificação de sinais de voz, algumas propriedades do sinal são exploradas com mais ênfase:

  • A distribuição de probabilidade da amplitude do sinal não é uniforme;
  • A autocorrelação entre amostras sucessivas da voz é diferente de zero;
  • O espectro de frequência do sinal não é uniforme;
  • É possível distinguir no sinal de voz segmentos sonoros e segmentos surdos;

Existe no sinal de voz uma quase periodicidade.

As qualidades mais importantes de um sistema de sintetização de voz são naturalidades (saída de voz parecida com a voz humana) e inteligibilidade (facilidade com que a saída é compreendida).

As duas principais tecnologias de geração da síntese da fala são: síntese por concatenação e síntese por formantes.

Para utilizar o recurso de síntese de voz no Android, no arquivo main.xml será montado o layout com os seguintes componentes (ver Listagem 7):

  • Um label com um texto introdutório;
  • Um campo de texto editável, onde o usuário será capaz de digitar o texto, ocupando a largura da tela;
  • E um botão, que será clicado para ouvir o texto, se ajustando ao tamanho do texto.

 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:tools="http://schemas.android.com/tools"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:paddingBottom="@dimen/activity_vertical_margin"
   android:paddingLeft="@dimen/activity_horizontal_margin"
   android:paddingRight="@dimen/activity_horizontal_margin"
   android:paddingTop="@dimen/activity_vertical_margin"
   tools:context=".MainActivity" >

   <TextView android:id="@+id/intro"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="Digite o texto:" />

   <Button
    android:id="@+id/speak"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_below="@+id/enter"
    android:layout_centerHorizontal="true"
    android:layout_marginTop="30dp"
    android:text="Falar" />

   <EditText
    android:id="@+id/enter"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_alignLeft="@+id/intro"
    android:layout_below="@+id/intro"
    android:layout_marginTop="14dp"
    android:ems="10" />
 
 </RelativeLayout> 
Listagem 7. Código do arquivo main.xml

No arquivo MainActivity.java altere a declaração de classe para implementar os eventos OnClickListener() e OnInitListener():


public class MainActivity extends Activity implements OnClickListener, OnInitListener

No método onCreate() adicione o código:

Button speakButton = (Button)findViewById(R.id.speak);
speakButton.setOnClickListener(this);

Este código cria um novo Intent para verificação dos dados do usuário. Quando o processo de verificação for concluída, o código irá chamar o método onActivityResult().

Intent checkTTSIntent = new Intent();
checkTTSIntent.setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA);
startActivityForResult(checkTTSIntent, MY_DATA_CHECK_CODE);

Quando o usuário clica no botão, o aplicativo precisa obter qualquer texto inserido de forma que você pode passá-lo para o método TTS.

Este código faz referência ao EditText, criado no arquivo de layout. Em seguida, o código obtém o texto do campo e armazena como uma variável de cadeia, nesse exemplo chamada de “words” (Listagem 8).


 public void onClick(View v) {
   EditText enteredText = (EditText)findViewById(R.id.enter);
   String words = enteredText.getText().toString();
   speakWords(words);
 } 

    // -> Nesse método será processada a TTS: 

 private void speakWords(String speech) {
   myTTS.speak(speech, TextToSpeech.QUEUE_FLUSH, null);
 }
Listagem 8. Variável words

Em seguida, adicione o método onActivityResult (Listagem 9).


 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  if (requestCode == MY_DATA_CHECK_CODE) {
   if (resultCode == TextToSpeech.Engine.CHECK_VOICE_DATA_PASS) {
    myTTS = new TextToSpeech(this, this);
   }            
   else {

    Intent installTTSIntent = new Intent();
    installTTSIntent.setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
    startActivity(installTTSIntent);
   }
  }
 }
Listagem 9. Método onActivityResult

Quando houver a verificação de dados da Intent, o aplicativo chama esse método, passando a variável MY_DATA_CHECK_CODEindicando se o usuário tem os dados TTS instalados.

Se os dados estiverem presentes, o código vai à frente e cria uma instância da classe TTS. Se os dados não estiverem presentes, o aplicativo solicitará que o usuário instale.

Agora será implementado o método onInit, conforme a Listagem 10.


 public void onInit(int initStatus) {
  if (initStatus == TextToSpeech.SUCCESS) {
   myTTS.setLanguage(Locale.US);

  }
  else if (initStatus == TextToSpeech.ERROR) {
   Toast.makeText(this, "Desculpe! A Aplicação falhou...", Toast.LENGTH_LONG).show();
  }
 }
Listagem 10. Método onInit

Neste método, são definidas todas as configurações como, por exemplo, o idioma. A Listagem 11 apresenta o código completo da classe MainActivity.


 package utfpr.estagio.texttospeech;

 import java.util.Locale;
 import android.os.Bundle;
 import android.app.Activity;
 import android.content.Intent;
 import android.speech.tts.TextToSpeech;
 import android.speech.tts.TextToSpeech.OnInitListener;
 import android.view.View;
 import android.view.View.OnClickListener;
 import android.widget.Button;
 import android.widget.EditText;
 import android.widget.Toast;

 public class MainActivity extends Activity implements OnClickListener, OnInitListener
 {
 
  private TextToSpeech myTTS;

  private int MY_DATA_CHECK_CODE = 0;
  public void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   setContentView(R.layout.activity_main);   
   Button speakButton = (Button)findViewById(R.id.speak);

   speakButton.setOnClickListener(this);

   Intent checkTTSIntent = new Intent();
   checkTTSIntent.setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA);
   startActivityForResult(checkTTSIntent, MY_DATA_CHECK_CODE);
  }

  public void onClick(View) {
        
   EditText enteredText = (EditText)findViewById(R.id.enter);
   String words = enteredText.getText().toString();
   speakWords(words);
  }

  private void speakWords(String speech) {

   myTTS.speak(speech, TextToSpeech.QUEUE_FLUSH, null);
  }

  protected void onActivityResult(int requestCode, int resultCode, Intent data) {
   if (requestCode == MY_DATA_CHECK_CODE) {
    if (resultCode == TextToSpeech.Engine.CHECK_VOICE_DATA_PASS) {

     myTTS = new TextToSpeech(this, this);
    }
    else {

     Intent installTTSIntent = new Intent();
     installTTSIntent.setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
     startActivity(installTTSIntent);
    }
   }
  }

  public void onInit(int initStatus) {
   if (initStatus == TextToSpeech.SUCCESS) {
    myTTS.setLanguage(Locale.US);

   }
   else if (initStatus == TextToSpeech.ERROR) {
    Toast.makeText(this, "Sorry! Text To Speech failed...", Toast.LENGTH_LONG).show();
   }
  }
 }
Listagem 11. Código completo da classe MainActivity

Ao final teremos o aplicativo sendo executado, conforme apresentado na Figura 8.

Aplicativo TextToSpeech 1
Figura 8. Aplicativo TextToSpeech 1

Como apresentado, todas os recursos são de fácil utilização, entretanto, muitas vezes são encontrados materiais de baixa qualidade na Internet a respeito, o que dificulta o aprendizado e a utilização.

No que diz respeito ao recurso de GPS, o mesmo pode ser emulado no ambiente de desenvolvimento, e sua utilização é muito simples. Sua utilização em um device real fica limitado à conexão com o satélite, que pode não ocorrer em ambientes fechados.

Já a utilização de mapas, antes muito simples com a tradicional API do Google Maps, agora ficou mais complexa com a versão 2, mas este material procurou desmistificar sua utilização.

Por fim, o recurso de sintetização de voz, este pouco utilizado pelos desenvolvedores, é de fácil utilização e promove um diferencial nos aplicativos: a possibilidade de inclusão digital para pessoas com deficiência visual.

Confira também