Por que eu devo ler este artigo:

Inicialmente serão apresentados os conceitos de Web Service bem como o portal webservicex, que dispõe de inúmeros serviços web que podem ser acessados via aplicação web, desktop ou mobile. Na sequência será apresentado o desenvolvimento de um aplicativo para consumir um Web Service sobre condições climáticas. De início, este aplicativo fará uso de multithread usando o modelo tradicional – classe Thread. Depois, será aprimorado para o uso da classe AsyncTask, e por fim será utilizado no aplicativo o componente visual de barra de progresso (ProgressDialog) para apresentar o andamento da conexão.

Uma das principais funções dos smartphones e tablets hoje em dia é a conectividade com a internet. Uma das formas desta conectividade acontecer é via rede da operadora, que permite o acesso a dados de qualquer lugar em que esta esteja acessível.

A conectividade com a internet via dispositivos móveis é possível já que a velocidade das redes de comunicações está cada vez mais rápida, permitindo ficar conectado através de conexões rápidas por várias horas seguidas. Outro atrativo é o custo destes serviços de conectividade via operadora que estão cada vez mais baratos.

Para quem deseja manter-se conectado mas sem custos, uma alternativa são as conexões locais, seja via rede sem fio – wifi – ou através de conexões Bluetooth. Pode-se navegar na Internet sem passar pela rede da operadora, e consequentemente, sem custos.

Segundo um estudo realizado pela Acision, 1/3 dos acessos às redes sociais, tais como Twitter e Facebook, são realizados a partir dos dispositivos portáteis. Também aumentou consideravelmente o número de pessoas que utilizam os dispositivos portáteis para acesso a conta de e-mails, feeds de notícias, sites de compras, entre muitos outros recursos online.

A evolução dos dispositivos móveis é tão grande que hoje é possível acessar uma página na Internet a partir de um smartphone da mesma maneira que acessamos e visualizamos na tela do nosso computador. Também já é possível termos acesso a serviços de rede que até então só estavam disponíveis em computadores desktop, tais como acesso a servidores telnet, contas de FTP, terminais remotos, acesso à Web services, entre outros serviços.

Nesse artigo será apresentada a conexão de um aplicativo Android com um Web Service disponível na rede sobre condições climáticas de várias cidades do mundo. Este Web Service poderia ser desenvolvido pelo próprio usuário com funcionalidades específicas, como manipular um banco de dados.

Conectividade utilizando Web service

Web service é uma tecnologia de acesso a dados que permite a troca de informações estruturada a partir de mensagens XML e SOAP. Esta tecnologia permite que diferentes empresas, mesmo utilizando tecnologias e plataformas distintas, conectem-se de maneira padrão e executem procedimentos remotos através da utilização do protocolo padrão da internet – HTTP. Tudo isso com muita facilidade de utilização, já que muitas vezes o cliente não precisa entender o funcionamento interno dos Web Services.

O uso de Web service é muito interessante, pois se pode acessar rotinas de validação de cartão de crédito, endereçamento postal (CEP), calcular valores de fretes dos sites de comércio eletrônico, news de empresas, previsão do tempo, cotação do dólar, etc. Esta é a tecnologia ideal para disponibilizar dados que costumam mudar com o tempo.

Devido à popularização dessa abordagem, uma gama gigantesca de serviços já está pronta em algum lugar, você só precisa ir lá e acessar, de maneira rápida e fácil, aliviando o processamento na máquina cliente, já que toda a lógica de negócio fica no servidor que hospeda os serviços.

Alguns sites destacam-se por agrupar vários Web services em um só lugar. Um exemplo é o webservicex. Nesse site pode-se encontrar alguns web services interessantes, como para acesso a informações climáticas de uma cidade, previsão de tempo e informações referentes a bolsa de valores.

O Web service que será utilizado nesse artigo informa o clima de uma cidade, dado o nome da cidade e o país da mesma. Esse web service encontra-se na categoria Utilities do webservicex, possuindo o nome de GlobalWeather.

