50

I have this exception and I was reading a thread on this, and it seemed confusing:

How to fix android.os.NetworkOnMainThreadException?

I already added this line to my manifest:

<uses-permission android:name="android.permission.INTERNET" />

On that discussion, they talk about the main execution thread of the app not being able to do networking. What I am wondering is how to restructure my code so that it is inline with Android good practices.

Here is my Activity class for this:

package com.problemio;

import java.io.InputStream;
import java.util.ArrayList;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
public class LoginActivity extends Activity 
{
    public void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.login);

        // Show form for login_email
        final EditText loginEmail = (EditText) findViewById(R.id.login_email);  
        String name = loginEmail.getText().toString();  

        // Show field for password  
        final EditText password = (EditText) findViewById(R.id.password);  
        String text = password.getText().toString();                  

        // Show button for submit
        Button submit = (Button)findViewById(R.id.submit);   




        // Show options for create-profile and forgot-password




        submit.setOnClickListener(new Button.OnClickListener() 
        {  
           public void onClick(View v) 
           {
              String email = loginEmail.getText().toString();
              String pass = password.getText().toString(); 
              sendFeedback(pass, email);
            }
        });        
    }


    public void sendFeedback(String pass , String email) 
    {  
        Log.d( "1" , pass );
        Log.d( "1" , email );

        // Go to db and check if these r legit
        // How do I do that? :)
        ArrayList<NameValuePair> postParameters = new ArrayList<NameValuePair>();  
        postParameters.add(new BasicNameValuePair("username", email ));  
        postParameters.add(new BasicNameValuePair("password", pass ));

        String responseString = null;

        try 
        {  
            HttpClient httpclient = new DefaultHttpClient();
            HttpPost httppost = new HttpPost("myUrl");

            // no idea what this does :)
            httppost.setEntity(new UrlEncodedFormEntity(postParameters));

            // This is the line that send the request
            HttpResponse response = httpclient.execute(httppost);

            HttpEntity entity = response.getEntity();            

            InputStream is = entity.getContent();
        } 
        catch (Exception e) 
        {     
            Log.e("log_tag", "Error in http connection "+e.toString());
        }        
    }          
}

What am I doing wrong here and how could I fix it? :) Thanks!!

Community
  • 1
  • 1
GeekedOut
  • 16,905
  • 37
  • 107
  • 185
  • 3
    possible duplicate of [android.os.NetworkOnMainThreadException](http://stackoverflow.com/questions/6343166/android-os-networkonmainthreadexception) – Peter O. Apr 03 '13 at 22:03
  • Use OkHTTP library: http://square.github.io/okhttp/ or AsyncTask(as others said) – Yousha Aleayoub Mar 12 '16 at 12:45

10 Answers10

59

NetworkOnMainThreadException: The exception that is thrown when an application attempts to perform a networking operation on its main thread.

You should call sendfeedback method on asynctask then only above code will work. As webserver is taking lot of time to response main thread becomes unresponsive. To avoid it you should call it on another thread. Hence asynctask is better.

here is link that illustrates how to use asynctask

RevanthKrishnaKumar V.
  • 1,855
  • 1
  • 21
  • 34
  • 2
    `AsyncTask` is now deprecated, a better alternative is to use `java.util.concurrent.Executors` to execute networking tasks in another thread. – Daniel C Jacobs Sep 16 '21 at 13:45
36

NetworkOnMainThreadException is thrown when your app tries networking operation in main thread.

To fix that you can use a private inner class within your Activity that extends android.os.AsyncTask<Params, Progress, Result> which will do the server call stuffs.

Something as,

private class SendfeedbackJob extends AsyncTask<String, Void, String> {

    @Override
    protected String doInBackground(String[] params) {
        // do above Server call here
        return "some message";
    }

    @Override
    protected void onPostExecute(String message) {
        //process message
    }
}

And then invoke above class from submit.setOnClickListener as below,

SendfeedbackJob job = new SendfeedbackJob();
job.execute(pass, email);

AsyncTask

References

AsyncTask doc

AsyncTask Android example

Community
  • 1
  • 1
prayagupa
  • 30,204
  • 14
  • 155
  • 192
14
if (android.os.Build.VERSION.SDK_INT > 9) {
    StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
    StrictMode.setThreadPolicy(policy);
}
k__gc_im_o_
  • 140
  • 1
  • 7
AnDx
  • 824
  • 8
  • 11
  • 7
    Not really, when you just need a small test and created a fresh small android project just for that.. :) – Henrique de Sousa Oct 15 '13 at 16:04
  • 1
    Well its a good idea, if you are just testing the app for data manipulation, and don't wanna bother about threads for a while. – Muhammad Aug 31 '14 at 11:01
  • Strictly not recommended, but if you're testing some functionality and need to do it faster you can use it. It's strongly suggested that you shouldn't use this in a production environment. We don't want badly designed apps, do we? – 0xC0DED00D Sep 17 '14 at 10:17
  • For more discussion (45 comments!) see here: http://stackoverflow.com/a/9289190/253938 – RenniePet Sep 25 '15 at 03:24
