Consumindo WebService pelo Android - Dúvidas

E ai galera beleza,

Gostaria de poder contar com a ajuda de vocês, tenho um WebService Rest desenvolvido em Java o mesmo já está funcionando, a minha dúvida está na parte do Android na hora de consumir os dados do banco.

Tenho as seguintes classes:

  • UsuarioREST

public class UsuarioREST {
private static final String URL_WS = “http://10.1.1.103:8084/ServidorWS/webresources/Usuario/Usuario/get/”;

public Usuario getUsuario(int id) throws Exception {

 String[] resposta = new Webservice().get(URL_WS+id);
 
 if (resposta[0].equals("200")) {
     Gson gson = new Gson();
     Usuario usuario = gson.fromJson(resposta[1], Usuario.class);
     return usuario;
 } else {
     throw new Exception(resposta[1]);
 }
}

}

  • HttpClient

private static final int JSON_CONNECTION_TIMEOUT = 3000;
private static final int JSON_SOCKET_TIMEOUT = 5000;
private static HttpClient instance;
private HttpParams httpParameters ;
private DefaultHttpClient httpclient;

    private void setTimeOut(HttpParams params){
     HttpConnectionParams.setConnectionTimeout(params, JSON_CONNECTION_TIMEOUT);
     HttpConnectionParams.setSoTimeout(params, JSON_SOCKET_TIMEOUT);
    }
    
    private HttpClient() {
     httpParameters = new BasicHttpParams();
     setTimeOut(httpParameters);
     httpclient = new DefaultHttpClient(httpParameters);
    }
    
    public static DefaultHttpClient getHttpClientInstace(){
     if(instance==null)
         instance = new HttpClient();
     return instance.httpclient;
    }
  • Webservice

public final String[] get(String url) {

     String[] result = new String[2];
    

     try {
    	 HttpGet httpget = new HttpGet(url);
	     HttpResponse response;
         response = HttpClient.getHttpClientInstace().execute(httpget);
         entity = response.getEntity();

         if (entity != null) {
             result[0] = String.valueOf(response.getStatusLine().getStatusCode());
             InputStream instream = entity.getContent();
             result[1] = toString(instream);
             instream.close();
             Log.i("get", "Result from post JsonPost : " + result[0] + " : " + result[1]);
         }
     } catch (Exception e) {
         Log.e("NGVL", "Falha ao acessar Web service", e);
         result[0] = "0";
         result[1] = "Falha de rede!";
     }
     return result;
    }
  • MainActivity

buscarIdBtn.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
        	id = idEdt.getText().toString();
            UsuarioREST rest = new UsuarioREST();
            try {
                Usuario usuario = rest.getUsuario(Integer.parseInt(id));
                txtView.setText(usuario.toString());
            } catch (NumberFormatException e) {
                e.printStackTrace();
                gerarToast("Digite um ID válido!");
            } catch (Exception e) {
                e.printStackTrace();
                gerarToast(e.getMessage());
            }
        }
    });

Essas são minhas classes no cliente android.
Gostaria de executar um GET e pegar dados de uma tabela que estão no banco, o erro que está aparecendo está na classe “Webservice”. segue o erro: “Falha ao acessar Web service”.
O que vocês acham que pode ser.

O primeira coisa que deve ser feito é alterar a seguinte linha:

Para:

Log.e(“NGVL”, e.getMessage(), e);

Pois a mensagem “Falha ao acessar Web service” é sua e não representa o erro em si.

Depois que vc fizer isso roda a aplicação e posta o erro que será impresso.

Se vc não jogar a exception fica difícil né ?

Retornou “null”.

Segue o log:

