Skip to main content

By clicking Submit, you agree to the developerWorks terms of use.

The first time you sign into developerWorks, a profile is created for you. Select information in your profile (name, country/region, and company) is displayed to the public and will accompany any content you post. You may update your IBM account at any time.

All information submitted is secure.

  • Close [x]

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerworks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

By clicking Submit, you agree to the developerWorks terms of use.

All information submitted is secure.

  • Close [x]

Build a mobile RSS reader

Handle XML with Android

Frank Ableson is an entrepreneur and software developer in northern New Jersey, specializing in mobile and embedded application software. He is currently authoring a book about Android application development for Manning Publications. His professional interests are embedded systems, wireless communications, and automotive electronics. His biggest fans are his wife, Nikki, and their children.

Summary:  What good is a mobile computing environment if you can't keep track of your favorite news feeds on the go? Sure, you can use Android's browser to read your favorite Web sites, but it's unlikely the sites are optimized for a screen two inches high. And besides, then you'll miss the opportunity to integrate RSS or other XML data with other mobile applications to make your own mash-ups. This tutorial shows you how to use the Android Developer Tools to read, parse, and display XML data.

Date:  18 Mar 2008
Level:  Intermediate PDF:  A4 and Letter (328 KB | 33 pages)Get Adobe® Reader®

Activity:  176341 views
Comments:  

Rendering RSS data in Android

The XML data from the RSS feed is now safely stored in memory in an instance of RSSFeed, which in turn contains a number of RSSItems in a convenient List structure. The purposes of an RSS reader are to manage the data and display it in an orderly fashion to the user. Here is where the specifics of Android user interface coding and resources come into play. In this section, you will learn about the Android user interface implementation and the way the RSS data is displayed.

Primary user interface

The RSSReader application's startup Activity is the class RSSReader. The entry point of an Activity is the onCreate method. This method is responsible for boot-strapping the user interface and in some cases, such as this one, the method also initiates subsequent operations beyond creating the user interface. Looking at the onCreate method found in RSSReader.java, and showing in Listing 8, you can see that the structure of the application is very simple.


Listing 8. The RSSReader's onCreate method
                    
    private RSSFeed feed = null;

    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        setContentView(R.layout.main);
        
        // go get our feed!
        feed = getFeed(RSSFEEDOFCHOICE);

        // display UI
        UpdateDisplay();
        
    }

The onCreate method performs three functions:

  • Sets up the user interface which is identified by R.layout.main and represents the layout contained in main.xml
  • Sets up an instance of the RSSFeed class by calling the getFeed() method
  • Updates the user interface to reflect the RSS feed contents through the UpdateDisplay() method.

User interface layout

The RSSReader Activity's user interface includes two TextViews and a ListView. The TextViews display the channel title and publication date, while the ListView displays the list of RSSItems in the RSSFeed.

Listing 9 contains the layout for the primary Activity's user interface.


Listing 9. main.xml contains the user interface definition for the RSSReader Activity
                    
<?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="Android RSSReader"
    android:id="@+id/feedtitle"
    />
<TextView  
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text=""
    android:id="@+id/feedpubdate"
    />
<ListView
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:id="@+id/itemlist"
    
    />    
</LinearLayout>

The layout in main.xml has very simple user interface views. Note the presence of the android:id attributes in each of the views. These are necessary because the application dynamically updates the content of each of these views.


Rendering

Look at the UpdateDisplay method in Listing 10 to see how the RSSFeed data connects to the user interface. Recall that an instance of the RSSFeed class now contains the RSS data. The UpdateDisplay method is tasked with taking the RSS data and rendering it through the Android user interface.


