Android HTTP Client : Network error and ConnectivityManager

In this post I will show how to handle http client network error or the situation when the connection changes (i.e from UMTS to WI-FI). In all these cases we have to gracefully handle these errors and implement some strategies to try to reconnect if possible.
In a perfect world when we connect to a remote server with HTTP protocol everything works perfectly, we don’t have to worry about connection errors, server under heavy request load or unstable network. Previously, we talked about how we can connect to a remote server and how we can send and receive data. In the real world, usually, while we are connected to a remote server we walk or run or even we are in a car, so that the network signal can vary or it can suddenly break. At the same time Android can device to switch from UMTS to WI-FI or vice versa or it can switch from one APN to another and so on. When we code our app, we have to take into account all these situations and handle them correctly.


http client network error

We can simplify and try to classify all these events in two classes:

  • Network error
  • Network configuration changes
What HTTP library are you using for your Android app? Check this post about Android HTTP library to know the best one to use.

If we used Apache HTTP Client there’s already a mechanism that helps us, we could implement HttpRequestRetryHandler interface with our retry mechanism logic or a default implementation. If we use the standard Android HTTP connection we have to implement is by ourselves.

HTTP Client Network error: Handling connection error

In this post I showed how to connect to a remote server and we created an HttpClient class that manages the connection. In this case we extend this class handling http client network error. To do it we use the call back mechanism, in other word we set up a listener that gets notified when there is a connection error. To do it we create an interface:
[java] public interface HttpConnectionRetryHandler {
public boolean shouldRetry(Throwable t, int attemptNumber) ;
}
[/java] This interface has just only one method where we implement our logic to handle or not the network error. We pass the exception and a counter that holds the number of attempt to re-establish the connection. The HttpClient then has to be modified to handle the client network connection error. It doesn’t have to raise an exception as soon as it can’t connect to the server but has to ask to our class that implements HttpConnectionRetryHandler if it should raise the exception or try to connect again.
[java] public void connect(String method, Properties props) throws HttpClientException {
boolean status = true;
int attemptNumber = 0;
while (status) {
try {
attemptNumber++;
doConnection(method, props);
status = false;
}
catch(Throwable t) {
if (handler != null) {
status = handler.shouldRetry(t, attemptNumber);
if (!status)
throw new HttpClientException(t);
}
else {
throw new HttpClientException(t);
}
}
}
}[/java] At line 12 when we have an exception we call handler.shouldRetry to verify if our connection error handler wants to handle the error or not. If not we raise the exception otherwise we keep on trying to reconnect. In our class, that handles the error we implement our business logic. The simplest thing is checking the number of attempts. In this case, we have:
[java]public class DefaultHttpConnectionRetryHandler implements HttpConnectionRetryHandler {

@Override
public boolean shouldRetry(Throwable t, int attemptNumber) {
System.out.println(“Attempt [“+attemptNumber+”]”);
if (attemptNumber > 5)
return false;
return true;
}
}[/java] So when we call the HttpClient we have:
[java]…
client.setHandler(new DefaultHttpConnectionRetryHandler());
…[/java]

Handling network configuration changes

As we said early while we move with our smartphone or tablet the network configuration can chance switching from WI-FI to UMTS or vice versa or from UTMS to switching from one APN to another (maybe in roaming). We have to handle all these changes and try to use the network configurations to re-establish the connection. To handle these events we can use a Broadcast receiver that gets notified when a network configuration change occurs. Changes in APN configuration or in changes in connectivity is handle by ConnectivityManager that broadcast some information to its subscribers. So the first thing we code our broadcast receiver:
[java] public class ConnectionMonitorReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context ctx, Intent intent) {
System.out.println(“Receive..”);
NetworkInfo netInfo = (NetworkInfo) intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
if (netInfo == null)
return ;

System.out.println(“Here”);
if (netInfo.getType() == ConnectivityManager.TYPE_MOBILE) {
String proxyHost = System.getProperty( “http.proxyHost” );
String proxyPort = System.getProperty( “http.proxyPort” );
if (proxyHost != null)
HttpClient.getInstance().setProxy(proxyHost, proxyPort);
else
HttpClient.getInstance().setProxy(null, null);
}
}[/java] At line 1 we simply extends the BroadcastReceiver and we implement onReceive method (line 4). At line 6 we get the information shipped inside the intent broad and implements our logic. In our case, we simply check if the proxy is changed but we could implement other types of business logic.

The last thing we have to do is register our broadcast receiver so that it can be called. We do it in our onCreate method of the Activity:
[java]registerReceiver(new ConnectionMonitorReceiver(), new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));[/java] Running the code we have:

Immagine1 Immagine2

Source code available @ github

    1. michael October 3, 2013
    2. yasar October 5, 2013
    3. survivingwithandroid October 7, 2013
    4. survivingwithandroid October 8, 2013

    Add Your Comment