03-16 14:57:26.387: E/NGVL(984): null
03-16 14:57:26.387: E/NGVL(984): android.os.NetworkOnMainThreadException
03-16 14:57:26.387: E/NGVL(984): at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1117)
03-16 14:57:26.387: E/NGVL(984): at libcore.io.BlockGuardOs.connect(BlockGuardOs.java:84)
03-16 14:57:26.387: E/NGVL(984): at libcore.io.IoBridge.connectErrno(IoBridge.java:144)
03-16 14:57:26.387: E/NGVL(984): at libcore.io.IoBridge.connect(IoBridge.java:112)
03-16 14:57:26.387: E/NGVL(984): at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:192)
03-16 14:57:26.387: E/NGVL(984): at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:459)
03-16 14:57:26.387: E/NGVL(984): at java.net.Socket.connect(Socket.java:842)
03-16 14:57:26.387: E/NGVL(984): at org.apache.http.conn.scheme.PlainSocketFactory.connectSocket(PlainSocketFactory.java:119)
03-16 14:57:26.387: E/NGVL(984): at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:144)
03-16 14:57:26.387: E/NGVL(984): at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164)
03-16 14:57:26.387: E/NGVL(984): at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119)
03-16 14:57:26.387: E/NGVL(984): at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:360)
03-16 14:57:26.387: E/NGVL(984): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555)
03-16 14:57:26.387: E/NGVL(984): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487)
03-16 14:57:26.387: E/NGVL(984): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:465)
03-16 14:57:26.387: E/NGVL(984): at com.android.ws.Webservice.get(Webservice.java:32)
03-16 14:57:26.387: E/NGVL(984): at com.android.apptoner.UsuarioREST.getUsuario(UsuarioREST.java:12)
03-16 14:57:26.387: E/NGVL(984): at com.android.activity.MainActivity$1.onClick(MainActivity.java:49)
03-16 14:57:26.387: E/NGVL(984): at android.view.View.performClick(View.java:4202)
03-16 14:57:26.387: E/NGVL(984): at android.view.View$PerformClick.run(View.java:17340)
03-16 14:57:26.387: E/NGVL(984): at android.os.Handler.handleCallback(Handler.java:725)
03-16 14:57:26.387: E/NGVL(984): at android.os.Handler.dispatchMessage(Handler.java:92)
03-16 14:57:26.387: E/NGVL(984): at android.os.Looper.loop(Looper.java:137)
03-16 14:57:26.387: E/NGVL(984): at android.app.ActivityThread.main(ActivityThread.java:5039)
03-16 14:57:26.387: E/NGVL(984): at java.lang.reflect.Method.invokeNative(Native Method)
03-16 14:57:26.387: E/NGVL(984): at java.lang.reflect.Method.invoke(Method.java:511)
03-16 14:57:26.387: E/NGVL(984): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
03-16 14:57:26.387: E/NGVL(984): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
03-16 14:57:26.387: E/NGVL(984): at dalvik.system.NativeStart.main(Native Method)
03-16 14:57:26.399: W/System.err(984): java.lang.Exception: Falha de rede!
03-16 14:57:26.417: W/System.err(984): at com.android.apptoner.UsuarioREST.getUsuario(UsuarioREST.java:19)
03-16 14:57:26.417: W/System.err(984): at com.android.activity.MainActivity$1.onClick(MainActivity.java:49)
03-16 14:57:26.417: W/System.err(984): at android.view.View.performClick(View.java:4202)
03-16 14:57:26.417: W/System.err(984): at android.view.View$PerformClick.run(View.java:17340)
03-16 14:57:26.428: W/System.err(984): at android.os.Handler.handleCallback(Handler.java:725)
03-16 14:57:26.428: W/System.err(984): at android.os.Handler.dispatchMessage(Handler.java:92)
03-16 14:57:26.428: W/System.err(984): at android.os.Looper.loop(Looper.java:137)
03-16 14:57:26.428: W/System.err(984): at android.app.ActivityThread.main(ActivityThread.java:5039)
03-16 14:57:26.428: W/System.err(984): at java.lang.reflect.Method.invokeNative(Native Method)
03-16 14:57:26.428: W/System.err(984): at java.lang.reflect.Method.invoke(Method.java:511)
03-16 14:57:26.438: W/System.err(984): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
03-16 14:57:26.438: W/System.err(984): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
03-16 14:57:26.448: W/System.err(984): at dalvik.system.NativeStart.main(Native Method)
03-16 14:57:27.128: E/SurfaceFlinger(36): ro.sf.lcd_density must be defined as a build property

da um e.toString(); no lugar do e.getMessage();
Mas ao que parece pelo stack trace, ele não ta batendo la no ws.
Já testou a url no postman ?
http://10.1.1.103:8084/ServidorWS/webresources/Usuario/Usuario/get/1 por ex
E precisa ver o http code retornado resposta[0]
E outra coisa inverta sua comparação, se sua resposta[0] vier null, nullpointerexception
"200".equals(resposta[0])