Ao clicar sobre o web service, é possível visualizar algumas informações a respeito dele como, por exemplo, o wsdl que representa o Web service e seus métodos – Figura 1. WSDL significa Web Service Descriptor Language, que nada mais é do que um documento XML que descreve o web service de uma maneira estruturada. Ele contém todas as informações essenciais para que um cliente de Web service, nesse caso, o device Android, possa entender a aplicação servidor que ele representa. Dentre suas características estão o nome dos métodos acessíveis no Web service, onde o serviço está disponibilizado (URL), a documentação para utilizá-lo, o nome e o tipo dos parâmetros dos métodos, bem como os dados de retorno.

Serviço para recuperação de informações climática de uma cidade
Figura 1. Serviço para recuperação de informações climática de uma cidade

Esse Web service será utilizado ao longo do artigo, logo, é necessário tomar nota do caminho WSLD do serviço, uma vez que este será utilizado para fazer referência ao Web service a partir do aplicativo Android. Ainda referente ao Web service, este possui dois métodos sendo o GetCitiesByCountry, o qual espera por parâmetro o nome de um país e retorna todas as cidades cadastras para este, e o GetWeather que espera por parâmetro um nome de cidade (devendo estar cadastrada no servidor) e um país, retornando as condições climáticas desta.

Desenvolvendo a interface do aplicativo Android

Para testar o uso do Web service, o primeiro passo é desenvolver um projeto Android, este com o nome Usando WebService. Para o projeto foi utilizada a versão do Android 4.0.3 (API 15). Após criado, o projeto ficou com a estrutura conforme apresentado na Figura 2.

Estrutura do projeto desenvolvido
Figura 2. Estrutura do projeto desenvolvido

Após a criação do projeto, é necessário desenvolver a interface gráfica do aplicativo, sendo o código apresentado na Listagem 1.


01. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
02.     xmlns:tools="http://schemas.android.com/tools"
03.     android:layout_width="match_parent"
04.     android:layout_height="match_parent"
05.     tools:context=".PrincipalActivity"
06.     android:orientation="vertical">
07.  
08.     <TextView
09.         android:layout_width="wrap_content"
10.         android:layout_height="wrap_content"
11.         android:text="Cidade:" />
12.     
13.     <EditText
14.         android:id="@+id/etCidade"
15.         android:layout_width="wrap_content"
16.         android:layout_height="wrap_content"
17.         android:text="" /> 
18.         
19.     <TextView
20.         android:layout_width="wrap_content"
21.         android:layout_height="wrap_content"
22.         android:text="País:" />
23.     
24.     <EditText
25.         android:id="@+id/etPais"
26.         android:layout_width="wrap_content"
27.         android:layout_height="wrap_content"
28.         android:text="" /> 
29.         
30.      <TextView
31.         android:id="@+id/tvResultado"
32.         android:layout_width="wrap_content"
33.         android:layout_height="wrap_content"
34.         android:text="Resultado:" />
35.      
36.      <Button
37.         android:id="@+id/btPesquisar"
38.         android:layout_width="wrap_content"
39.         android:layout_height="wrap_content"
40.         android:text="Pesquisar" 
41.         android:onClick="btPesquisarOnClick"/>     
42.  
43. </LinearLayout>
Listagem 1. activity_principal.xml – Interface gráfica do aplicativo HelloWorld

Esta interface contém dois campos EditText (linhas 13 e 24) para a digitação do nome da cidade e do país, um TextView (linha 30) para o resultado e um Button (linha 36) para realizar a pesquisa.

Como se trata de uma aplicação com acesso à rede, é importante adicionar a permissão de acesso à internet, caso contrário o aplicativo não pode ser executado. Esta permissão é dada no arquivo AndroidManifest.xml. Na categoria Permission clica-se no botão Add... escolhendo o Uses Permission android.permission.INTERNET, conforme a Figura 3.

