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.
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.
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.
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
.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With