Home » Android » android – NetworkOnMainThread

android – NetworkOnMainThread

Posted by: admin June 15, 2020 Leave a comment

Questions:

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.

How to&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.

Answer:

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.

Answer:

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.