Adicionando permissão ao aplicativo para acesso à Internet
Figura 3. Adicionando permissão ao aplicativo para acesso à Internet

Esta mudança adicionará a seguinte entrada no arquivo AndroidManifest.xml:

<uses-permission android:name="android.permission.INTERNET"/>

O próximo passo é modificar a classe PrincipalActivity.java para tratar os componentes visuais e o evento de botão, conforme apresentado na Listagem 2.


01. package br.edu.utfpr.usandowebservices;
02.  
03. import android.app.Activity;
04. import android.content.Context;
05. import android.os.Bundle;
06. import android.view.View;
07. import android.widget.EditText;
08. import android.widget.TextView;
09.  
10. public class PrincipalActivity extends Activity {
11.  
12.   private EditText etCidade;
13.   private EditText etPais;
14.   private TextView tvResultado;
15.   
16.   @Override
17.   protected void onCreate(Bundle savedInstanceState) {
18.        super.onCreate(savedInstanceState);
19.        setContentView(R.layout.activity_principal);
20.        
21.        etCidade = (EditText) findViewById( R.id.etCidade );
22.        etPais = (EditText) findViewById( R.id.etPais );
23.        tvResultado = (TextView) findViewById( R.id.tvResultado );
24.        
25.   }
26.  
27.   public void btPesquisarOnClick( View v ) {
28.        
29.   }
30.   
31. }
Listagem 2. PrincipalActivity.java – Código Java para tratamento da interface gráfica

O código apresentado se resume a importar as classes utilizadas pelo programa (linha 03 a 08), declarar os componentes visuais (linhas 12 a 14), assim como tratar o evento de clique do botão Pesquisar (linha 27 a 29).

Desta forma, o aplicativo está pronto para receber as funcionalidades para acesso ao Web service disponibilizado pelo webservicex.

Preparando o aplicativo para acesso ao Web service

O tráfego de informações entre o aplicativo Android e o servidor onde está hospedado o Web service acontece no formato XML, sendo utilizado o padrão de comunicação SOAP para “envelopar” os pacotes na comunicação. Porém, até o fechamento deste artigo não existia um suporte nativo do Android para a comunicação via SOAP, o que faz necessária a utilização de uma API de terceiro, esta chamada de KSOAP.

Para o download do KSOAP, deve-se acessar a página do projeto conforme Figura 4, clicando na categoria download, baixando o arquivo ksoap2-android-assembly-2-2.4-jar-with-dependencies.jar.

Site do projeto ksoap2
Figura 4. Site do projeto ksoap2

Após baixar o arquivo, deve-se copiar o .jar para dentro da pasta lib do projeto, utilizando o gerenciador de arquivo do sistema operacional (ex. Windows Explorer). Isto garante que a biblioteca seja copiada junto com o projeto, quando este é copiado de uma máquina para outra.

Após isso, é necessário importar a biblioteca para dentro do projeto desenvolvido, clicando com o botão direito sobre o projeto, escolhendo a opção Properties, e na categoria Java Build Path, em Libraries, deve-se adicionar este arquivo .jarFigura 5. Esta biblioteca possui arquivos importantes utilizados para a comunicação com um Web service, tais como SoapObject, SoapEnvelope, SoapSerializationEnvelope e HttpTransportSE.

Adicionando a biblioteca no projeto Android
Figura 5. Adicionando a biblioteca no projeto Android

Acessando Web service a partir do Android

