Friday, April 30, 2010

A simple RSS reader, in ListView

In the last exercise, "A simple RSS reader, using Android's org.xml.sax package", the RSS's titles are displayed as a single String. For sure it's not a good presentation in this way.

In this article, it will be modified to display it in ListView.



AndroidManifest.xml to grant "android.permission.INTERNET" to the application. (Refer to last article "A simple RSS reader, using Android's org.xml.sax package")

In order to use ListView, create a new file, /res/layout/rsslist.xml
<?xml version="1.0" encoding="utf-8"?>
<TextView
 xmlns:android="http://schemas.android.com/apk/res/android"
 android:id="@+id/rowtext"
 android:layout_width="fill_parent"
 android:layout_height="25px"
 android:textSize="10sp" />


Modify main.xml to have a ListView
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:orientation="vertical"
   android:layout_width="fill_parent"
   android:layout_height="fill_parent"
   >
<TextView 
   android:layout_width="fill_parent"
   android:layout_height="wrap_content"
   android:text="@string/hello" />
<ListView
 android:id="@android:id/list"
 android:layout_width="fill_parent"
 android:layout_height="wrap_content" />
<TextView
 android:id="@android:id/empty"
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 android:text="No Data" />
</LinearLayout>


Modify AndroidRssReder.java
package com.exercise.AndroidRssReader;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

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.ListActivity;
import android.os.Bundle;
import android.widget.ArrayAdapter;

public class AndroidRssReader extends ListActivity {
 
 private List<String> item = new ArrayList<String>();
 
   /** Called when the activity is first created. */
   @Override
   public void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.main);

       try {
   URL rssUrl = new URL("http://feeds.feedburner.com/Android-er?format=xml");
   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);
   
  } catch (MalformedURLException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } catch (ParserConfigurationException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } catch (SAXException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } catch (IOException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
      
  ArrayAdapter<String> itemList = new ArrayAdapter<String>(this, R.layout.rsslist, item);
  setListAdapter(itemList);
   }
  
   private class RSSHandler extends DefaultHandler
   {
    final int stateUnknown = 0;
    final int stateTitle = 1;
    int state = stateUnknown;
    
  @Override
  public void startDocument() throws SAXException {
   // TODO Auto-generated method stub
  }

  @Override
  public void endDocument() throws SAXException {
   // TODO Auto-generated method stub
  }

  @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;
   }
   else
   {
    state = stateUnknown;
   }
  }

  @Override
  public void endElement(String uri, String localName, String qName)
    throws SAXException {
   // TODO Auto-generated method stub
   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)
   {
    item.add(strCharacters);
    
   }
  }
    
   }
}


Download the files.


14 comments:

Illuminatus said...

Why are you creating myRSSHandler? I don't see it being used anywhere..

Nii Laryea said...

I only keep saying the "No Data" text when I run the app. What am I doing wrong?

Nii Laryea said...

Please I really need help here. I'm working on a school project and the RSS url I'm using doesn't load. The "No Data" text appears on the screen always. What am I doing wrong, please??

Android Er said...

"No Date" most probably you have no internet connection. Have to grant "android.permission.INTERNET"? How you test it? Real device? Emulator? Do your device connected to internet?

What is your target platform set? what is set on minSdkVersion? Please note that if you set minSdkVersion="10" or newer, it will have error of android.os.NetworkOnMainThreadException.

Download it in project form here.

Nii Laryea said...

Thanks a lot. It was my internet connection, I fixed that. This is a screen shot of what I got when I run it in the emulator http://www.flickr.com/photos/77922330@N06/7138242951/in/photostream. Can u please help me make a few changes: 1. I want the texts in each list view to be larger so the feed fills the whole screen and possibly below, which will be accessed by the user scrolling downwards.
2. I want to add the functionality where a user can click on a list view and the underlying url is opened in a webviewclient.
The rss url I'm using is http://www.knust.edu.gh/pages/rss.php?type=news. I'll greatly appreciate ur help. Thanks.

Nii Laryea said...

I worked on the text size and was able to take care of that but can't figure out how to get the url of each list item. Can u please help me with that asap?

Nii Laryea said...

Android Er, is there a way to add an onclick method so that a page is opened when a list view item is clicked?

Nii Laryea said...

Androider, please I really need your help. I did some research and know to use an onListItemClick method: Intent myIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(newsItem.get(position).getLink().toExternalForm()));
startActivity(myIntent);
My problem now is what to declare newsItem. Can't declare as a string as getLink() is not defined for string variables. Help me out here pls.

Android Er said...

hello Nii Laryea,

if you want to start in browser using Intent with ACTION_VIEW, the second parameter is the target Uri.

Please read A simple RSS reader IV, start browser to open the selected feed.

Nii Laryea said...

Lots of thanks Android Er. It's awesome!!

Rajkumar said...

i am getting error here.

ArrayAdapter itemList = new ArrayAdapter(this, R.layout.rsslist, item);
setListAdapter(itemList);
}
rsslist cannot be resolved or is not a field


Rajkumar Arumugam said...

its first displays hello world!

then i added "android.permission.INTERNET in android.manifest.xml

now nothing displayed. blank...

Rupali said...

I am not able to display my rss feed on list it gives me no data on screen plz help me.

Nii Laryea said...

Rupali, there could be lots of things you're doing wrong. You goota tell us what you're already doing, or post some code or something so you can be helped