Month: December 2014

Don’t make network requests on the UI thread!

Today I was generating an HTTP request in an Android application and I got an exception that briefly confused me. The solution is an obvious one once I understood the reason and to be fair the exception is pretty self explanatory.

The code I has was the following, just to make an HTTP connection and check the file size of the file I was requesting.


  try {
    HttpURLConnection urlConnection = null;
    URL url = new URL("http://www.google.com");

    try {
      urlConnection = (HttpURLConnection) url.openConnection();
      urlConnection.connect();

      int fileLength = urlConnection.getContentLength();
    } catch (IOException exception) {
       // Handle exception
  } finally {
    if (urlConnection != null) {
       urlConnection.disconnect();
    }
  }
 } catch (MalformedURLException malformedUrl) {
   // Handle exception
}

The exception that I got from this code was


Caused by: android.os.NetworkOnMainThreadException
            at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1145)
            at java.net.InetAddress.lookupHostByName(InetAddress.java:385)
            at java.net.InetAddress.getAllByNameImpl(InetAddress.java:236)
            at java.net.InetAddress.getAllByName(InetAddress.java:214)
            at com.android.okhttp.internal.Dns$1.getAllByName(Dns.java:28)
            at com.android.okhttp.internal.http.RouteSelector.resetNextInetSocketAddress(RouteSelector.java:216)
            at com.android.okhttp.internal.http.RouteSelector.next(RouteSelector.java:122)
            at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:292)
            at com.android.okhttp.internal.http.HttpEngine.sendSocketRequest(HttpEngine.java:255)
            at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:206)
            at com.android.okhttp.internal.http.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:345)
            at com.android.okhttp.internal.http.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:89)

The reason for this exception was because I was making a network request from a method that was invoked from a button click in an activity. What I should have done is created a new thread or AsyncTask to make this call. Most people will see this exception and understand immediately or not do such a daft thing in the first place, but if you are new to Android development then the solution may help others.


private class DownloadTask extends AsyncTask {
    @Override
    protected Void doInBackground(Void... sUrl) {
        try {
            HttpURLConnection urlConnection = null;
            URL url = new URL("http://www.google.com");

            try {
                urlConnection = (HttpURLConnection) url.openConnection();
                urlConnection.connect();

                int fileLength = urlConnection.getContentLength();
            } catch (IOException exception) {
                // Handle exception
            } finally {
                if (urlConnection != null) {
                    urlConnection.disconnect();
                }
            }
        } catch (MalformedURLException malformedUrl) {
            // Handle exception
        }
        return null;
    }
}

The task would then be invoked using the following.


new DownloadTask().execute();

Using the new AndroidJUnitRunner from Espresso

So, a new version of Espresso should be out shortly that will be bundled with the Android Support Tools. It will include a new test instrumentation runner and the dependencies should be importable into your Gradle project.

Below shows what you’ll need to do to include the new runner and the dependencies, however, as it’s not out yet the version of androidTestCompile is still TBD. 😦

Can’t wait!


android {
  defaultConfig {
    testInstrumentationRunner 'android.support.test.runner.AndroidJUnitRunner'
  }
}

dependencies {
  androidTestCompile 'android.support.test:support-lib:tbd'
}