Agora é hora de colocar o código para a comunicação com o Web service. Toda comunicação que envolva a rede deve ser realizada utilizando um Thread separada afim de evitar travamento na interface do aplicativo, uma vez que a comunicação com a rede é intermitente. A maneira tradicional de fazer isso é criar outra classe (esta pode ser uma classe interna de PrincipalActivity.java, a qual herda funcionalidades de Thread e implementa o método run(). Outra maneira de tratar multithread é implementando a interface Runnable, porém, a primeira foi adotada neste artigo.

O código completo do aplicativo, já tratando a comunicação com a rede utilizando multithread é apresentado na Listagem 3.


01. package br.edu.utfpr.usandowebservices;
02.  
03. import android.app.Activity;
04. import android.content.Context;
05. package br.edu.utfpr.usandowebservices;
06.  
07. import org.ksoap2.SoapEnvelope;
08. import org.ksoap2.serialization.SoapObject;
09. import org.ksoap2.serialization.SoapSerializationEnvelope;
10. import org.ksoap2.transport.HttpTransportSE;
11.  
12. import android.app.Activity;
13. import android.os.Bundle;
14. import android.view.View;
15. import android.widget.EditText;
16. import android.widget.TextView;
17.  
18. public class PrincipalActivity extends Activity {
19.  
20.   private EditText etCidade;
21.   private EditText etPais;
22.   private TextView tvResultado;
23.   
24.   @Override
25.   protected void onCreate(Bundle savedInstanceState) {
26.     super.onCreate(savedInstanceState);
27.     setContentView(R.layout.activity_principal);
28.        
29.     etCidade = (EditText) findViewById( R.id.etCidade );
30.     etPais = (EditText) findViewById( R.id.etPais );
31.     tvResultado = (TextView) findViewById( R.id.tvResultado );
32.   }
33.  
34.   public void btPesquisarOnClick( View v ) {
35.     ConexaoThread myTask = new ConexaoThread();
36.     myTask.start();
37.   }
38.   
39.  
40.   class ConexaoThread extends Thread {
41.  
42.     private static final String URL = "http://www.webserviceX.NET";
43.     private static final String METHOD = "GetWeather";
44.     private static final String SOAP_ACTION = "http://www.webserviceX.NET/GetWeather";
45.     private static final String WSDL = "http://www.webservicex.net/globalweather.asmx?WSDL";
46.        
47.     public void run() {
48.       try {
49.         SoapObject request = new SoapObject( URL, METHOD );
50.         request.addProperty( "CityName", etCidade.getText().toString() );
51.         request.addProperty( "CountryName", etPais.getText().toString() );
52.         SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(
53.         SoapEnvelope.VER11 );
54.         envelope.bodyOut = request;
55.         envelope.dotNet = true;
56.         HttpTransportSE ht = new HttpTransportSE( WSDL );
57.         ht.call( SOAP_ACTION, envelope );
58.         final String resposta = envelope.getResponse().toString();
59.                   
60.         PrincipalActivity.this.runOnUiThread( new Thread() {
61.                        
62.           public void run() {
63.             tvResultado.setText( resposta );
64.           }
65.                        
66.         } );
67.                   
68.       } catch ( final Exception e) {
69.         PrincipalActivity.this.runOnUiThread( new Thread() {
70.                        
71.           public void run() {
72.             tvResultado.setText( "Erro: " + e.getMessage() );
73.           }
74.         } );
75.       } 
76.     }
77.   }
78. }
Listagem 3. PrincipalActivity.java – Activity completo acessando Web service

No código apresentado, as primeiras linhas são responsáveis por importar as classes utilizadas no aplicativo, em especial, as classes responsáveis pela comunicação com o Web service (linhas 07 a 10).

Outra diferença desta listagem em relação a Listagem 2 está na chamada da Thread que fará a comunicação com o Web service, o qual acontece no método btPesquisarOnClick() – linha 34. Neste, é instanciado um objeto do tipo ConexaoThread (linha 35), está é uma subclasse de Thread, codificada a partir da linha 40. Após a instanciação, a Thread é executada com o método start() – linha 36.

Já a classe que herda funcionalidades de Thread foi codificada na linha 40, sendo inicialmente declaradas quatro constantes importantes para o acesso ao Web service, que são:

  • URL: Possui o caminho onde o Web service está hospedado;
  • METHOD: Tem o nome do método que será invocado pelo Web service;
  • SOAP_ACTION: Contém o caminho completo do método do Web service que será invocado;
  • WSDL: Caminho do arquivo com o descritivo de todas as funções do Web service.

Uma vez declaradas as constantes, o método run() da Thread será responsável pelo acesso das informações na rede. Na linha 49 é declarado um objeto do tipo SoapObject, o qual contém informações que serão passados para o método do Web service, como os parâmetros para nome de cidade (linha 49) e país (linha 50).

Após isso, estas informações serão encapsuladas em um objeto do tipo SoapSerializationEvelope (linha 52), sendo atribuídos alguns valores, como o corpo da mensagem que será enviado ao Web service (linha 54) e se o Web service foi desenvolvido na tecnologia .net (linha 55).

Por fim, o objeto responsável pela comunicação é instanciado (linha 56), sendo a partir deste executado o método call() – linha 57, o qual invocará o Web service. A resposta pode ser obtida pelo método getResponse() – linha 58, sendo este armazenado em uma variável String.

A plataforma Android tem uma característica: somente a Thread que criou os componentes visuais de tela podem modificá-los. Neste caso, quem criou os componentes visuais foi a classe PrincipalActivity.java, porém, devemos modificar seu conteúdo na classe ConexaoThread. Isto é possível executando o método runOnUiThread() do this da classe que criou os componentes (linha 60). Assim, este método recebe uma Thread por parâmetro que no seu método run() - linha 62, altera o conteúdo do componente TextView do resultado (linha 63). O resultado visual desta execução é apresentado na Figura 6.

Aplicativo apresentando dados retornados de um Web service
Figura 6. Aplicativo apresentando dados retornados de um Web service

Utilizando a classe AsyncTask

Como apresentado anteriormente, toda a comunicação com a rede deve ser executada a partir de uma nova Thread, evitando com isso que a interface gráfica do aplicativo fique travada com a demora na resposta dos servidores.

Como apresentado no exemplo da Listagem 3, é possível a utilização de classes que implementam multithreads, como a classe Thread ou a interface Runnable, ou ainda outras classes como Timer e TimerTask, entretanto, sem dúvida, a melhor opção para este tipo de comunicação é a classe AsyncTask.

Esta classe facilita a codificação de rotinas para acessar a rede, e em especial, permite a modificação de componentes da interface gráfica sem o uso de comandos como runOnUiThread. Assim, a Listagem 4 apresenta o código de acesso a um Web service utilizando AsyncTask.


01. package br.edu.utfpr.usandowebservices;
02.  
03. import org.ksoap2.SoapEnvelope;
04. import org.ksoap2.serialization.SoapObject;
05. import org.ksoap2.serialization.SoapSerializationEnvelope;
06. import org.ksoap2.transport.HttpTransportSE;
07.  
08. import android.app.Activity;
09. import android.content.Context;
10. import android.os.AsyncTask;
11. import android.os.Bundle;
12. import android.view.View;
13. import android.widget.EditText;
14. import android.widget.TextView;
15.  
16. public class PrincipalActivity extends Activity {
17.  
18.   private EditText etCidade;
19.   private EditText etPais;
20.   private TextView tvResultado;
21.   
22.   @Override
23.   protected void onCreate(Bundle savedInstanceState) {
24.     super.onCreate(savedInstanceState);
25.     setContentView(R.layout.activity_principal);
26.        
27.     etCidade = (EditText) findViewById( R.id.etCidade );
28.     etPais = (EditText) findViewById( R.id.etPais );
29.     tvResultado = (TextView) findViewById( R.id.tvResultado );
30.   }
31.  
32.   public void btPesquisarOnClick( View v ) {
33.     ConexaoThread myTask = new ConexaoThread( this );
34.     myTask.execute( etCidade.getText().toString(), etPais.getText().toString() );
35.   }
36.   
37.  
38.   class ConexaoThread extends AsyncTask<String, Integer, String> {
39.  
40.     private static final String URL = "http://www.webserviceX.NET";
41.     private static final String METHOD = "GetWeather";
42.     private static final String SOAP_ACTION = "http://www.webserviceX.NET/GetWeather";
43.     private static final String WSDL = "http://www.webservicex.net/globalweather.asmx?WSDL";
44.        
45.     private Context c;
46.        
47.     public ConexaoThread( Context c ) {
48.       this.c = c;
49.     }
50.        
51.     @Override
52.     protected void onPreExecute() {
53.     }
54.  
55.     @Override
56.     protected String doInBackground(String... params) {
57.       try {
58.         SoapObject request = new SoapObject( URL, METHOD );
59.         request.addProperty( "CityName", params[0] );
60.         request.addProperty( "CountryName", params[1] );
61.         SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(
62.         SoapEnvelope.VER11 );
63.         envelope.bodyOut = request;
64.         envelope.dotNet = true;
65.         HttpTransportSE ht = new HttpTransportSE( WSDL );
66.         ht.call( SOAP_ACTION, envelope );
67.         final String resposta = envelope.getResponse().toString();
68.         return resposta;
69.                   
70.       } catch (Exception e) {
71.                   return e.getMessage();
72.       } 
73.     }
74.        
75.     @Override
76.     protected void onProgressUpdate(Integer... values) {
77.     }
78.  
79.     @Override
80.     protected void onPostExecute(String result) {
81.       tvResultado.setText( "Temperatura: " +  result );
82.     }
83.   }
84. }
Listagem 4. PrincipalActivity.java – Activity completo acessando Web service com AsyncTask

A diferença no aplicativo começa na execução do método btPesquisarOnClick() – linha 38, sendo nesta declarado um objeto do tipo ConexaoThread, que agora é uma subclasse de AsyncTask (linha 38). A diferença com relação ao código anterior é que agora precisamos passar por parâmetro uma instância da classe principal – this. Após isso, o AsyncTask é executado com o método execute() – linha 34, o qual recebe por parâmetro as informações da classe principal utilizada dentro da nova Thread. Para este exemplo são passados os campos cidade e país.

Na declaração da classe ConexaoThrad (linha 38), é informado o tipo dos parâmetros de entrada (String), do parâmetro de incremento (Integer) e do parâmetro de saída (String). Os parâmetros de entrada, para o exemplo, são os campos cidade e estados, passados na linha 34 e que são do tipo String. O parâmetro de saída é o resultado da execução da Thread, neste exemplo é uma String que será apresentada no componente TextView. O parâmetro de incremento é usado caso exista um componente de barra de progresso para mostrar o andamento da execução, por este motivo este campo deve ser inteiro.

Da mesma forma, as constantes com as informações referentes ao Web service são declaradas (linhas 40 a 43), é declarado um objeto Context com o contexto da aplicação (linha 45), sendo este valorizado no método construtor do ConexaoThread (linha 47).

Ao codificar uma subclasse de AsyncTask, quatro métodos possuem codificação obrigatória, são eles:

  • onPreExecute(): Este método é executado logo no início do processamento, nele podem ser criados os componentes de barra de progresso, atribuído valores iniciais a ele, inicializadas variáveis, entre outras operações iniciais da conexão;
  • doInBackGround(): Este método contém a lógica da comunicação. É nele que a rede deve ser acessada. Ele recebe os parâmetros passados na linha 34, faz o processamento e devolve o resultado da comunicação, neste exemplo, a String com a resposta enviada pelo Web service.
  • onPostExecute(): Este método é responsável pela finalização da execução, apresentando o resultado do método doInBackGround() para o usuário. No nosso exemplo, o método doInBackGround retornará uma String, que é o parâmetro deste método e deve formatar o campo de resultado na tela.
  • onProgressUpdate(): Neste método deve ser colocada a lógica para atualizar uma barra de progresso, por exemplo.

Uma visão geral destes quatro métodos, assim como eles se comunicam é apresentada na Figura 7.

Visão geral dos parâmetros do AsyncTask
Figura 7. Visão geral dos parâmetros do AsyncTask

Para o nosso exemplo, os métodos onPreExecute() – linha 52 e onProgressUpdate() – linha 76 não foram codificados. Já o método doInBackground() – linha 56 possui a lógica para comunicação com o Web service. O resultado deste processamento é retornado ao método em caso de sucesso (linha 68) ou erro (linha 71). Após o processamento, o método onPostExecute() é chamado – linha 80), apresentando o resultado do processamento no componente tvResultado.

