Como Receber Dados de um WebService no Android

Neste post vou demonstrar como tratar informações vindas de um webservice desenvolvido em .NET em uma aplicação Android.

O webservice utilizado nesta aplicação é o mesmo publicado no post Retornando Dados em Json com WebService .NET. Este WebService retorna a relação de estados do Brasil juntamente com as informações de área, capital e abreviação em formato Json.

A aplicação Android vai receber as informações do webservice, tratar os dados e exibir  a relação de estados em um ListView.

A aplicação possui duas classes Principal.java e WebService.java. Na classe WebService.java foi criado o método getEstados() que se conecta ao WebService e retorna os dados em uma String que contêm as informações formatas em Json. (Listagem 1).

Listagem 1:
public class WebService {
    private static final int TIMEOUT_CONEXAO = 20000; // 20 segundos
    private static final int TIMEOUT_SOCKET = 30000; // 30 segundos
    private static final int TAM_MAX_BUFFER = 10240; // 10Kbytes
    private String url;
    
    public WebService(String url) {
        this.url = url;
    }
    
    public String getEstados(){
        String parserbuilder = "";
        
        try{
            HttpParams httpParameters = new BasicHttpParams();
            
            // Configura o timeout da conexão em milisegundos até que a conexão
            // seja estabelecida
            HttpConnectionParams.setConnectionTimeout(httpParameters, 
                    TIMEOUT_CONEXAO);
            
            // Configura o timeout do socket em milisegundos do tempo 
            // que será utilizado para aguardar os dados
            HttpConnectionParams.setSoTimeout(httpParameters, 
                    TIMEOUT_SOCKET);   
            
            HttpClient httpclient = new DefaultHttpClient(httpParameters);
            HttpPost httppost = new HttpPost(url + "/GetEstados");
    
            HttpResponse response = httpclient.execute(httppost);
            
            BufferedReader reader = new BufferedReader(
                    new InputStreamReader(response.getEntity().getContent(),
                            "UTF-8"), TAM_MAX_BUFFER);
            
            StringBuilder builder = new StringBuilder();
            
            for (String line = null ; (line = reader.readLine())!= null;) {
                builder.append(line).append("\n");
            }
            
            parserbuilder = builder.toString();
            
            // Retira a string <?xml version="1.0" encoding="utf-8" ?> 
            // <string xmlns="http://tempuri.org/"> e a tag </string> 
            // para obter o resultado em Json, já que o webservice está
            // retornando uma string
            Integer firstTagString = parserbuilder.indexOf("<string");
            Integer posXml = parserbuilder.indexOf(">", firstTagString);
            Integer posTagString = parserbuilder.indexOf("</string>");
            parserbuilder = parserbuilder.substring(posXml + 1, posTagString + 1);
        
        }catch(ClientProtocolException e){
            Log.e("WebService", e.toString());
        }
        catch(IOException e){
            Log.e("WebService", e.toString());
        }
        
        return parserbuilder;    
    }
}
No método getEstados() foi utilizada a classe BasicHttpParams() para configurar os timeouts de conexão, e as classes DefaultHttpClient(HttpParams) e HttpPost(String) para fazer uma requisição tipo Post no WebService.

A informação retornada pelo WebService .NET é um Xml que retorna uma String com dados no formato Json. Para facilitar a obtenção das informações no formato Json, optei em tratar a String retornada pelo WebService de modo a ter somente a informação no formato Json.

Na classe Principal.java no método onCreate(Bundle) foi chamada a classe WebService() e feito o tratamento para exibir os estados no ListView. (Listagem 2)

Listagem 2:
public class Principal extends ListActivity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        List<String> estados = new ArrayList<String>();
        
        // o endereço http://localhost no emulador deve
        // se chamado como http://10.0.2.2, porque o
        // endereço http://localhost ou http://127.0.0.1
        // é utilizado pelo próprio emulador
        WebService webService = 
            new WebService("http://10.0.2.2:4362/websitejson/service.asmx");
        
        // Obtêm a resposta do webservice
        String resultado = webService.getEstados();
        
        try {
            // Utiliza a classe JSONArray para obter as
            // informações e separar o campo que será
            // utilizado no listview
            JSONArray json = new JSONArray(resultado);
            
            for (int i = 0; i < json.length(); i++) {
                JSONObject jsonObj = json.getJSONObject(i);
                
                // Insere o estado na lista de estados
                estados.add(jsonObj.getString("Nome"));
            }
            
        } catch (JSONException e) {
            Log.e("WebService", e.toString());
        }
        finally{
            setListAdapter(new ArrayAdapter<String>(this, 
                    android.R.layout.simple_list_item_1, estados));
        }
        
    }
}
O webservice está rodando no localhost (127.0.0.1) porta 4362, mas para chamar o webservice no emulador do android não pode ser utilizado o IP 127.0.0.1 porque este IP é utilizado no emulador, por isso na URL utilizar o IP 10.0.2.2.

Para obter somente os estados utilizei as classe JSONArray e JSONObject para extrair a informação desejada. 

Antes de rodar a aplicação não esquecer de dar permissão de acesso à internet no arquivo AndroidManifest.xml.
    <uses-permission android:name="android.permission.INTERNET"></uses-permission>
A aplicação rodando vai exibir a seguinte tela:

tela1

A API utilizada HttpDefaultClient é melhor para dispositivos que utilizam a versão 2.2 (Froyo) ou anterior do Android. Para as versões 2.3 (Gingerbread) ou superior é melhor utilizar a API HttpURLConnection. O post Usando HttpURLConnection para Receber Dados no Android demonstra como utilizar esta API.