Error android.os.NetworkOnMainThreadException in using Android HttpURLConnection

4

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 the 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

    
asked by Webserveis 10.06.2016 в 14:41
source

5 answers

2
  

NetworkOnMainThreadException : Caused when you try to perform   operations on the main thread (Main thread), which is incorrect.

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

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

Use 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 by Salvador Gómez).

    
answered by 10.06.2016 / 18:28
source
3

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 an answer and / or modify views after the call, use AsynkTask in this way:

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);
     }
};
    
answered by 23.02.2017 в 15:21
1

Add the following code before making the web request with HttpURLConnection

    StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
    StrictMode.setThreadPolicy(policy);
    
answered by 10.06.2016 в 14:41
1

As another option to this problem, which also happens to me by the hands, is to implement your code within a runOnUiThread() that will allow access to the variables of the main thread, 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 chance I will try your solution and know well other possible solutions.

    
answered by 10.06.2016 в 16:22
1

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

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

  • Run a long process in the background informing the user of its progress
  • Run a long process in the background without the user knowing about it
  • Run a process in the background and perform another process according to its result.
  • Therefore, I do not know what your case is and it is important that you think about it. For the first case AsyncTask comes in handy. You execute your heavy process in doInBackground , you inform the user about its progress in publishProgress and at the end you show the result on your screen through onPostExecute . It is the usual, not only to make requests to servers, it is also valid for complicated calculations, searches in database, etc. As long as your intention is to keep the user waiting for that process (something that can be annoying) and that you can interact with the app once it is finished.

    For the second case a Thread or a Runnable along with a Handler comes in handy, you execute a process in a run method that is independent of its completion status and the user not even aware it is given of this.

    For the third case, let's give example: You have a process that captures data and transforms it into useful information, this information is stored in your local database but you must also send it to the server for data redundancy issues; but you should also wait for the result of sending to the server to update an indicator on the record that defines you if the shipment was successful or not, so as not to send it again, for example. For this type of situation it is convenient to work with thread planners that allow you to execute an action for the moment in which the thread finishes its execution. A very simple example is Google Guava and its classes Futures and ListenableFuture .

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

        
    answered by 11.06.2016 в 00:21