Desta forma, o acesso à rede fica mais enxuto e elegante, existindo métodos com funções específicas, não sendo necessária a execução de comandos do tipo runOnUiThread.

Adicionando um ProgressBar ao programa

Em aplicativos que fazem uso da rede da operadora, uma boa prática de programação é apresentar, sempre que possível, um componente visual contendo as informações sobre o andamento do acesso à rede.

Isto é importante pois a maioria dos usuários de devices Android com plano de dados pagam por byte trafegado, assim, quanto maior o fluxo de dados, maior o custo de acesso. Logo, se um programa iniciar um acesso à rede e não apresentar a evolução desta conexão, após alguns segundos o usuário começa a se questionar se a comunicação não travou, e muitas vezes, interrompem o fluxo de dados.

Para minimizar este problema, uma boa técnica é o uso do componente ProgressBar, em especial, apresentando ele ao usuário através do componente ProgressDialog.

A Listagem 5 apresenta o código do programa de acesso ao Web service utilizando um componente ProgressDialog.


01. package br.edu.utfpr.usandowebservices;
02.  
03. import org.ksoap2.SoapEnvelope;
04. import org.ksoap2.serialization.SoapObject;
05. import org.ksoap2.serialization.SoapSerializationEnvelope;
06. import org.ksoap2.transport.HttpTransportSE;
07.  
08. import android.app.Activity;
09. import android.app.ProgressDialog;
10. import android.content.Context;
11. import android.os.AsyncTask;
12. import android.os.Bundle;
13. import android.view.View;
14. import android.widget.EditText;
15. import android.widget.TextView;
16.  
17. public class PrincipalActivity extends Activity {
18.  
19.   private EditText etCidade;
20.   private EditText etPais;
21.   private TextView tvResultado;
22.   private ProgressDialog progresso;
23.   
24.   @Override
25.   protected void onCreate(Bundle savedInstanceState) {
26.     super.onCreate(savedInstanceState);
27.     setContentView(R.layout.activity_principal);
28.        
29.     etCidade = (EditText) findViewById( R.id.etCidade );
30.     etPais = (EditText) findViewById( R.id.etPais );
31.     tvResultado = (TextView) findViewById( R.id.tvResultado );
32.        
33.   }
34.  
35.   public void btPesquisarOnClick( View v ) {
36.        
37.     ConexaoThread myTask = new ConexaoThread( this );
38.     myTask.execute( etCidade.getText().toString(), etPais.getText().toString() );
39.   }
40.   
41.   class ConexaoThread extends AsyncTask<String, Integer, String> {
42.  
43.     private static final String URL = "http://www.webserviceX.NET";
44.     private static final String METHOD = "GetWeather";
45.     private static final String SOAP_ACTION = "http://www.webserviceX.NET/GetWeather";
46.     private static final String WSDL = "http://www.webservicex.net/globalweather.asmx?WSDL";
47.        
48.     private Context c;
49.        
50.     public ConexaoThread( Context c ) {
51.       this.c = c;
52.     }
53.        
54.     @Override
55.     protected void onPreExecute() {
56.       progresso = new ProgressDialog( c );
57.       progresso.setMessage( "Acessando WebService" );
58.       progresso.setProgressStyle( ProgressDialog.STYLE_HORIZONTAL );
59.       progresso.setMax( 10 );
60.       progresso.setCancelable( false );
61.       progresso.show();
62.     }
63.  
64.     @Override
65.     protected String doInBackground(String... params) {
66.       try {
67.         SoapObject request = new SoapObject( URL, METHOD );
68.         this.publishProgress( 1 );
69.         request.addProperty( "CityName", params[0] );
70.         this.publishProgress( 2 );
71.         request.addProperty( "CountryName", params[1] );
72.         this.publishProgress( 3 );
73.         SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(
74.         SoapEnvelope.VER11 );
75.         this.publishProgress( 4 );
76.         envelope.bodyOut = request;
77.         this.publishProgress( 5 );
78.         envelope.dotNet = true;
79.         this.publishProgress( 6 );
80.         HttpTransportSE ht = new HttpTransportSE( WSDL );
81.         this.publishProgress( 7 );
82.         ht.call( SOAP_ACTION, envelope );
83.         this.publishProgress( 8 );
84.         final String resposta = envelope.getResponse().toString();
85.         this.publishProgress( 9 );
86.         return resposta;
87.                   
88.       } catch (Exception e) {
89.         return e.getMessage();
90.       } 
91.        
92.     }
93.        
94.     @Override
95.     protected void onProgressUpdate(Integer... values) {
96.       progresso.setProgress( values[0] );
97.     }
98.  
99.     @Override
100.    protected void onPostExecute(String result) {
101.                  
102.      String temperatura = result.substring( result.indexOf( "<Temperature>") + 13, 
103.      result.indexOf( "</Temperature>") );
104.                  
105.      tvResultado.setText( "Temperatura: " +  temperatura );
106.      progresso.dismiss();
107.    }
108.   
109.    }
110.       
111.       
112.  }
Listagem 5. PrincipalActivity.java – Activity completo acessando Web service com AsyncTask e ProgressDialog

