0

I have an app that has an xml Dom parser in it. The parser activity is activated by a button in another fragment. When i run the app it runs fine on Gingerbread, but on Honeycomb and up to Jelly Bean it force closes every time. Here is the class information and the log cat file for when it force closes. IF anyone has any ideas on what is causing this please let me know.

Class I'm trying to launch

 public class CustomizedListView extends SherlockActivity {
// All static variables
static final String URL = "http://treymorgan.net/feed";
// XML node keys
static final String KEY_ID = "channel"; // parent node 
static final String KEY_ITEM = "item";
static final String KEY_TITLE = "title";
static final String KEY_PUB_DATE = "pubDate";
static final String KEY_LINK = "link";

ListView list;
LazyAdapter adapter;

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
    case android.R.id.home:
        // app icon in action bar clicked; go home
                    Intent intent = new Intent(this, MainActivity.class);
                    intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                    startActivity(intent);
                    return true;
    default:
        return super.onOptionsItemSelected(item);
    }
}

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

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

    ActionBar bar = getSupportActionBar();
    bar.setDisplayHomeAsUpEnabled(true);



    final ArrayList<HashMap<String, String>> songsList = new ArrayList<HashMap<String, String>>();

    XMLParser parser = new XMLParser();
    String xml = parser.getXmlFromUrl(URL); // getting XML from URL
    Document doc = parser.getDomElement(xml); // getting DOM element

    NodeList nl = doc.getElementsByTagName(KEY_ITEM);
    // looping through all song nodes <song>
    for (int i = 0; i < nl.getLength(); i++) {
        // creating new HashMap
        HashMap<String, String> map = new HashMap<String, String>();
        Element e = (Element) nl.item(i);
        // adding each child node to HashMap key => value
        map.put(KEY_ITEM, parser.getValue(e, KEY_ITEM));
        map.put(KEY_TITLE, parser.getValue(e, KEY_TITLE));
        map.put(KEY_PUB_DATE, parser.getValue(e, KEY_PUB_DATE));
        map.put(KEY_LINK, parser.getValue(e, KEY_LINK));

        // adding HashList to ArrayList
        songsList.add(map);
    }


    list=(ListView)findViewById(R.id.list);

    // Getting adapter by passing xml data ArrayList
    adapter=new LazyAdapter(this, songsList);        
    list.setAdapter(adapter);


    // Click event for single list row
    list.setOnItemClickListener(new OnItemClickListener() {

        @Override
        public void onItemClick(AdapterView<?> parent, View view,
                int position, long id) {

            Uri uriUrl = Uri.parse(songsList.get(position).get(KEY_LINK));  
            Intent launchBrowser = new Intent(Intent.ACTION_VIEW, uriUrl);  
            startActivity(launchBrowser);  



             }

    });
}   
}

Log Cat

08-29 03:28:48.603: E/AndroidRuntime(658): FATAL EXCEPTION: main
08-29 03:28:48.603: E/AndroidRuntime(658): java.lang.RuntimeException: Unable to start        activity ComponentInfo{com.threesixteenapps.treymorgan/com.threesixteenapps.treymorgan.CustomizedListView}: android.os.NetworkOnMainThreadException
08-29 03:28:48.603: E/AndroidRuntime(658):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1956)
08-29 03:28:48.603: E/AndroidRuntime(658):  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1981)
08-29 03:28:48.603: E/AndroidRuntime(658):  at android.app.ActivityThread.access$600(ActivityThread.java:123)
08-29 03:28:48.603: E/AndroidRuntime(658):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1147)
08-29 03:28:48.603: E/AndroidRuntime(658):  at android.os.Handler.dispatchMessage(Handler.java:99)
08-29 03:28:48.603: E/AndroidRuntime(658):  at android.os.Looper.loop(Looper.java:137)
08-29 03:28:48.603: E/AndroidRuntime(658):  at android.app.ActivityThread.main(ActivityThread.java:4424)
08-29 03:28:48.603: E/AndroidRuntime(658):  at java.lang.reflect.Method.invokeNative(Native Method)
08-29 03:28:48.603: E/AndroidRuntime(658):  at java.lang.reflect.Method.invoke(Method.java:511)
08-29 03:28:48.603: E/AndroidRuntime(658):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
08-29 03:28:48.603: E/AndroidRuntime(658):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
08-29 03:28:48.603: E/AndroidRuntime(658):  at dalvik.system.NativeStart.main(Native Method)
08-29 03:28:48.603: E/AndroidRuntime(658): Caused by: android.os.NetworkOnMainThreadException
08-29 03:28:48.603: E/AndroidRuntime(658):  at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1099)
08-29 03:28:48.603: E/AndroidRuntime(658):  at java.net.InetAddress.lookupHostByName(InetAddress.java:391)
08-29 03:28:48.603: E/AndroidRuntime(658):  at java.net.InetAddress.getAllByNameImpl(InetAddress.java:242)
08-29 03:28:48.603: E/AndroidRuntime(658):  at java.net.InetAddress.getAllByName(InetAddress.java:220)
08-29 03:28:48.603: E/AndroidRuntime(658):  at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:137)
08-29 03:28:48.603: E/AndroidRuntime(658):  at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164)
08-29 03:28:48.603: E/AndroidRuntime(658):  at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119)
08-29 03:28:48.603: E/AndroidRuntime(658):  at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:360)
08-29 03:28:48.603: E/AndroidRuntime(658):  at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555)
08-29 03:28:48.603: E/AndroidRuntime(658):  at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487)
08-29 03:28:48.603: E/AndroidRuntime(658):  at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:465)
08-29 03:28:48.603: E/AndroidRuntime(658):  at com.threesixteenapps.treymorgan.XMLParser.getXmlFromUrl(XMLParser.java:45)
08-29 03:28:48.603: E/AndroidRuntime(658):  at com.threesixteenapps.treymorgan.CustomizedListView.onCreate(CustomizedListView.java:64)
08-29 03:28:48.603: E/AndroidRuntime(658):  at android.app.Activity.performCreate(Activity.java:4465)
08-29 03:28:48.603: E/AndroidRuntime(658):  at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1049)
08-29 03:28:48.603: E/AndroidRuntime(658):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1920)
08-29 03:28:48.603: E/AndroidRuntime(658):  ... 11 more

If any more info is needed i will gladly provide it for you. Thank you for your help

Bryan
  • 275
  • 1
  • 8
  • 24
  • possible duplicate of [NetworkOnMainThreadException](http://stackoverflow.com/questions/5150637/networkonmainthreadexception) – Sam Nov 11 '12 at 21:50

2 Answers2

3

Android 3.0 and higher won't allow you to do any networking tasks in the ui-thread (see this post).
The solution is to implement an AsyncTask or possibly a Loader.

Edit: I made a quick example of how you can implement an AsyncTask in your Activity. I removed some parts or replaced them with comments to keep it reasonably short. Just merge it with your code and it should work fine (replace MyActivity with your own etc).

public class MyActivity extends Activity{

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        //super onCreate, setup your content, actionbar etc.

        AsyncTask getxml = new MyAsyncTask();
        getxml.execute(URL);
    }

    private class MyAsyncTask extends AsyncTask<String, Integer, Void>{
        private static final int RESULT_GOT_XML = 1;
        private static final int RESULT_FAILED = 0;
        private ArrayList<HashMap<String, String>> asyncList;
        public MyAsyncTask(){
            asyncList = new ArrayList<HashMap<String, String>>();
        }

        @Override
        protected Integer doInBackground(String... url) {

            try{
                XMLParser parser = new XMLParser();
                String xml = parser.getXmlFromUrl(url[0]);
                Document doc = parser.getDomElement(xml);

                NodeList nl = doc.getElementsByTagName(KEY_ITEM);
                for (int i = 0; i < nl.getLength(); i++) {
                    //...perform the parsing and add to list:
                    asyncList.add(map);
                }
            }catch(IOException e){
                Log.e("MyAsync", "could not complete xml retrieval/parsing", e);
                return RESULT_FAILED;
            }
            return RESULT_GOT_XML;
        }

        @Override
        protected void onPostExecute(Integer result) {
            switch (result) {
            case RESULT_FAILED:
                Toast.makeText(MyActivity.this, "Could not get data", Toast.LENGTH_SHORT).show();
                break;
            case RESULT_GOT_XML:
                songsList.addAll(asyncList);
                list=(ListView)findViewById(R.id.list);
                adapter=new LazyAdapter(this, songsList);        
                list.setAdapter(adapter);

                list.setOnItemClickListener(yourclicklistener);
            default:
                Log.wtf("MyAsync","got unexpected result: "+result);
                break;
            }
        }
    }
}
Jave
  • 31,598
  • 14
  • 77
  • 90
  • do you know of a good feed parser tutorial that might demonstrate this, i'm not very familiar with using AsyncTask yet and was hoping this would be an easy fix instead of having to rewrite a lot of code – Bryan Nov 11 '12 at 21:53
  • The AsyncTask is quite simple to use actually, you just override the `doInBackground`-method and put all the networking and parsing there, and then update your list in the `onPostExecute` method. That's all that's needed. – Jave Nov 11 '12 at 21:55
  • at the risk of sounding like a complete novice you lost me there, I'm sorry. I can see now that Async is gonna be the proper way to go with this just not sure what i need to change now to make it work properly but i will continue to research what you said here – Bryan Nov 11 '12 at 21:58
  • thank you for the code, having a little bit of trouble implementing it as this is my first time dealing with Async Task, would you have time to possibly move this to a chat and maybe help me out a bit with this? – Bryan Nov 12 '12 at 22:00
1
Caused by: android.os.NetworkOnMainThreadException

You are performing a network operation on the main thread, this is not allowed in the more recent APIs. Use the DownloadManager or move your XMLParser to a new Thread, perhaps an AsyncTask.

Community
  • 1
  • 1
Sam
  • 86,580
  • 20
  • 181
  • 179