Android Error.os.NetworkOnMainThreadException in using Android HttpURLConnection

I try to make a request for a resource json using HttpURLConnection

I test the following code in onCreate()

   try {
        URL url = new URL("http://localhost/testrealm/api/v1/status");
        HttpURLConnection urlConnection = null;

        urlConnection = (HttpURLConnection) url.openConnection();
        InputStream in = new BufferedInputStream(urlConnection.getInputStream());

        Log.d(TAG, "get json: " + in.toString());
        urlConnection.disconnect();

    } catch (IOException e) {
        e.printStackTrace();
    }

Error in request

Java.lang.RuntimeException: Unable to start activity ComponentInfo ... android.os.NetworkOnMainThreadException

Log Error integer

06-10 14:32:21.113 E/AndroidRuntime: FATAL EXCEPTION: main
  Process: realm.test.app.testrealm, PID: 11702
  java.lang.RuntimeException: Unable to start activity ComponentInfo{realm.test.app.testrealm/realm.test.app.testrealm.MainActivity}: android.os.NetworkOnMainThreadException
      at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2339)
      at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2413)
      at android.app.ActivityThread.access$800(ActivityThread.java:155)
      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1317)
      at android.os.Handler.dispatchMessage(Handler.java:102)
      at android.os.Looper.loop(Looper.java:135)
      at android.app.ActivityThread.main(ActivityThread.java:5343)
      at java.lang.reflect.Method.invoke(Native Method)
      at java.lang.reflect.Method.invoke(Method.java:372)
      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:905)
      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:700)
   Caused by: android.os.NetworkOnMainThreadException
      at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1161)
      at java.net.InetAddress.lookupHostByName(InetAddress.java:418)
      at java.net.InetAddress.getAllByNameImpl(InetAddress.java:252)
      at java.net.InetAddress.getAllByName(InetAddress.java:215)
      at com.android.okhttp.HostResolver$1.getAllByName(HostResolver.java:29)
      at com.android.okhttp.internal.http.RouteSelector.resetNextInetSocketAddress(RouteSelector.java:232)
      at com.android.okhttp.internal.http.RouteSelector.next(RouteSelector.java:124)
      at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:272)
      at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:211)
      at com.android.okhttp.internal.http.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:382)
      at com.android.okhttp.internal.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:332)
      at com.android.okhttp.internal.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:199)
      at realm.test.app.testrealm.MainActivity.onCreate(MainActivity.java:57)
      at android.app.Activity.performCreate(Activity.java:6010)
      at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1129)
      at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2292)
      at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2413) 
      at android.app.ActivityThread.access$800(ActivityThread.java:155) 
      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1317) 
      at android.os.Handler.dispatchMessage(Handler.java:102) 
      at android.os.Looper.loop(Looper.java:135) 
      at android.app.ActivityThread.main(ActivityThread.java:5343) 
      at java.lang.reflect.Method.invoke(Native Method) 
      at java.lang.reflect.Method.invoke(Method.java:372) 
      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:905) 
      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:700) 

Documentation of HttpURLConnection

 5
Author: Webserveis, 2016-06-10

5 answers

NetworkOnMainThreadException : is thrown when you try to perform operations on the main thread, which is incorrect.

If you use StrictMode.ThreadPolicy.Builder to allow any operation, it works but you are disabling a policy that is supposed not to allow certain behavior in the application, in this case operations on the main thread, this is mainly used for development, for production you should not use.

 StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
    StrictMode.setThreadPolicy(policy);

Usa runOnUiThread()

    runOnUiThread(new Runnable() {
        @Override
        public void run() {
            try {  
               proceso(); //Realizar aquí tu proceso!                    

            } catch (Exception e) {
                Log.e("Error", "Exception: " + e.getMessage());
            }
        }
    });

Other options are Asynctask and also Handler.post().

I found this article excellent for more information: "background tasks on Android (I): Thread and AsyncTask" (blog of Salvador Gómez).

 2
Author: Jorgesys, 2016-12-14 16:29:34

You should use AsynkTask:

AsyncTask.execute(new Runnable() {
    @Override
    public void run() {
        try {
            URL url = new URL("http://localhost/testrealm/api/v1/status");
            HttpURLConnection urlConnection = null;

            urlConnection = (HttpURLConnection) url.openConnection();
            InputStream in = new BufferedInputStream(urlConnection.getInputStream());

            Log.d(TAG, "get json: " + in.toString());
            urlConnection.disconnect();

        } catch (IOException e) {
            e.printStackTrace();
        }        
    }
});

If you need to know when you receive response and/or modify views after the call use AsynkTask like this:

new AsyncTask<Void,Void,Void>(){
    @Override
    protected Void doInBackground(Void... voids) {
        try {
           URL url = new URL("http://localhost/testrealm/api/v1/status");
           HttpURLConnection urlConnection = null;

           urlConnection = (HttpURLConnection) url.openConnection();
           InputStream in = new BufferedInputStream(urlConnection.getInputStream());

            Log.d(TAG, "get json: " + in.toString());
            urlConnection.disconnect();

        } catch (IOException e) {
            e.printStackTrace();
        } 
        return null;
     }

     @Override
     protected void onPostExecute(Void aVoid) {
          // your code here
          super.onPostExecute(aVoid);
     }
};
 4
Author: MarcGV, 2017-02-23 14:21:16

Add the following code before performing the web request with HttpURLConnection

    StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
    StrictMode.setThreadPolicy(policy);
 1
Author: Webserveis, 2016-06-10 12:41:48

As another option to this problem, which I also pass it through my hands, is to implement your code inside a runOnUiThread() that will allow access to the main thread variables, since that is just the problem.

In this question, I explain this method:

¿Use Activity.runOnUiThread() or Handler.post (Runnable) to update the main Thread?

As soon as I have the opportunity again I will test your solution and thus know well other possible solutions.

 1
Author: Vicky Vicent, 2017-04-13 13:00:52

This topic is always something to talk about. Definitely disabling policies is not the option.

But beware that this has a lot to do with how you want to do things, in my experience I have seen the following scenarios:

  1. run a long process in the background informing the user of its progress
  2. running a long process in the background without the user knowing about it
  3. run a background process and perform another process according to your result.

Therefore, I do not know what your case is and it is important that you think about it. For the first case AsyncTask it suits you very well. You run your heavy process on the doInBackground, you inform the user about the progress of the same on the publishProgress and at the end you show the result on your screen through the onPostExecute. It is the usual, not only to make requests to servers, it also applies to complicated calculations, database searches, etc. as long as your intention it is to keep the user waiting for that process (something that can be annoying) and that he can interact with the app once it has finished.

For the second case a Thread or a Runnable along with a Handler comes in handy, you run a process in a run method that is independent of its completion State and the user doesn't even know about it.

For the third case, let's take an example: you have a process that captures data and transforms it into useful information, this information is saved in your local database but you must also send it to the server for data redundancy reasons; but you must also wait for the result of the send to the server to update an indicator about the record that defines you whether the Send was successful or not, so as not to send it again for example. For this type of situation, it is best to work with thread schedulers that allow you to execute an action by the time the thread ends its execution. A a very simple example is Google Guava and its classes Futures and ListenableFuture.

Is a bit of additional information to what you have been told that it is good to know it, so define your scenarios well so you can choose a better way to work.

 1
Author: Rosendo Ropher, 2016-06-10 22:45:02