A diferença deste aplicativo em relação ao aplicativo anterior inicia na linha 22, quando um objeto do tipo ProgressDialog é declarado. Dentro da classe ConexaoThread, no método onPreExecute() – linha 55, o ProgressDialog é instanciado (linha 56), assim como definida a mensagem apresentada para o usuário (linha 57), sua apresentação como uma barra horizontal (linha 58), seu valor máximo (linha 59) e que o mesmo não poderá ser cancelado pelo usuário (linha 60), sendo apresentado na interface (linha 60).

Já o método onProgressUpdate() – linha 95 é a responsável pela atualização do andamento do ProgressDialog, sendo nele definido o comando para atualização (linha 96).

O valor inteiro que o método onProgressUpdate é passado através do método publishProgress(), e costuma ser executado no método doInBackground() – linha 65).

Como pode ser observado, após cada comando, um valor sequencial e crescente é passado por parâmetro no método publishProgress (linhas 68 a 85). Isso fará com que o ProgressBar seja atualizado durante o acesso ao Web service.

Ao final do processamento, no método onPostExecute(), é apresentada para o usuário apenas a informação referente ao campo Temperatura (linha 102 e 103), sendo na sequência retirado o objeto da classe ProgressDialog da tela (linha 106). O resultado da utilização do ProgressDialog é apresentado na Figura 8.

Utilizando um ProgressDialog para acesso à rede
Figura 8. Utilizando um ProgressDialog para acesso à rede

Embora alguns usuários e empresas critiquem o uso de Web service a partir de dispositivos móveis, dado a grande quantidade de dados “extras” trafegados na rede pelo uso de mensagens XML e SOAP. Este ainda é o meio mais comum de acessar dados, em especial, dados não estáticos, como cotação do dólar e informações sobre a bolsa de valores.

Ainda podemos destacar que está cada vez mais barato o acesso à internet, existindo inclusive planos onde o acesso a dados é ilimitado, o que incentiva ainda mais o uso de Web service por devices Android.

Confira também