Listing 10. UpdateDisplay method connects the data to the user interface
                    
    private void UpdateDisplay()
    {
        TextView feedtitle = (TextView) findViewById(R.id.feedtitle);
        TextView feedpubdate = (TextView) findViewById(R.id.feedpubdate);
        ListView itemlist = (ListView) findViewById(R.id.itemlist);
  
        
        if (feed == null)
        {
            feedtitle.setText("No RSS Feed Available");
            return;
        }
        
        feedtitle.setText(feed.getTitle());
        feedpubdate.setText(feed.getPubDate());

        
ArrayAdapter<RSSItem> adapter = new
    ArrayAdapter<RSSItem>(this,android.R.layout.
    simple_list_item_1,feed.getAllItems());

        itemlist.setAdapter(adapter);
        
        itemlist.setSelection(0);

        itemlist.setOnItemClickListener(this);
        
        
    }
	

Following along in Listing 10, the UpdateDisplay method starts out by connecting the two TextView objects and a ListView object to the layout through the findViewById() method, passing in the respective identifiers.

If the RSSFeed is null, the method displays a message indicating that RSS feed is available.

The channel title and publication dates are displayed in the respective TextView objects.


List of RSSItems

To connect the list of RSSItems to the ListView, you create an instance of the ArrayAdapter class. This parameterized class is constructed to manage items of type RSSItem. The layout of the list is governed by the built-in resource known as simple_list_item_1, which is essentially a list where each entry supports a single line of text. You also pass in a list of all RSSItem entries in your RSSFeed through the getAllItems() method of the RSSFeed class. If you recall, the RSSItem class overrides the default toString() method to allow the ArrayAdapter to get meaningful representations for displaying in the ListView. Listing 11 shows how the method does some simple formatting to make sure the text fits into the ListView nicely.


Listing 11. Overriding the default toString() method of the RSSItem class
                    
    public String toString()
    {
        // limit how much text you display
        if (_title.length() > 42)
        {
            return _title.substring(0, 42) + "...";
        }
        return _title;
    }

This ArrayAdapter is assigned to the ListView and the first entry is selected by calling the setSelection method with an argument of zero.

Lastly, you want to setup a listener to respond to item selections with the setOnItemClickListener method. The RSSReader class implements the OnItemClickListener interface: public class RSSReader extends Activity implements OnItemClickListener.

The listener functionality is implemented in the onItemClick method as seen in Listing 12.


Listing 12. onItemClick implementation
                    
public void onItemClick(AdapterView parent, View v, int position, long id)
     {
         Log.i(tag,"item clicked! [" + feed.getItem(position).getTitle() + "]");

         Intent itemintent = new Intent(this,ShowDescription.class);
         
         Bundle b = new Bundle();
         b.putString("title", feed.getItem(position).getTitle());
         b.putString("description", feed.getItem(position).getDescription());
         b.putString("link", feed.getItem(position).getLink());
         b.putString("pubdate", feed.getItem(position).getPubDate());
         
         itemintent.putExtra("android.intent.extra.INTENT", b);
         
         startSubActivity(itemintent,0);
     }
	 

When an item in the ListView is selected, the application displays the Description element of the chosen RSSItem. Look at the code in onItemClick and note three things:

  • The creation of an Intent which is necessary to launch another Activity, the ShowDescription Activity which is defined in ShowDescription.java
  • The use of a Bundle to pass data to the invoked activity
  • Starting the ShowDescription activity as a sub activity, which aids in bringing about a synchronous effect to the application

ShowDescription

The ShowDescription Activity provides the next level of detail for the chosen RSSItem, as seen in Figure 2.


Figure 2. Next level of detail for the chosen RSSItem
Next level of detail for the chosen RSSItem

The ShowDescription class is listed in Listing 13. Note the process of un-Bundling the RSSItem data and formatting a string to be used in the user interface.


Listing 13. ShowDescription activity
                    
package com.msi.androidrss;

import android.app.Activity;
import android.os.Bundle;
import android.widget.Button;
import android.widget.TextView;
import android.content.Intent;
import android.view.*;

public class ShowDescription extends Activity 
{
    public void onCreate(Bundle icicle) 
    {
        super.onCreate(icicle);
        setContentView(R.layout.showdescription);
        
        String theStory = null;
        
        
        Intent startingIntent = getIntent();
        
        if (startingIntent != null)
        {
            Bundle b = startingIntent.getBundleExtra("android.intent.extra.INTENT");
            if (b == null)
            {
                theStory = "bad bundle?";
            }
            else
            {
                theStory = b.getString("title") + "\n\n" + b.getString("pubdate") 
				+ "\n\n" + b.getString("description").replace('\n',' ') 
				+ "\n\nMore information:\n" + b.getString("link");
            }
        }
        else
        {
            theStory = "Information Not Found.";
        
        }
        
        TextView db= (TextView) findViewById(R.id.storybox);
        db.setText(theStory);
        
        Button backbutton = (Button) findViewById(R.id.back);
        
        backbutton.setOnClickListener(new Button.OnClickListener() 
        {
            public void onClick(View v) 
            {
                finish();
            }
        });        
    }
}

Take some care to ensure the Activity does not try to process a null Bundle or display erroneous data. Make sure that the variable theStory always has something valid assigned.


The back button

The code has a simple Button OnClickListener to terminate this Activity. Because this Activity was launched with the startSubActivity() method, this call to finish() results in control returning to the calling Activity, which is RSSReader.

Note that the textual representation of this description includes a hyperlink. Android takes care this of automatically with the attribute android:autoLink="all" as seen in Listing 14.


Listing 14. ShowDescription.xml defines the user interface for the ShowDescription Activity
                    
<?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:autoLink="all"
    android:text="story goes here ...."
    android:id="@+id/storybox"
    />
<Button
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:text="Back"
    android:id="@+id/back"
    />    

</LinearLayout>

With the text linking, to launch a Web site through the link of RSSItem is a zero code operation, as seen in Figures 3 and 4.


Figure 3. Web site references in text are automatically hyper-linked
Web site references in text are automatically hyper-linked

Figure 4 shows the launched Web page from the RSSItem link element. This demonstrates the power and efficiency of RSS. You see a topic of interest in the List of items when you select it. You see a concise abstract and if that conveys a satisfactory amount of information, you're done. If your curiosity is further piqued, click on the link and you have even more detailed information.


Figure 4. A launched Web page from the RSSItem link element
A launched Web page from the RSSItem link element

That's it. You have a functioning RSS reader!


Expansion hooks

In the source code, the final item to look at is the RSSReader.java file where the menus are setup. Recall that this tutorial does not address the topic of selecting the RSS feed nor refreshing it other than on startup, However, you'll note some hooks provided to do this in a future tutorial. Listing 15 contains the two methods required to implement menu behavior.


Listing 15. Menu handling methods
                    
   public boolean onCreateOptionsMenu(Menu menu) 
    {
        super.onCreateOptionsMenu(menu);
        
        menu.add(0,0,"Choose RSS Feed");
        menu.add(0,1,"Refresh");
        Log.i(tag,"onCreateOptionsMenu");
        return true;
    }
    
    public boolean onOptionsItemSelected(Menu.Item item){
        switch (item.getId()) {
        case 0:
            
            Log.i(tag,"Set RSS Feed");
            return true;
        case 1:
            Log.i(tag,"Refreshing RSS Feed");
            return true;
        }
        return false;
    }

The onCreateOptionsMenu() is called once during the life cycle of the Activity and allows the creation of menu items. The second argument to the method call is a unique identifier for the menu.

The onOptionsItemSelected method is invoked when the user selects an item. Using the menu item's identifier through the getId() method, it is straight-forward to respond to a specific menu selection.

It is beyond the scope of this tutorial to expand on this functionality; these methods are included as a starting point for enhancements to the Android RSS reader!

5 of 9 | Previous | Next

Comments



static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=XML, Open source
ArticleID=295231
TutorialTitle=Build a mobile RSS reader
publish-date=03182008
author1-email=fableson@msiservices.com
author1-email-cc=dwxed@us.ibm.com