android.os.NetworkOnMainThreadException – StrictMode$AndroidBlockGuardPolicy

Usecase

Sending a request to invoke a URL/API/Resource over the Internet from the Activity.

Exception

E/LiveTraxs(29173): HttpApiService:81-Exception : nullE/LiveTraxs(29173): android.os.NetworkOnMainThreadException
android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1208)
E/LiveTraxs(29173):     at java.net.InetAddress.lookupHostByName(InetAddress.java:388)
E/LiveTraxs(29173):     at java.net.InetAddress.getAllByNameImpl(InetAddress.java:239)
E/LiveTraxs(29173):     at java.net.InetAddress.getAllByName(InetAddress.java:214)
E/LiveTraxs(29173):     at libcore.net.http.HttpConnection.<init>(HttpConnection.java:70)
E/LiveTraxs(29173):     at libcore.net.http.HttpConnection.<init>(HttpConnection.java:50)
E/LiveTraxs(29173):     at libcore.net.http.HttpConnection$Address.connect(HttpConnection.java:340)
E/LiveTraxs(29173):     at libcore.net.http.HttpConnectionPool.get(HttpConnectionPool.java:87)
E/LiveTraxs(29173):     at libcore.net.http.HttpConnection.connect(HttpConnection.java:128)
E/LiveTraxs(29173):     at libcore.net.http.HttpEngine.openSocketConnection(HttpEngine.java:315)
E/LiveTraxs(29173):     at libcore.net.http.HttpEngine.connect(HttpEngine.java:310)
E/LiveTraxs(29173):     at libcore.net.http.HttpEngine.sendSocketRequest(HttpEngine.java:289)
E/LiveTraxs(29173):     at libcore.net.http.HttpEngine.sendRequest(HttpEngine.java:239)
E/LiveTraxs(29173):     at libcore.net.http.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:80)
libcore.net.http.HttpURLConnectionImpl.getOutputStream(HttpURLConnectionImpl.java:188)

Cause & Solution

The Http request to access a network resouce is being made within the same main UI Thread. This will block the main UI thread, making the app un-responsive. By default Android does not allow making such Sync Network call and results into the NetworkOnMainThreadException.

This issue can be bypassed by disabling the StrictMode Android Block Guard Policy by adding a Policy override in the Activity as:

Even though this will work it is not a good approach as it makes Unresponsive, the user cannot cancel the operation, leading to bad experience and some case it may take long time to complete depending on the operation and network speed etc. The better way would be to use create an Async Task and do any Network level IO in that.

  1. private class LoginTask extends AsyncTask {
  2.  
  3.                 @Override
  4.                 protected Void doInBackground(Voidparams) {
  5.  
  6.                         // try to login : Network Task
  7.                         loginResponse = HttpApiService.login(username, password);
  8.  
  9.                         return null;
  10.  
  11.                 }
  12.  
  13.                 @Override
  14.                 protected void onPreExecute() {
  15.                         super.onPreExecute();
  16.        
  17.                 }
  18.  
  19.                 @Override
  20.                 protected void onProgressUpdate(Voidvalues) {
  21.                         super.onProgressUpdate(values);
  22.  
  23.                 }
  24.  
  25.                 @Override
  26.                 protected void onPostExecute(Void v) {
  27.                         super.onPostExecute(v);
  28.  
  29.  
  30.                 }
  31.  
  32. }

<!>