26

I have a problem with my code and I was hoping for some help. I was firstly using this code :

        new DefaultHttpClient().execute(new HttpGet(linkk)).getEntity().writeTo(
           new FileOutputStream(f));

And it works just fine on android 2.3 but on 4.0 it doesn't. After some research, I hear that is better to use AndroidHttpClient and this way it will work on 4.0 and 3.1. The problem is that I do not know whether I have modified my code correctly and there aren't too many examples regarding AndroidhttpClient on the internet.

Here is my code that was adjusted:

    AndroidHttpClient client = AndroidHttpClient.newInstance("Android");
    HttpGet request = new HttpGet(linkk);   
    HttpResponse response = client.execute(request); //here is where the exception is thrown    
    response.getEntity().writeTo(new FileOutputStream(f));

This is what the logcat shows:

     01-03 01:32:11.950: W/dalvikvm(17991): threadid=1: thread exiting with uncaught exception (group=0x40a2e1f8)
     01-03 01:32:11.986: E/AndroidRuntime(17991): FATAL EXCEPTION: main
     01-03 01:32:11.986: E/AndroidRuntime(17991): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.lacra.fbirthdays/com.lacra.fbirthdays.ListV}: android.os.NetworkOnMainThreadException
     01-03 01:32:11.986: E/AndroidRuntime(17991):   at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1956)
     01-03 01:32:11.986: E/AndroidRuntime(17991):   at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1981)
     01-03 01:32:11.986: E/AndroidRuntime(17991):   at android.app.ActivityThread.access$600(ActivityThread.java:123)
     01-03 01:32:11.986: E/AndroidRuntime(17991):   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1147)
     01-03 01:32:11.986: E/AndroidRuntime(17991):   at android.os.Handler.dispatchMessage(Handler.java:99)
     01-03 01:32:11.986: E/AndroidRuntime(17991):   at android.os.Looper.loop(Looper.java:137)
     01-03 01:32:11.986: E/AndroidRuntime(17991):   at android.app.ActivityThread.main(ActivityThread.java:4424)
     01-03 01:32:11.986: E/AndroidRuntime(17991):   at java.lang.reflect.Method.invokeNative(Native Method)
     01-03 01:32:11.986: E/AndroidRuntime(17991):   at java.lang.reflect.Method.invoke(Method.java:511)
    01-03 01:32:11.986: E/AndroidRuntime(17991):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
    01-03 01:32:11.986: E/AndroidRuntime(17991):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
    01-03 01:32:11.986: E/AndroidRuntime(17991):    at dalvik.system.NativeStart.main(Native Method)
    01-03 01:32:11.986: E/AndroidRuntime(17991): Caused by: android.os.NetworkOnMainThreadException
    01-03 01:32:11.986: E/AndroidRuntime(17991):    at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1099)
    01-03 01:32:11.986: E/AndroidRuntime(17991):    at java.net.InetAddress.lookupHostByName(InetAddress.java:391)
    01-03 01:32:11.986: E/AndroidRuntime(17991):    at java.net.InetAddress.getAllByNameImpl(InetAddress.java:242)
    01-03 01:32:11.986: E/AndroidRuntime(17991):    at java.net.InetAddress.getAllByName(InetAddress.java:220)
    01-03 01:32:11.986: E/AndroidRuntime(17991):    at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:137)
    01-03 01:32:11.986: E/AndroidRuntime(17991):    at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164)
    01-03 01:32:11.986: E/AndroidRuntime(17991):    at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119)
    01-03 01:32:11.986: E/AndroidRuntime(17991):    at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:360)
    01-03 01:32:11.986: E/AndroidRuntime(17991):    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555)
Jakub Šturc
  • 35,201
  • 25
  • 90
  • 110
Lara
  • 781
  • 3
  • 8
  • 21

2 Answers2

72

StrictMode.ThreadPolicy was introduced since API Level 9 and the default thread policy had been changed since API Level 11, which in short, does not allow network operation (include HttpClient and HttpUrlConnection) get executed on UI thread. if you do this, you get NetworkOnMainThreadException.

This restriction can be changed, using:

    if (android.os.Build.VERSION.SDK_INT > 9) {
      StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
      StrictMode.setThreadPolicy(policy);
    }

Add the above code into your main activity's onCreate() method.

In addition, it is always recommended to move network operation off the UI thread, for example, using AsyncTask.

hope this help.

Josh
  • 12,448
  • 10
  • 74
  • 118
yorkw
  • 40,926
  • 10
  • 117
  • 130
  • 9
    The whole point of these policies is to force good practice and emsure your application performs well. Turning the policies off is a bad idea. See Sbossb's answer for the right approach. – rgardler May 05 '12 at 08:30
  • 4
    @rgardler, read the answer carefully: **it is always recommended to move network operation off the UI thread, for example, using AsyncTask.** Thread policy was changed without highlighted and many consumer developer are not aware, it is worth to point out the exact reason why same code work in GingerBread but nor HoneyComb, Also note that AsyncTask is recommended but definitely not the only right approach. – yorkw May 05 '12 at 08:50
  • 2
    @yorkw Ugh... why would you put this as the answer?!? Beginners looking for a quick fix aren't going to care... they are just going to copy and paste your code into their project and it'll be your fault when another crappy app gets published on the Android Market. – Alex Lockwood Aug 01 '12 at 05:23
  • 1
    There's no reason why you should ever disable `StrictMode`... it is there for a reason. – Alex Lockwood Aug 01 '12 at 05:25
  • Actually I am using an async http library which does the networking component in a background thread but passes control back to the caller.. Certain calls at that point can fail (but only on certain phones).. For instance if I try to shutdown the connection on the UI thread, even though it takes a really tiny amount of time it throws that exception. If i try to read data from the response (after the response has returned), I occasionally get that error as well. – Matt Wolfe Sep 10 '12 at 23:44
  • @yorkw thnx for your answer +1 for u its worked for me you save my lot of time... – Karthik Sep 28 '13 at 12:43
31

Use an AsyncTask so that the network request does not block the UI thread. The NetworkOnMainThreadException was introduced since API version 11, which is the reason why it is only showing up 3.0 and up.

private class NetworkTask extends AsyncTask<String, Void, HttpResponse> {
    @Override
    protected HttpResponse doInBackground(String... params) {
        String link = params[0];
        HttpGet request = new HttpGet(link);
        AndroidHttpClient client = AndroidHttpClient.newInstance("Android");
        try {
            return client.execute(request);
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        } finally {
        client.close();
    }
    }

    @Override
    protected void onPostExecute(HttpResponse result) {
        //Do something with result
        if (result != null)
            result.getEntity().writeTo(new FileOutputStream(f));
    }
}

To call this thread simple do this.

new NetworkTask().execute(linkk);

Take a look at this article written on the Android developer site. It explains in more detail how to write your app to handle threads.

M-Wajeeh
  • 17,204
  • 10
  • 66
  • 103
Stefan Bossbaly
  • 6,682
  • 9
  • 53
  • 82
  • I have tried this and it gives me an error that I can't solve. Here is what the logcat shows : 01-03 15:01:46.508: E/AndroidRuntime(23161): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.lacra.fbirthdays/com.lacra.fbirthdays.ListV}: java.lang.IndexOutOfBoundsException: Invalid index 0, size is 0 01-03 15:36:44.121: E/AndroidRuntime(24957): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1956) – Lara Jan 03 '12 at 13:41
  • I have commented the String link = params[0]; and I have also surrounded client.execute(request); with try/catch – Lara Jan 03 '12 at 13:44