O problema é que você está tentando consultar o web service na UI Thread, você deve usar no mínimo um AsyncTask.
Descrição do erro:
http://developer.android.com/intl/pt-br/reference/android/os/NetworkOnMainThreadException.html

O Link abaixo tem a solução para o seu problema em português:

1 curtida

Dei uma lida no link que você mandou, só não entendi de que forma vou chamar essa classe no meu projeto.

Segue a classe:

public class Consulta extends AsyncTask<String, Void, Boolean> {

@Override
protected Boolean doInBackground(String... params) {

    String URL = "http://10.1.1.103:8084/ServidorWS/webresources/Usuario/Usuario/get";
    String linha = "";
    Boolean Erro = true;

    if (params.length > 0)
        // faço qualquer coisa com os parâmetros

        try {

            HttpClient client = new DefaultHttpClient();
            HttpGet requisicao = new HttpGet();
            requisicao.setHeader("Content-Type",
                    "text/plain; charset=utf-8");
            requisicao.setURI(new URI(URL));
            HttpResponse resposta = client.execute(requisicao);
            BufferedReader br = new BufferedReader(new InputStreamReader(
                    resposta.getEntity().getContent()));
            StringBuffer sb = new StringBuffer("");

            while ((linha = br.readLine()) != null) {
                sb.append(linha);
            }

            br.close();

            linha = sb.toString();
            Erro = false;

        } catch (Exception e) {
            Erro = true;
        }

    return Erro;
}

}

Seu código deve ficar mais ou menos assim:

@Override
public void onClick(View v) {
    int id = idEdt.getText().toString();

    AsyncTask<Integer, Void, Usuario> atBuscaUsuario = new AsyncTask<Integer, Void, Usuario>() {

        ProgressDialog progressDialog;

        @Override
        protected Usuario doInBackground(Integer... params) {
            try {
                UsuarioREST rest = new UsuarioREST();
                Usuario usuario = rest.getUsuario(Integer.parseInt(params[0]));
                return usuario;

            } catch (NumberFormatException e) {
                e.printStackTrace();
                gerarToast("Digite um ID válido!");
                
            } catch (Exception e) {
                e.printStackTrace();
                gerarToast(e.getMessage());
            }

            return null;
        }

        @Override
        protected void onPreExecute() {
            super.onPreExecute();

            progressDialog = ProgressDialog.show(getActivity(), "Aguarde", "Buscando usuario...");
        }

        @Override
        protected void onPostExecute(Usuario usuario) {
            super.onPostExecute(usuario);

            if (usuario != null) {
                txtView.setText(usuario.toString());
            }

            progressDialog.dismiss();
        }
    };
    atBuscaUsuario.execute(id);
}

/**
 * 
 * Forca a exibicao de uma mensagem fora da UI Thread (MainThread)
 * 
 * @param msg
 */
private void gerarToast(final String msg) {
    getActivity().runOnUiThread(new Runnable() {
        @Override
        public void run() {
            Toast.makeText(getActivity(), msg, Toast.LENGTH_LONG).show();
        }
    });
}
1 curtida

Tive duas dúvidas nesse código que você mandou:

1º Esse “id” do tipo “int”, no caso na tela do android ele recebe uma String nesse caso ai deu erro.

2º Eu preciso criar uma classe com o método “getActivity()”?

Esqueci de fazer o cast no campo id:

        1º    int id = Integer.parseInt(idEdt.getText().toString());
        2º    Esse "getActivity()" é o contexto de onde você está chamando o método, se vc estiver chamando apartir de uma Activity vc deve chamar SuaActivity.this, se vc estivesse chamando apartir de uma fragment vc deveria chamar getActivity(), entendeu?
1 curtida

Valeu ai cara, os dois ítens foram solucionados com suas dicas agora ficou um erro nessa linha:

Usuario usuario = rest.getUsuario(Integer.parseInt(params[0]));

Disse que o método parseInt (String) não é aplicado para o argumento Integer.

Não precisa fazer o cast, deixa o código assim:

1 curtida

Deu certo, agora vou testar o app pra ver se fluiu.
Desde já agradeço.

Agora deu certo.

Muitíssimo abrigado não sei nem como lhe agradecer, já estava com quase uma semana batendo nesse erro. Agora fluiu.

É nóis. qualquer coisa posta aí.