Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NetworkOnMainThread

I get a NetworkOnMainThreadException when I try to implement the following code:

public class HandlingXMLStuff extends ListActivity{
static final String URL = "xml_file";

 static final String ITEM = "item"; //parent
    static final String Id = "id";
    static final String Name = "name";
    static final String Desc = "desc";
    static final String Link = "Link";

@Override
public void onCreate(Bundle savedInstanceState){
    super.onCreate(savedInstanceState);
    setContentView(R.layout.xmllist);

ArrayList<HashMap<String, String>> menuItems = new ArrayList<HashMap<String, String>>(); 

xmlparser parser = new xmlparser();
String xml = parser.getXmlFromUrl(URL);
Document doc = parser.getDomElement(xml);


NodeList nl = doc.getElementsByTagName(ITEM);


//START: loop through all item nodes <item>
for (int i = 0;i<nl.getLength();i++){
    //lets create our HASHMAP!! (feeds items into our ArrayList)
    HashMap<String, String> map = new HashMap<String, String>();
    Element e = (Element) nl.item(i);
    //add each child node to the HashMap (key, value/<String, String>)
    map.put(Name, parser.getValue(e, Name));
    map.put(Desc, parser.getValue(e, Desc));
    map.put(Link, parser.getValue(e, Link));


    menuItems.add(map);

}//DONE 


ListAdapter adapter = new SimpleAdapter(this, menuItems, R.layout.list_item,
        new String[] {Name, Desc, Link}, new int []{R.id.name, R.id.description, R.id.link});

setListAdapter(adapter);
        }
}

and the handler:

public class xmlparser{

public String getXmlFromUrl(String url) {
String xml = null;

try {

    DefaultHttpClient httpClient = new DefaultHttpClient();
    HttpPost httpPost = new HttpPost(url);

    HttpResponse httpResponse = httpClient.execute(httpPost);
    HttpEntity httpEntity = httpResponse.getEntity();
    xml = EntityUtils.toString(httpEntity);

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

return xml;
}
public Document getDomElement(String xml){
    Document doc = null;
    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
    try {

        DocumentBuilder db = dbf.newDocumentBuilder();

        InputSource is = new InputSource();
            is.setCharacterStream(new StringReader(xml));
            doc = db.parse(is); 

        } catch (ParserConfigurationException e) {
            Log.e("Error: ", e.getMessage());
            return null;
        } catch (SAXException e) {
            Log.e("Error: ", e.getMessage());
            return null;
        } catch (IOException e) {
            Log.e("Error: ", e.getMessage());
            return null;
        }

        return doc;
  }

public String getValue(Element item, String str) {      
        NodeList n = item.getElementsByTagName(str);        
        return this.getElementValue(n.item(0));
    }

public final String getElementValue( Node elem ) {
         Node child;
         if( elem != null){
             if (elem.hasChildNodes()){
                 for( child = elem.getFirstChild(); child != null; child = child.getNextSibling() ){
                     if( child.getNodeType() == Node.TEXT_NODE  ){
                         return child.getNodeValue();
                     }
                 }
             }
         }
         return "";
  }    

}

Any idea why? It should work, all the tutorials I've read treat this as working code but it doesn't run and only throws the exception. I've read I might need to implement asynctask but im new to it and not sure what parts need their own thread. Thanks for any help, critique (constructive), suggestions, etc.

like image 865
Bob Avatar asked Mar 16 '12 23:03

Bob


People also ask

How do you handle Networkonmainthreadexception?

Stay organized with collections Save and categorize content based on your preferences. The exception that is thrown when an application attempts to perform a networking operation on its main thread. This is only thrown for applications targeting the Honeycomb SDK or higher.

What is Android StrictMode?

StrictMode is a developer tool which detects things you might be doing by accident and brings them to your attention so you can fix them. StrictMode is most commonly used to catch accidental disk or network access on the application's main thread, where UI operations are received and animations take place.


3 Answers

Any idea why?

Because, if that hunk of code is being executed on the main application thread, you are doing network I/O on the main application thread.

I've read I might need to implement asynctask but im new to it and not sure what parts need their own thread.

I would put the network I/O and the parsing in doInBackground() and the setListAdapter() call in onPostExecute() of an AsyncTask.

like image 60
CommonsWare Avatar answered Oct 24 '22 08:10

CommonsWare


If you simply want to test your code, and don't want to add any more complications yet, you can add this to your onCreate()

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

You don't want this to be permanent, as network operations on the UI thread makes for a bad experience when using the app, but can be useful when testing.

like image 20
The Holo Dev Avatar answered Oct 24 '22 08:10

The Holo Dev


Adding to CommonsWare answer, the NetworkOnMainThreadException was added sometime between 2.3.3 (Gingerbread_MR1) and 3.0 (Honeycomb). If you look at

android.app.ActivityThread

you will find the following piece of code:

    /**
     * For apps targetting SDK Honeycomb or later, we don't allow
     * network usage on the main event loop / UI thread.
     *
     * Note to those grepping:  this is what ultimately throws
     * NetworkOnMainThreadException ...
     */
    if (data.appInfo.targetSdkVersion > 9) {
        StrictMode.enableDeathOnNetwork();
    }

I think the tutorials that you were following were written before this was put into place, and so did not cause the NetworkOnMainThreadException. Follow CommonsWare instructions regarding AsyncTask and you'll fix your error.

like image 24
louielouie Avatar answered Oct 24 '22 08:10

louielouie