In this tutorial we will build a simple rss application.

Requirements are:

1) parse an rss feed and display the headlines in a ListView

2) when the user clicks on a headline, open the Android browser and redirect to corresponding web page.



Note: this tutorial is outdated. I would suggest you follow the new tutorial. The new tutorial is more extended, but it addresses few issues present in this example. On the other hand, if you are not looking for a very detailed tutorial and are interested only in XML parsing part, feel free to browse this example.



We will parse the PCWorld‘s rss looking for the latest news: http://feeds.pcworld.com/pcworld/latestnews

The final result will look like in the screenshot below:

1. Create a new project in Eclipse:

Project: SimpleRssReader

Activity: SimpleRssReaderActivity

2. Add required permissions to AndroidManifest file.

The application will make use of Internet, so this should be specified in the AndroidManifest file, otherwise an exception will be thrown. Just after the <application> tag, (as a child of <manifest> tag), add the following line:

<uses-permission android:name="android.permission.INTERNET"/>

3. Open the main.xml layout file, delete the already existing TextView control, and add instead a ListView with the id “list”. This should should look like this:

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <ListView android:id="@+android:id/list" android:layout_width="fill_parent" android:layout_height="wrap_content" > </ListView> </LinearLayout>

4. Lets create the skeleton of our main activity.

Open the SimpleRSSReaderActivity and make it extend ListActivity, instead of Activity as it comes by default. We need this in order to display the headlines in the ListView by binding to an array which will hold our data, using the list view adapter.

Add 2 instance variables: “headlines” and “links” of type List.

It should look like this:

public class SimpleRSSReaderActivity extends ListActivity { List headlines; List links; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); } }

5. In the onCreate() method, just after the setContentView(….) , add following lines:

// Initializing instance variables headlines = new ArrayList(); links = new ArrayList(); try { URL url = new URL("http://feeds.pcworld.com/pcworld/latestnews"); XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); factory.setNamespaceAware(false); XmlPullParser xpp = factory.newPullParser(); // We will get the XML from an input stream xpp.setInput(getInputStream(url), "UTF_8"); /* We will parse the XML content looking for the "<title>" tag which appears inside the "<item>" tag. * However, we should take in consideration that the rss feed name also is enclosed in a "<title>" tag. * As we know, every feed begins with these lines: "<channel><title>Feed_Name</title>...." * so we should skip the "<title>" tag which is a child of "<channel>" tag, * and take in consideration only "<title>" tag which is a child of "<item>" * * In order to achieve this, we will make use of a boolean variable. */ boolean insideItem = false; // Returns the type of current event: START_TAG, END_TAG, etc.. int eventType = xpp.getEventType(); while (eventType != XmlPullParser.END_DOCUMENT) { if (eventType == XmlPullParser.START_TAG) { if (xpp.getName().equalsIgnoreCase("item")) { insideItem = true; } else if (xpp.getName().equalsIgnoreCase("title")) { if (insideItem) headlines.add(xpp.nextText()); //extract the headline } else if (xpp.getName().equalsIgnoreCase("link")) { if (insideItem) links.add(xpp.nextText()); //extract the link of article } }else if(eventType==XmlPullParser.END_TAG && xpp.getName().equalsIgnoreCase("item")){ insideItem=false; } eventType = xpp.next(); //move to next element } } catch (MalformedURLException e) { e.printStackTrace(); } catch (XmlPullParserException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } // Binding data ArrayAdapter adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, headlines); setListAdapter(adapter);

6. In the onCreate() method we passed an input stream to setInput(): xpp.setInput(getInputStream(url), "UTF_8" );

getInputStream() is not a standard Java method, so we should create it. This method should take as an argument the feed url, and return the input stream.

public InputStream getInputStream(URL url) { try { return url.openConnection().getInputStream(); } catch (IOException e) { return null; } }

7. Finnaly, we want when a title is clicked, the Android browser to be opened and display the corresponding article. This one is simple, we override the onListItemClick() method, get the position of article in the ListView, retrieve the coresponding link, and pass the url of that article to ACTION_VIEW intent which takes care further of displaying the web page.

@Override protected void onListItemClick(ListView l, View v, int position, long id) { Uri uri = Uri.parse(links.get(position)); Intent intent = new Intent(Intent.ACTION_VIEW, uri); startActivity(intent); }

By this time you should compile and run successfully the application.

Well, if everything went fine and you are done with the simple rss application, the next step to consider is how can you enhance the visual aspect of the application. Adding some style to the ListView, for example alternating between background colors, or displaying an icon next to each headline, can considerably increase the visual aspect, which will make your application look more appealing.

Take a look at this tutorial: Building a Custom Fancy ListView in Android, where I show in details how to achieve this.

This application, however, has one major drawback. Its drawback is that all the parsing and network access is done on the UI thread. As a result, you may notice that when starting the application, it “freezes” for a few seconds and then displays the headlines. To fix this issue, you should put all the parsing functionality in a background thread. In regards how to do that, you definitely should consider this post: Understanding AsyncTask – Once and Forever