I am trying to get my application to connect to my server. But it throws these errors. How do I fix the MainThreadException? [duplicate]

StackOverflow https://stackoverflow.com/questions/15778166

Question

04-02 21:59:03.086: E/log_tag(27382): Error in http connection android.os.NetworkOnMainThreadException
04-02 21:59:03.106: E/log_tag(27382): Error converting result java.lang.NullPointerException
04-02 21:59:03.106: E/log_tag(27382): Error parsing data org.json.JSONException: End of input at character 0 of 

From the following code:

package net.example.glutefree;

import android.app.Activity;
import android.os.Bundle;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
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 org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.util.Log;
import android.widget.LinearLayout;
import android.widget.TextView;

public class Networking extends Activity {
    TextView txt;
    int request_Code = 1;
//called when activity is first created
    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_networking);
         // Create a crude view - this should really be set via the layout resources 
        // but since its an example saves declaring them in the XML. 
        LinearLayout rootLayout = new LinearLayout(getApplicationContext()); 
        txt = new TextView(getApplicationContext()); 
        rootLayout.addView(txt); 
        setContentView(rootLayout); 
        // Set the text and call the connect function. 
        txt.setText("Connecting...");
      //call the method to run the data retreival
        txt.setText(getServerData(KEY_121));
    }

    public static final String KEY_121 = "http://WEBSITE/application_query.php";

    private String getServerData(String returnString) {
       String UPC = getIntent().getStringExtra("UPCA");
       InputStream is = null;
       String result = "";
        //the upc data to send
        ArrayList<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();

        nameValuePairs.add(new BasicNameValuePair("UPCA",UPC));

        //http post
        try{

                HttpClient httpclient = new DefaultHttpClient();
                HttpPost httppost = new HttpPost(KEY_121);
                httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
                HttpResponse response = httpclient.execute(httppost);
                HttpEntity entity = response.getEntity();
                is = entity.getContent();

        } catch(Exception e) {
                Log.e("log_tag", "Error in http connection "+e.toString());
        }

        //convert response to string
        try {
                BufferedReader reader = new BufferedReader(new InputStreamReader(is,"iso-8859-1"),8);
                StringBuilder sb = new StringBuilder();
                String line = null;
                while ((line = reader.readLine()) != null) {
                        sb.append(line + "\n");
                }
                is.close();
                result=sb.toString();
        } catch(Exception e) {
                Log.e("log_tag", "Error converting result "+e.toString());
        }
        //parse json data
        try {
                JSONArray jArray = new JSONArray(result);
                Log.e("log_tag", "Result "+result.toString()); 
                for(int i=0;i<jArray.length();i++) {
                        JSONObject json_data = jArray.getJSONObject(i);
                        Log.i("log_tag","UPCA: "+json_data.getString("UPCA")+
                                ", Product: "+json_data.getString("Product"));
                        //Get an output to the screen
                        returnString += "\n\t" + jArray.getJSONObject(i);
                }
        } catch(JSONException e) {
                Log.e("log_tag", "Error parsing data "+e.toString());
        }
        return returnString;
    }   

}
Was it helpful?

Solution

Use

new Thread() {
    public void run() {
        final String data = getServerData(KEY_121);
        if (data != null)
            runOnUiThread(new Runnable()
            {
                public void run()
                {
                    txt.setText(data);
                }
            });
    }
}.start();

Instead of:

 //call the method to run the data retreival
 txt.setText(getServerData(KEY_121));

You cannot run long tasks on the main thread. But you have to use the UI thread to set the text.

OTHER TIPS

The issue is that You're trying to execute network request (getServerData()) from UI thread. It's not allowed in order to avoid ANRs (e.g. in case of lack of network connection or slow responses).

Please refer to painless threading article for infromation on how to prepare thread for Your network-related operations. Then, move all code which requires network operation to separate thread.

Android will not allow you to do long-running network operations on the main (UI) thread, because doing so will cause the entire UI to lock up. You'll need to create a new thread in which to handle your network operations. I would recommend creating an AsyncTask, which you can run from the main thread task by calling

new AST(this).execute;  //assuming you've created an AsyncTask class called AST

Here's the doc for AsyncTasks: http://developer.android.com/reference/android/os/AsyncTask.html

The problem is that you are performing network connection on the UI thread. For performance and user experience, Android does not allow that. Try surrounding getServerData() in a thread.

new Thread() {
    public void run() {
        getServerData();
    }
}.start();

You are not supposed to do network activity on the main thread of the Android app. You need to fork a new thread for it.

see this.

In all Android versions 3.0 and above, if you make any network call on the UI thread (the main thread), that exception will be thrown and the app will immediately crash.

You should instead make a subclass on AsyncTask and call your getServerData method from there.

Here is an official blog post on the subject.

Check out AsyncTask here

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top