Tratando problemas de conexão http nos aplicativos Android

Diversas aplicações android utilizam uma conexão com a internet para conseguir recuperar dados essenciais para o correto funcionamento do aplicativo, alguns exemplos são o Facebook e o Twitter . Um detalhe que nem sempre é lembrado é o de prover um feedback útil para o usuário quando a conexão está com problemas. Por exemplo, ela pode estar lenta ou simplesmente pode ter caído. O que fazer nessas situações?

O primeiro caso é o mais comum e, provavelmente, o que menos recebe atenção. O usuário está conectado mas, como a conexão está muito lenta, o uso da aplicação fica quase impossibilitado. Muitas aplicações fazem uso do ProgressDialog ou, seguindo as mais novas orientações do Google,  do ProgressBar. O problema é que, como a conexão está lenta, esses dois componentes dão a impressão que estão carregando indefinidamente. Lembre-se que mesmo usando uma AsyncTask, o que é recomendado para carregar qualquer dado que seja externo à aplicação, o usuário ainda está sujeito a espera indefinida do processamento da Task.

Para tentar fornecer algum feedback para o usuário sobre a situação, pode-se tentar configurar um tempo de expiração da conexão, caso nada seja trafegado. Caso você esteja usando o Apache HttpComponents, a biblioteca padrão para realizar requisições no Android, você pode definir algumas propriedades como http.socket.timeout e http.connection.timeout para tentar evitar o problema das conexões muito lentas:

httpclient.getParams().setIntParameter("http.socket.timeout", 10000);
httpclient.getParams().setIntParameter("http.connection.timeout", 4000);

É bom conhecer as diversas propriedades e configurações oferecidas pelo HttpComponents. Agora você deve ficar preparado para dar o feedback apropriado para seu usuário. Não tem segredo, ao invés de tratar a exception mais genérica, basta tratar SocketTimeoutException ou  ConnectTimeoutException e devolver uma mensagem mais explicativa para seu usuário, por exemplo: “Sua conexão está lenta, quer tentar de novo?“.

Uma outra abordagem, ainda mais defensiva, é a de tentar estabelecer um número de tentativas de conexão antes de avisar ao usuário que a conexão está lenta ou que caiu. Para não termos que implementar isso na mão,  podemos utilizar a biblioteca LoopJ. Ela já realiza todos requests numa Thread separada, fornecendo métodos de callback para casos de sucesso ou falha e inclusive já vem com a estratégia de tentativas pronta! Essa estratégia é muito importante num ambiente onde a internet não é estável e a qualquer momento o sinal pode ser perdido ou ficar muito fraco.

Para a situação em que o usuário não está conectado ou caso tenha ocorrido algum problema no seu servidor, uma UnknownHostException é lançada e você pode trata-la informando ao usuário que o sistema não está respondendo naquele momento.

O grande ponto é que por mais que uma exception completamente inesperada tenha sido lançada, simplesmente exibir uma mensagem informando que deu  “Erro no servidor” não ajuda muito o usuário. Lembre-se, vários deles não são da área de computação  e não tem nenhuma ideia do que certas mensagens querem dizer. Um outro detalhe importante é que nem sempre o request é essencial para a aplicação, por exemplo o download de um thumbnail. Nessa situação, em caso de falha, pode-se simplesmente ser exibido uma imagem padrão para que isso não interfira na experiência do usuário, além de deixar o thumbnail quebrado linkado para uma nova tentativa de baixá-lo, por exemplo.

Que truques você utiliza para deixar sua aplicação android mais responsiva em relação ao status de sua conexão? Conheça também outras boas práticas no curso de Android da Caelum.

9 Comentários

  1. Eduardo Stuart 25/06/2012 at 13:10 #

    Muito bom post! Uma dúvida..
    Eu utilizo o “LoopJ”, e você falou no post: “…. é a de tentar estabelecer a conexão um número mínimo de vezes antes de avisar ao usuário que a conexão está lenta ou que caiu. Para não termos que implementar isso na mão, podemos utilizar a biblioteca LoopJ…. ”
    Você sabe me dizer, se é possível definir um timeout no LoopJ ? O que quer dizer um número mínimo de vezes (não seria máximo? – 2 tentativas….e falha)..?

  2. Alberto Souza 25/06/2012 at 13:37 #

    Oi Eduardo, fiz a correção em relação ao “número mínimo”, troquei por estabelecer “um número de tentativas”. Me expressei mal :).

    Para definir o timeout, basta chamar o método setTimeout no objeto AsyncHttpClient.

  3. Élysson Mendes Rezende 20/07/2012 at 14:08 #

    Boa tarde tudo bem?
    usei estes parametros com a AsyncTack para deixar um feedback para o usuário enquanto ele espera o sistema recuperar os dados do web service.

    Ficou massa!
    Vlw

  4. Johanes J. Ferreira 09/08/2012 at 00:02 #

    Falando também sobre mais problemas do android, tem um aqui que me custou algum tempo até achar uma solução, tem um post falando sobre isso http://johanesferreira.wordpress.com/2012/08/09/teclado-do-emulador-android-nao-funciona/

  5. Joao 08/01/2013 at 17:57 #

    Embora com boa conexao os aplicativos pararam de funcionar so é possivel acessar as redes sociais pelo navegador.

  6. Leonardo Gazio 11/11/2013 at 04:21 #

    Eu estou com um problema no meu código que é relacionado à isso, já rodei o Google todo procurando solução e não consegui. Quem já tiver passado por isso pode me dar uma dica?

    Segue o link pro tópico que eu abri no GUJ pra quem puder ajudar. Abraços;

    http://www.guj.com.br/java/305927-thread-problema–aplicacao–parou-inesperadamente

  7. Caio Salgado Nepomuceno 25/06/2015 at 11:31 #

    Opa, adorei o post.
    Mas pelo que eu vi, a LoopJ usa o HTTPRequest que agora está deprecated. Sabe me dizer se a LoopJ já possui uma versão com a URLConnection, que agora é o novo método de se usar?

  8. Alberto Souza 25/06/2015 at 11:35 #

    Oi caio, o tempo passou e as melhores libs também mudaram. Tenta dar uma olhada esse daqui http://square.github.io/retrofit/.

Deixe uma resposta