[RESOLVIDO] Setar timeout ao enviar dados via post (Android)
11 respostas
eliangela
Olá Pessoal!
Estou desenvolvendo um projeto para Android que envia dados via POST para um servidor.
A minha aplicação já está detectando:
- quando o Wifi do celular não está ligado;
- quando o Wifi está ligado, mas não está conectado.
- quando o Wifi está ligado e conectado a uma rede.
O problema da minha aplicação é quando a qualidade do sinal wireless está num nível muito baixo, e a minha aplicação envia dados via post e fica esperando mais de um minuto pela resposta, até cair numa exceção:
java.io.IOException: java.net.SocketException: Connection timed out
Ou seja, está caindo em timeout.
Eu quero configurar o timeout pra 1 segundo (mais ou menos) pra minha aplicação não ficar travada, e dar uma resposta logo.
Eu tentei fazer isso pra resolver:
List<NameValuePair>dados=newArrayList<NameValuePair>();dados.add(newBasicNameValuePair("pesquisa","teste");HttpClienthttpclient=newDefaultHttpClient();HttpPosthttppost=newHttpPost("http://127.0.0.1/teste.php");httppost.setEntity(newUrlEncodedFormEntity(dados));HttpResponseresponse=httpclient.execute(httppost);HttpEntityentity=response.getEntity();InputStreamis=entity.getContent();HttpConnectionParams.setConnectionTimeout(httppost.getParams(),100);//eu tentei setar o timeout aquiinti;StringBuilderstringBuilder=newStringBuilder();while((i=is.read())>=0){stringBuilder.append((char)i);}System.out.println(stringBuilder.toString());
Não sei se é melhor mas para comunicação http, para enviar dados e receber resposta, existe a classe URLConnection.
abs,
Evandro
toshikurauchi
Oi Eliangela!
Então, na hora que você seta o timeout o httpclient já executou o post. Tente colocar a linha do timeout antes de chamar o execute.
Outra coisa, você está fazendo essa requisição em outra thread?
eliangela
Evandro_Contato:
Oi,
Não sei se é melhor mas para comunicação http, para enviar dados e receber resposta, existe a classe URLConnection.
abs,
Evandro
Oi Evandro!
Eu preciso usar post mesmo. Existe uma maneira de setar o timeout, mas eu devo estar fazendo errado.
[ ]'s
eliangela
toshikurauchi:
Oi Eliangela!
Então, na hora que você seta o timeout o httpclient já executou o post. Tente colocar a linha do timeout antes de chamar o execute.
Outra coisa, você está fazendo essa requisição em outra thread?
Olá toshikurauchi!!
Obrigada pela ajuda!
eu vi que eu setei o timeout somente depois de executar o httpclient, e também vi que eu esqueci de setar o httpParams denovo!
O código ficou assim:
publicstaticStringpost(Stringurl,List<NameValuePair>dados,inttimeout)throwsIOException{HttpParamshttpParameters=newBasicHttpParams();HttpConnectionParams.setConnectionTimeout(httpParameters,timeout);HttpConnectionParams.setSoTimeout(httpParameters,timeout);HttpPosthttppost=newHttpPost(url);DefaultHttpClienthttpClient=newDefaultHttpClient();httppost.setEntity(newUrlEncodedFormEntity(dados));httpClient.setParams(httpParameters);//eu seto os params aqui... tinha me esquecido disso!HttpResponseresponse=httpClient.execute(httppost);HttpEntityentity=response.getEntity();InputStreamis=entity.getContent();if(is==null){return"";}inti;StringBuilderstringBuilder=newStringBuilder();while((i=is.read())>=0){stringBuilder.append((char)i);}returnstringBuilder.toString();}
Obrigada!
S
srmachado
Como eu faria!
primeiramente como uma boa pratica, colocar sempre um try/catch para tratar as exception, fica ai a dica, vc pode usar um objeto do tipo Handler que serve para processar alguma coisa depois de um certo tempo, funciona com uma Thread.sleep(), ai vc configura seu handler com o delay de 1 segundo, ou vc tbm pode usar um Alarm para agendar sua rotina, fica ai a dica, da uma pesquisada sobre a classe Headler http://developer.android.com/reference/android/os/Handler.html e AlarmaManager http://developer.android.com/reference/android/app/AlarmManager.html e outra coisa vc tbm poderia delegar o envio do post para uma thread. Qualque duvida posta ai.
toshikurauchi
Legal que funcionou!
E reforço que é uma boa prática fazer esses processamentos mais demorados (como as requisições web) em threads separadas, como o srmachado falou… Isso para não bloquearmos a thread principal que é reservada para a interação com o usuário (entrada e saída, atualização da tela, etc).
eliangela
toshikurauchi:
Legal que funcionou!
E reforço que é uma boa prática fazer esses processamentos mais demorados (como as requisições web) em threads separadas, como o srmachado falou… Isso para não bloquearmos a thread principal que é reservada para a interação com o usuário (entrada e saída, atualização da tela, etc).
Concordo com vcs nisso, e eu tenho threads que fazem essas coisas separadamente no meu programa (até coisas em segundo plano), mas nesse caso específico, a resposta tem que ser instantânea, porque é um caso onde o cliente não pode ficar esperando pela boa vontade do wireless.
Bom… try/catch tem lá, porque quando cai em timeout, dá uma exception mesmo. Daí eu trato com uma mensagem dizendo que não tem conexão disponível.
Sobre essa ideia do Handler e ficar monitorando, eu fiz um parecido pra guardar informações quando não tiver conexão, e quando o smartphone conectar, ele envia as informações pendentes pro servidor.
Pessoal, obrigada pela ajuda.
Até mais
S
srmachado
Vc usou o esquema de Broadcastreceiver?
eliangela
Eu não conhecia esse esquema (acabei de pesquisar e achei interessante), mas eu fiz assim:
criei uma Thread que é ativada quando tem algum dado pendente de envio. Essa Thread fica monitorando a cada 5 segundos se existe conexão. Caso exista ele envia os dados pro servidor.
Quando esses dados são enviados com sucesso, eu seto a flag da minha thread pra FALSE pra finalizá-la.
Vou pesquisar mais sobre o Broadcast Receiver e vou ver se implemento aqui.
Obrigada
S
srmachado
Da uma olhada nesse post que ensino a uar o Broadcastreceiver para capturar o evento de conexão com internet: