vabanagas
vabanagas

Reputation: 811

Error when accessing URL in RSS feed

I am unable to run my very simple RSS reader. When attempting to run the app force closes and my logcat gives me an error at this line:

InputSource myInputSource = new InputSource(rssUrl.openStream());

Here is my MainActivity.java:

package com.banagas.polypost;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

public class MainActivity extends Activity {

String streamTitle = "";

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    TextView result = (TextView)findViewById(R.id.result);

    try {
        URL rssUrl = new URL("http://www.thepolypost.com/search/?q=&t=article&l=10&d=&d1=&d2=&s=start_time&sd=desc&c[]=news,news/*&f=rss");
        SAXParserFactory mySAXParserFactory = SAXParserFactory.newInstance();
        SAXParser mySAXParser = mySAXParserFactory.newSAXParser();
        XMLReader myXMLReader = mySAXParser.getXMLReader();
        RSSHandler myRSSHandler = new RSSHandler();
        myXMLReader.setContentHandler(myRSSHandler);
        InputSource myInputSource = new InputSource(rssUrl.openStream());
        myXMLReader.parse(myInputSource);

        result.setText(streamTitle);

    } catch (MalformedURLException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
        result.setText("Cannot connect RSS!");
    } catch (ParserConfigurationException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
        result.setText("Cannot connect RSS!");
    } catch (SAXException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
        result.setText("Cannot connect RSS!");
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
        result.setText("Cannot connect RSS!");
    }


}

private class RSSHandler extends DefaultHandler
{
    final int stateUnknown = 0;
    final int stateTitle = 1;
    int state = stateUnknown;

    int numberOfTitle = 0;
    String strTitle = "";
    String strElement = "";

    @Override
    public void startDocument() throws SAXException {
        // TODO Auto-generated method stub
        strTitle = "--- Start Document ---\n";
    }

    @Override
    public void endDocument() throws SAXException {
        // TODO Auto-generated method stub
        strTitle += "--- End Document ---";
        streamTitle = "Number Of Title: " + String.valueOf(numberOfTitle) + "\n"
            + strTitle;
    }

    @Override
    public void startElement(String uri, String localName, String qName,
                             Attributes attributes) throws SAXException {
        // TODO Auto-generated method stub
        if (localName.equalsIgnoreCase("title"))
        {
            state = stateTitle;
            strElement = "Title: ";
            numberOfTitle++;
        }
        else
        {
            state = stateUnknown;
        }
    }

    @Override
    public void endElement(String uri, String localName, String qName)
    throws SAXException {
        // TODO Auto-generated method stub
        if (localName.equalsIgnoreCase("title"))
        {
            strTitle += strElement + "\n";
        }
        state = stateUnknown;
    }

    @Override
    public void characters(char[] ch, int start, int length)
    throws SAXException {
        // TODO Auto-generated method stub
        String strCharacters = new String(ch, start, length);
        if (state == stateTitle)
        {
            strElement += strCharacters;
        }
    }

}
}

Here is my manifest file:

<?xml version="1.0" encoding="utf-8"?>
<manifest         xmlns:android="http://schemas.android.com/apk/res/android"
package="com.banagas.polypost"
android:versionCode="1"
android:versionName="1.0" >

<application
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name" >
    <activity
        android:label="@string/app_name"
        android:name=".MainActivity" >
        <intent-filter >
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>
<uses-permission android:name="android.permission.INTERNET" />

<uses-sdk 
    android:minSdkVersion="4" 
    android:targetSdkVersion="11" />

</manifest>

Edit: Here's my log:

02-19 23:18:22.103 I/ActivityManager(  539): START {act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.banagas.polypost/.MainActivity bnds=[540,922][540,922] u=0} from pid 1411
02-19 23:18:22.153 I/ActivityManager(  539): Start proc com.banagas.polypost for activity com.banagas.polypost/.MainActivity: pid=10710 uid=10225 gids={3003, 1028}
02-19 23:18:22.313 E/EmbeddedLogger(  539): App crashed! Process: com.banagas.polypost
02-19 23:18:22.313 E/EmbeddedLogger(  539): App crashed! Package: com.banagas.polypost v1 (1.0)
02-19 23:18:22.313 E/AndroidRuntime(10710): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.banagas.polypost/com.banagas.polypost.MainActivity}: android.os.NetworkOnMainThreadException
02-19 23:18:22.313 E/AndroidRuntime(10710):     at com.banagas.polypost.MainActivity.onCreate(MainActivity.java:40)
02-19 23:18:22.313 W/ActivityManager(  539):   Force finishing activity com.banagas.polypost/.MainActivity
02-19 23:18:22.864 W/ActivityManager(  539): Activity pause timeout for ActivityRecord{42908170 com.banagas.polypost/.MainActivity}
02-19 23:18:23.475 I/ActivityManager(  539): Process com.banagas.polypost (pid 10710) has died.

Upvotes: 0

Views: 582

Answers (2)

Gorcyn
Gorcyn

Reputation: 2817

Since Android 3, http requests are just forbidden in the main thread to prevent freezing devices. Because of without timeout requests and servers that do not answer, some requests turns to infinite loops and when the user touch his device screen, the system ask him to kill the app because it is not responding... To prevent this bad way to do things, the system throw this NetworkOnMainThreadException to alert developers.

My suggestion is to use an AsyncTask. The AsyncTask will execute the code you put in its doInBackground function in a Thread and will automatically call its onPostExecute function on the thread end giving this function what the doInBackground returned. The onPostExecute is synchronized with the MainThread and will be able to update it.

class RSSFeedAsyncTask extends AsyncTask<URL, Void, String>
{
    public interface RSSFeedAsyncTaskListener
    {
        public void setText(String text);
    }

    private RSSFeedAsyncTaskListener listener;

    public RSSFeedAsyncTask(RSSFeedAsyncTaskListener listener)
    {
        this.listener = listener;
    }

    protected Long doInBackground(URL... urls)
    {
        String streamTitle = "";
        URL url = urls[0];
        try
        {
            // Download and parse the feed
            ...
            streamTitle = XX;
        }
        // Will catch MalformedURLException,
        // ParserConfigurationException,
        // SAXException and
        // IOException
        catch(Exception exception)
        {
            streamTitle = "Cannot connect RSS!";
        }
    }

    protected void onPostExecute(String result)
    {
        this.listener.setText(result);
    }
}

Then to use it in your activity, you will just have to use your asynctask like this :

RSSFeedAsyncTask rssFeedAsyncTask = new RSSFeedAsyncTask(this);
rssFeedAsyncTask.execute(new URL("http://..."));

and implement the RSSFeedAsyncTaskListener interface function setText to update the UI after the AsynTask did his job.

Upvotes: 0

sandrstar
sandrstar

Reputation: 12643

You get android.os.NetworkOnMainThreadException :

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. Applications targeting earlier SDK versions are allowed to do networking on their main event loop threads, but it's heavily discouraged. See the document Designing for Responsiveness.

from the documentation

So, You need to move block under try { which works with the network to thread different from main one. Read painless threading for easy ways to do it.

Upvotes: 1

Related Questions