[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 = new ArrayList<NameValuePair>();
dados.add(new BasicNameValuePair("pesquisa", "teste");

HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://127.0.0.1/teste.php");
httppost.setEntity(new UrlEncodedFormEntity(dados));
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();
InputStream is = entity.getContent();

HttpConnectionParams.setConnectionTimeout(httppost.getParams(), 100); //eu tentei setar o timeout aqui

int i;
StringBuilder stringBuilder = new StringBuilder();

while ((i = is.read()) >= 0) {
	stringBuilder.append((char) i);
}

System.out.println(stringBuilder.toString());

Como que eu posso setar o timeout aqui?

Obrigada

11 Respostas

E

Oi,

Não sei se é melhor mas para comunicação http, para enviar dados e receber resposta, existe a classe URLConnection. :wink:

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. :wink:

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:
public static String post(String url, List<NameValuePair> dados, int timeout) throws IOException {
		HttpParams httpParameters = new BasicHttpParams();
		HttpConnectionParams.setConnectionTimeout(httpParameters, timeout);
		HttpConnectionParams.setSoTimeout(httpParameters, timeout);

		HttpPost httppost = new HttpPost(url);
		DefaultHttpClient httpClient = new DefaultHttpClient();
		httppost.setEntity(new UrlEncodedFormEntity(dados));
		httpClient.setParams(httpParameters); //eu seto os params aqui... tinha me esquecido disso!

		HttpResponse response = httpClient.execute(httppost);
		HttpEntity entity = response.getEntity();
		InputStream is = entity.getContent();

		if (is == null) {
			return "";
		}

		int i;
		StringBuilder stringBuilder = new StringBuilder();

		while ((i = is.read()) >= 0) {
			stringBuilder.append((char) i);
		}

		return stringBuilder.toString();
	}

Obrigada!

S

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! :slight_smile:

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! :slight_smile:

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

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

Da uma olhada nesse post que ensino a uar o Broadcastreceiver para capturar o evento de conexão com internet:

http://guj.com.br/java/255791-android-conexao-com-mysql-e-gerenciamento-de-dados-com-xml

Qualquer duvida estamos ai.

eliangela

Obrigada! vou fazer com broadcast receiver aqui :wink:

Criado 19 de outubro de 2011
Ultima resposta 21 de out. de 2011
Respostas 11
Participantes 4