8
 try 
    {  
        HttpClient httpclient = new DefaultHttpClient();
        HttpPost httppost = new HttpPost("myUrl");

        // no idea what this does :)
        httppost.setEntity(new UrlEncodedFormEntity(postParameters));

        // This is the line that send the request
        HttpResponse response = httpclient.execute(httppost);

        HttpEntity entity = response.getEntity();            

        InputStream is = entity.getContent();
    } 
    catch (Exception e) 
    {     
        Log.e("log_tag", "Error in http connection "+e.toString());
    }        

Here is your problem. Since api 11, this exception will inform you that you are running long tasks on the ui thread (the http communication in your class), and according with the new StrictGuard policy this is not possibile. So you have two different choice

  1. Use thread or aynctask in order to execut yout long term task (better way)
Blackbelt
  • 156,034
  • 29
  • 297
  • 305
3

You can just create Async class as below

class Retrievedata extends AsyncTask<String, Void, String> {
@Override
    protected String doInBackground(String... params) {
         try{
                //Your code 
                }
        return null;
    }
}

You can just put your all code inside doInBackground method

Kirtikumar A.
  • 4,140
  • 43
  • 43
  • use volley library-Have a look at this -http://stackoverflow.com/questions/16836992/how-to-do-a-simple-async-task-using-volley-library-android – Mahalakshmi Jan 08 '16 at 10:09
3

You made network call on main thread which is against to android rules, so you have to do your network call on separate thread like asynctask or handler etc.

Sankar
  • 1,685
  • 2
  • 16
  • 27
1

Use thread for that case,

Thread thread = new Thread(new Runnable() {

    @Override
    public void run() {
        try  {
            //Code here
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
});

thread.start(); 
Hardik Hirpara
  • 2,594
  • 20
  • 34
  • 1
    I like this answer because it uses java code and a Thread. Why? 1. because all this convert to kotlin stuff sucks. 2. constant deprecations async now concurrent bla bla bla so I'll bet that deprecating Thread will be too hard for google to do. – dcarl661 May 12 '23 at 16:35
  • @dcarl661 Agreed. – Tigerrrrr Aug 06 '23 at 09:15
0

look at this link : https://developer.android.com/reference/android/os/NetworkOnMainThreadException.html

The exception that is thrown when an application attempts to perform a networking operation on its main thread. Applications targeting earlier SDK versions are allowed to do networking on their main event loop threads, but it's heavily discouraged.

if you set minSdkVersion <11, then your application will work and you can run network operation in main thread.

amin
  • 561
  • 6
  • 18
0

After a long research (lasted half day) I have found a solution for my problem which is similar to the problem indicated here. The exception displayed by my Android Studio 2.3.3 was this:

android studio android.os.networkonmainthreadexception

The problem was based on the impossibility to set a UI variable in the MainActivity. So I saw the following video and I solved my problem. I hope it is also useful to others:

How to avoid android os NetworkOnMainThreadException

0

As indicated here, AsyncTask is deprecated, and Google recommends you use the java.util.concurrent package or Kotlin coroutines

You can execute your network task in another thread very easily using java.util.concurrent.Executors.

Simply add these two variables to your LoginActivity class:

val executor = Executors.newSingleThreadExecutor()

Then surround your networking call with an executor.execute{} block:

executor.execute {
    /**
     * Executes network task in background. You cannot
     * access view elements here.
     */
    
    HttpResponse response = httpclient.execute(httppost);
    
    HttpEntity entity = response.getEntity();            

    InputStream is = entity.getContent()

}
Daniel C Jacobs
  • 691
  • 8
  • 18