Pdf Reader For Android

					      Build a mobile RSS reader
      Handle XML with Android

      Skill Level: Intermediate


      Frank Ableson (fableson@msiservices.com)
      Software designer



      18 Mar 2008


      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.


      Section 1. Before you start
      This tutorial introduces XML handling on the Android platform. To build the sample
      application in this tutorial, the Android SDK must be installed and functional on the
      development computer. Building Android applications in Eclipse is recommended,
      but not a requirement for this tutorial. Mobile development experience is helpful, but
      Java™ programming skills are required for the Android applications and will be
      helpful for this tutorial.


      About this tutorial
                            Frequently used acronyms
                                   •   DOM: Document Object Model

                                   •   GUI: Graphical user interface




Build a mobile RSS reader                                                                  Trademarks
© Copyright IBM Corporation 2008. All rights reserved.                                    Page 1 of 33
developerWorks®                                                                ibm.com/developerWorks




                                   •   HTTP: Hyper Text Transport Protocol

                                   •   RSS: Really Simple Syndication

                                   •   SAX: Simple API for XML

                                   •   SDK: Software Development Kit

                                   •   XML: Extensible Markup Language


      Why do you care about an RSS reader for Android? And where does XML fit into the
      picture? First, Android is a platform that is rapidly gaining mindshare in the mobile
      marketplace. Even before consumer devices equipped with Android are available,
      thousands of developers are jumping into this mobile market, hoping to be prepared
      for the much anticipated introduction of Android-equipped devices in the near future.
      Rich devices, such as Android, demand content. Sometimes that content is in the
      form of games or a productivity application. Beyond mobile e-mail, however, the
      content that drives data usage the most is news and information. This content might
      look like news stories relevant to a particular financial market or something as
      ubiquitous as the weather forecast. And who isn't interested in the weather forecast
      for the upcoming weekend trip to the beach? Getting data to a mobile device in a
      fashion that is organic and usable becomes the challenge.

      Android includes the WebKit.org browser engine, which means that it delivers a top
      quality browser experience to the mobile user. However, chasing down multiple Web
      sites for news and information can be tedious in a small screen with limited input
      devices. Don't misunderstand, the market has come a very long way since the WAP
      browser and limited text-based information, however the power of mobile information
      is when it is available at-a-glance: Enter RSS feeds. RSS is an acronym for "Really
      Simple Syndication." In essence, RSS is a convenient way to distribute information
      of interest. RSS makes XML data available; the data contains brief abstracts or
      teasers of the full information source. If interested, the user can dig deeper and get
      "the rest of the story" as the radio host Paul Harvey might say. This tutorial
      demonstrates the major aspects of XML data handling in the construction of an
      Android RSS reader.

      This tutorial is organized into the following sections:

                • RSS basics
                • Android RSS reader application architecture
                • Fetching and parsing XML data with SAX
                • Rendering RSS data in Android


      Prerequisites

Build a mobile RSS reader                                                                  Trademarks
© Copyright IBM Corporation 2008. All rights reserved.                                    Page 2 of 33
ibm.com/developerWorks                                                                   developerWorks®



      This tutorial requires several technologies that work together. You will need to obtain
      all of them to perform the steps of this tutorial.

                • Download Eclipse from http://www.eclipse.org/downloads.
                • To install the Android Developer Tools (the Eclipse Plugin), follow the
                  instructions at
                  http://code.google.com/android/intro/installing.htm#installingplugin
                • Find the Android SDK at http://code.google.com/android. The Android
                  SDK is a moving target. When I wrote this tutorial, the current version of
                  the SDK was m5-rc14.
                • Choose an RSS feed. This tutorial uses a feed of the most popular
                  tutorials from the developerWorks Web site.
                • Have an active Internet Connection to run the sample application.
      Full source code is available from Downloads. Source code snippets in this tutorial
      include:

                • AndroidManifest.xml snippet: This file is the application deployment
                  descriptor for Android applications.
                • RSSReader: This class implements the main GUI and includes code for
                  menu handling.
                • RSSFeed: This class contains a parsed RSS Feed, including information
                  about the RSS channel and a List of the included RSSItems.
                • RSSHandler: This class implements the SAX parser handler to enable
                  the parsing of an XML stream (an RSS feed from the Internet) and
                  populates an instance of the RSSFeed.
                • RSSItem: This class represents a single RSS item parsed out of an XML
                  stream.
                • ShowDescription: This is an Activity that displays the abstract of a
                  selected RSSItem and includes linkable text to enable seamless
                  launching of the Android browser to access the link available in the
                  RSSItem. Launching this Activity demonstrates the use of an Intent with
                  an extra Bundle in a pseudo-synchronous call.
                • R.java: This file represents the GUI identifiers used in the application.
      Terminology

      Building an Android RSS/XML application requires knowledge of XML, RSS and
      HTTP, as well as aspects of the Android platform. An understanding of the terms
      below is helpful for you to get the most out of this tutorial. For additional links for

Build a mobile RSS reader                                                                        Trademarks
© Copyright IBM Corporation 2008. All rights reserved.                                          Page 3 of 33
developerWorks®                                                                      ibm.com/developerWorks



      more information on each of these topics, see Resources.

                • Android: The flagship product of the Open Handset Alliance. This is an
                  open source operating environment targeted for mobile devices such as
                  cell phones.
                • RSS: Really Simple Syndication is a data format used to publish
                  information in an efficient manner.
                • XML: eXtensible Mark-up Language is a self describing data format.
                • HTTP: Hyper Text Transport Protocol almost exclusively transfers all RSS
                  feeds.
                • Parser: This tool is designed to extract information from one format and
                  make it accessible to other structures. For example, an XML parser
                  extracts data from an XML data source.
                • Emulator: This software tool is representative of another system. Android
                  is not available today on real hardware platforms to consumers; the
                  sample application is exercised on the Android Emulator.




      Section 2. Covering some RSS basics
      Before I jump into the details of downloading an RSS feed and process it with an
      Android-based RSS reader, let's take a quick look at the need for RSS, where RSS
      is used, and how it is structured.


      Why RSS?
      The multitude of information dissemination tools ranges from free radio, public and
      cable television, printed media, and even that moderately disruptive technology
      called the Internet with its abundance of Web sites and e-mail subscriptions. The
      problem with this vast array of choices is that it is often difficult to find the information
      of real interest and value amongst the noise and volume of data. Thankfully, RSS
      can assist with this challenge.

      RSS stands for "Really Simple Syndication". RSS is an XML data format used by
      publishers of content to distribute information that is categorized and is suitable for
      both human and machine consumption. RSS feeds are typically processed and
      presented to users in a friendly human-readable format such as a news reader
      including the application built in this tutorial. RSS feeds are also consumed by


Build a mobile RSS reader                                                                        Trademarks
© Copyright IBM Corporation 2008. All rights reserved.                                          Page 4 of 33
ibm.com/developerWorks                                                             developerWorks®



      computers to generate subsequent, aggregated information sources. An example of
      a machine-consumed RSS feed might be a listing of available rental properties that
      is retrieved periodically and fed into a travel agent's local reservation system.

      RSS is typically mentioned when discussing news stories, however the format can
      be used to organize and publish many types of information beyond news. For
      example, many Web sites publish an RSS feed of available pod-casts to distribute
      audio and video content. Handango.com, a popular online merchant of mobile
      software and content, supplies RSS feeds of new and popular software titles,
      categorized by mobile platform. For example, there is a feed for Windows® Mobile,
      Blackberry, Palm and others. Before too long, there will hopefully be a feed for
      Android applications as well!

      The format of RSS is XML data, meaning the data itself contains descriptive
      elements such that it is self-contained. The XML layout over the past few years has
      undergone some changes as the industry has normalized a bit. The most recent and
      generally accepted version is 2.0. RSS 2.0 is a relatively simple XML layout that is
      readily parsed by computer programs. In this tutorial, the sample application
      demonstrates the parsing of an RSS feed taken from the Web site of IBM
      developerWorks.


      RSS version 2.0
      Enough discussion in the abstract about which version is most popular, let's examine
      the specification for RSS 2.0. The RSS 2.0 format includes only a few tags. You
      have the obligatory <?xml> tag, which every XML document requires. The first real
      tag is the <rss> tag, which includes the version as an attribute. Following the <rss>
      tag is one or more channels where each channel includes the elements shown in
      Listing 1.

      Listing 1. Channels and elements in RSS 2.0

       <channel>
       <title/>
       <link/>
       <description/>
       <pubDate />
       <language/>
       <copyright/>
       <image>
           <title />
           <url />
           <link />
       </image>
       + <item />
       </channel>
       </rss>


      Each channel may have one or more items. Each item has the structure shown in


Build a mobile RSS reader                                                                Trademarks
© Copyright IBM Corporation 2008. All rights reserved.                                  Page 5 of 33
developerWorks®                                                                ibm.com/developerWorks



      Listing 2.

      Listing 2. Item structure

       <item>
       <title />
       <description />
       <link />
       <category />
       <pubDate />
       </item>



      Data usage
      The consumer of an RSS feed determines how to display the data. Typically an RSS
      reader displays some title information regarding the available channels, including the
      publication date (found in the pubDate element). Remember, RSS is about
      publishing relevant, timely data so the publication date should not be ignored. Figure
      1 demonstrates this tutorial's sample application in action displaying an RSS feed.
      Figure 1 displays the title of the RSS feed, the publication date and displays the
      items in a List format. Later in this tutorial, I discuss the mechanics of getting the
      parsed RSS feed into the Android user interface.

      Figure 1. Android RSS reader in action




Build a mobile RSS reader                                                                  Trademarks
© Copyright IBM Corporation 2008. All rights reserved.                                    Page 6 of 33
ibm.com/developerWorks                                   developerWorks®




Build a mobile RSS reader                                     Trademarks
© Copyright IBM Corporation 2008. All rights reserved.       Page 7 of 33
developerWorks®                                                                   ibm.com/developerWorks



      The elements of the item tag of an RSS feed describe each contained item of the
      feed. For example, in this tutorial, you are working with an RSS feed that contains a
      list of popular tutorials from the developerWorks site at IBM. Each entry in the feed
      includes enough information to give the consumer a feel for what the topic is about
      and how to learn more. There are three levels of information, each of increasing
      verbosity and detail. In addition, each entry contains a publication date and category
      information. The title of the item gives a brief feel for what the topic is, for example:
      <title><![CDATA[Develop Android applications with
      Eclipse]]></title>.

      This tells you enough about this item to peak your interest if you care to learn about
      using Eclipse for Android development. If the consumer (that is, the person using the
      application) wants to learn more, there is more information to provide, namely the
      description from Listing 3.

      Listing 3. The description

             <description><![CDATA[Android is Google's oft-discussed mobile,
       wireless, computer, and communications platform. You can take advantage of
       the powerful Eclipse environment to build Android applications using the Android
       Eclipse plug-in. This tutorial introduces Android application development with the
       Eclipse plug-in, otherwise known as Android Development Tools. The tutorial provides
       an introduction to Android development with a quick introduction to the platform, a
       tour of Android Development Tools, and includes the construction of two example
       applications. ]]></description>


      Note the use of the CDATA XML technique. CDATA is used when the XML feed
      might contain mark-up elements which can interfere with the containing XML tags.
      One of the side effects of CDATA is that the data is taken as is, so you might need
      additional formatting to occur on the text for it to display properly in the target user
      interface. You'll see an example of this in the sample application, introduced later in
      this tutorial.

      Finally, if consumers are very interested in this topic, a link is provided where they
      can find even more information on the specific topic:


       <link>
       <![CDATA[http://www.ibm.com/developerworks/edu/os-dw-os-eclipse-android.html?ca=drs-]]>
       </link>


      This tutorial does not dive into any special handling of the category as all of the
      categories in this particular RSS feed are the same. The publication date is
      displayed as a best practice technique.

      Now that you know a little bit about RSS and where it is used, let's take a high-level
      look at the RSS reader application architecture.




Build a mobile RSS reader                                                                       Trademarks
© Copyright IBM Corporation 2008. All rights reserved.                                         Page 8 of 33
ibm.com/developerWorks                                                                developerWorks®




      Section 3. Android RSS reader application architecture
      Building a richly featured RSS reader is a bit of an ambitious project for a brief
      tutorial, so let's look at what an RSS reader needs to accomplish. Then you'll build
      out the important elements which are relevant to XML handling and rendering on the
      Android platform. When you're done, you'll have a functioning RSS reader with some
      hooks and plans for further extension in the future.


      The major requirements of an RSS reader application
      The following sections detail how the Android RSS reader addresses the major
      requirements of an RSS reader application.

      Specify the RSS feed of interest

      RSS feeds are available from more Internet sites than you can count. The
      application needs to specify which RSS feed to work with. A fully featured RSS
      reader includes one or more means of selecting the desired RSS feed. This can
      include the ability to choose from a number of sites and channels, or allow the user
      to enter the feed of interest manually in an EditView. To minimize the non-XML
      related code in this tutorial, the RSS feed URL is simply hard coded into the source.
      A menu is implemented as a hook to add RSS feed selections, as desired.

      Obtain the RSS feed of interest

      Before you can do any fancy parsing and data manipulation of an RSS feed, you
      must retrieve it from the Internet. This means that you connect to the site hosting the
      RSS feed through an Internet connection (cellular or WiFi) and perform an HTTP
      GET operation to retrieve the RSS data. The data which comes back is not a file, it
      is a stream of XML data. The URL class is employed to fetch the data.

      Parse the XML data stream

      You can parse XML data with multiple mechanisms. All of them involve the
      navigation of the data stream and delineation of one data element from another with
      the opportunity to store the data. Different kinds of XML Parsers are available in the
      Android SDK, in addition to the option to create your own. The Android SDK includes
      provisions for the two most popular approaches, namely the DOM Parser, as well as
      the SAX Parser. The DOM approach is well suited for complex XML documents as it
      builds a node-oriented representation of the XML data in memory. The SAX
      approach uses callbacks whenever new tags are encountered, allowing the


Build a mobile RSS reader                                                                  Trademarks
© Copyright IBM Corporation 2008. All rights reserved.                                    Page 9 of 33
developerWorks®                                                                    ibm.com/developerWorks



      application to store only the data it is interested in. Due to the simplistic nature of the
      RSS XML structure, the SAX Parser is employed in this tutorial. The tutorial has a
      class named RSSHandler which implements the SAX Parser callback functions.

      Store the RSS data

      The RSS feed extracted from the XML data stream must be put into a useful form.
      The tutorial has two helper classes: RSSFeed and RSSItem, which store the parsed
      form of the RSS XML data stream in memory. Once the XML data stream is fully
      parsed, the application interacts with these classes to render the information.

      Rendering the RSS feed

      The tutorial's sample application employs two Activity classes to provide the user
      interface. The primary screen lists the RSS feed title and publication date followed
      by a list of the RSS items. Once an item is selected through a tap, or enter in the
      Android Emulator, the ShowDescription Activity displays the full detail including
      the Title, Publication Date, Description and Link elements of the RSS item. The user
      interface is set up so any links such as e-mail or Web contained in the text are
      active—if you select them, the appropriate action takes place. For example, if you
      select the link text, the Android browser launches with the link as the target. In this
      way, the RSS reader allows all three levels of information to be accessed very
      intuitively. This is the power of RSS in general, and more specifically the efficacy of
      RSS on a mobile platform.

      Data refreshing and off-line viewing

      Refreshing data on a periodic basis is an important aspect to an RSS reader, as is
      the ability to access the information when off-line, such as when you fly on an
      airplane and your Android device is in flight mode. Some provision has been made
      for this in the sample application in the form of a menu hook for refreshing the data,
      but data persistence and scheduling are beyond the scope of this tutorial.

      Next you'll build an application to obtain and display an RSS feed in an Android
      application.




      Section 4. Building the application
      The remainder of the tutorial helps you build the Android RSS reader. The
      explanations are broken into two main sections. The first section discusses the
      handling of XML data streams, while the following section focuses on the rendering
      of the RSS data in the Android user interface.


Build a mobile RSS reader                                                                     Trademarks
© Copyright IBM Corporation 2008. All rights reserved.                                       Page 10 of 33
ibm.com/developerWorks                                                               developerWorks®




      Fetching and parsing XML data with SAX
      The core activity in building an RSS reader application is the retrieval and handling
      of XML data. Fetching XML data is done through an Internet connection and can be
      accomplished through an HTTP GET operation. A few different classes in Java
      enable this kind of HTTP transaction. This tutorial demonstrates fetching data with
      an instance of the URL class. As discussed briefly in the earlier section on
      application architecture, the SAX parser is employed in this tutorial. SAX parsers
      require minimal amounts of memory and excel when the data formats are relatively
      simple in nature or when your data requirements allow selective use of the data
      structure.

      Before you dive into the specifics of using the SAX parser, take a quick look at the
      RSSFeed and RSSItem classes as they will be referred to extensively throughout
      the remainder of this tutorial.


      RSSFeed
      The RSSFeed class represents the RSS feed from a high level perspective. The
      RSSFeed class includes the elements of interest from the channel portion of the
      RSS data source as well as a list of RSSItems. The RSSItem represents the
      individual item in an RSS channel. Look at both of these important classes.
      RSSFeed.java is found in Listing 4.

      Listing 4. RSSFeed.java

       package com.msi.androidrss;

       import java.util.List;
       import java.util.Vector;
       import com.msi.androidrss.RSSItem;
       public class RSSFeed
       {
           private String _title = null;
           private String _pubdate = null;
           private int _itemcount = 0;
           private List<RSSItem> _itemlist;

             RSSFeed()
             {
                 _itemlist = new Vector(0);
             }
             int addItem(RSSItem item)
             {
                 _itemlist.add(item);
                 _itemcount++;
                 return _itemcount;
             }
             RSSItem getItem(int location)


Build a mobile RSS reader                                                                Trademarks
© Copyright IBM Corporation 2008. All rights reserved.                                  Page 11 of 33
developerWorks®                                                                  ibm.com/developerWorks




             {
                 return _itemlist.get(location);
             }
             List getAllItems()
             {
                 return _itemlist;
             }
             int getItemCount()
             {
                 return _itemcount;
             }
             void setTitle(String title)
             {
                 _title = title;
             }
             void setPubDate(String pubdate)
             {
                 _pubdate = pubdate;
             }
             String getTitle()
             {
                 return _title;
             }
             String getPubDate()
             {
                 return _pubdate;
             }
       }


      When the SAX parsing engine is complete with parsing the XML data in your RSS
      source, an instance of the RSSFeed class has been created and now contains
      everything required to work with the RSS data in your application. The RSSFeed
      class contains three important elements, and Set-ers and Get-ers for data
      manipulation. The data elements of interest are:

                 • Title (_title): A Java.lang.String to hold the title of the channel for
                   display.
                 • Publication Date (_pubdate): A java.lang.String to hold the
                   publication date for display. Note that in a more sophisticated RSS
                   reader, you can use this publication date information to perform an
                   intelligent update or refresh operation.
                 • List of Items (_itemlist): A parameterized java.util.List for holding a
                   collection of RSSItems.


      RSSItem
      Let's look at the list of items contained in RSSFeed. Each element in that list is of
      type RSSItem. The RSSItem class defines a member of type java.lang.String to hold
      the value found by the parser. Having each element in a convenient retrieval class
      makes the application logic and user interface rendering a much more
      straight-forward task as you will soon see. RSSItem.java is shown in Listing 5.



Build a mobile RSS reader                                                                     Trademarks
© Copyright IBM Corporation 2008. All rights reserved.                                       Page 12 of 33
ibm.com/developerWorks                                         developerWorks®



      Listing 5. RSSItem.java

       package com.msi.androidrss;
       public class RSSItem
       {
           private String _title = null;
           private String _description = null;
           private String _link = null;
           private String _category = null;
           private String _pubdate = null;

             RSSItem()
             {
             }
             void setTitle(String title)
             {
                 _title = title;
             }
             void setDescription(String description)
             {
                 _description = description;
             }
             void setLink(String link)
             {
                 _link = link;
             }
             void setCategory(String category)
             {
                 _category = category;
             }
             void setPubDate(String pubdate)
             {
                 _pubdate = pubdate;
             }
             String getTitle()
             {
                 return _title;
             }
             String getDescription()
             {
                 return _description;
             }
             String getLink()
             {
                 return _link;
             }
             String getCategory()
             {
                 return _category;
             }
             String getPubDate()
             {
                 return _pubdate;
             }
             public String toString()
             {
                 // limit how much text you display
                 if (_title.length() > 42)
                 {
                     return _title.substring(0, 42) + "...";
                 }
                 return _title;
             }
       }




Build a mobile RSS reader                                          Trademarks
© Copyright IBM Corporation 2008. All rights reserved.            Page 13 of 33
developerWorks®                                                                    ibm.com/developerWorks



      An instance of the RSSItem class contains the textual data elements related to an
      individual item found in the RSS feed. In addition to the java.lang.String fields to hold
      the data, the class includes a Get-er and Set-er for each field. Lastly, this class
      overrides the toString() method as this is the method invoked when the Android
      user interface elements display the list of items. Keep this comment regarding the
      toString() method in mind as it is required in the discussion of rendering the RSS
      data in the Android user interface.


      The SAX approach
      As introduced briefly earlier, the SAX approach to XML parsing relies on a callback
      structure where the parser scans the data stream to look for tags and invokes
      methods in a handler (which you supply) to process the data. The handler extends a
      Java class known as the DefaultHandler. There are five methods of interest in
      the handler. Each one performs a separate, distinct and important role in the XML
      parsing process. These methods are:

                • startDocument: Invoked when the document parsing commences. This
                  is an opportunity to initialize required data structures.
                • endDocument: Invoked when document parsing concludes.
                • startElement: Called when a new tag is encountered by the scanner.
                  Handlers typically use this method to determine location in the document
                  to properly be prepared to store the data when ready. Additionally, any
                  attributes associated with this elements are available for processing,
                  storing and interpreting.
                • endElement: Called when a closing tag is encountered by the scanner.
                  Handlers typically use this method to determine location in the document
                  and also to store intermediate data. In the case of the RSS sample
                  application, each RSSItem is stored into the RSSFeed object when it
                  encounters the </item> tag.
                • characters: Called when data from a tag is available. This is the
                  opportunity to store textual data. For example, when parsing RSS data,
                  the contents of the title, description, link, category, and publication date
                  elements are all stored in this method.


      RSSHandler
      The RSSHandler class is key to the operation of the tutorial application. It is
      responsible for identifying and storing the relevant information in the XML data
      stream. Each of its methods is invoked in turn when called upon by the SAX parser.



Build a mobile RSS reader                                                                     Trademarks
© Copyright IBM Corporation 2008. All rights reserved.                                       Page 14 of 33
ibm.com/developerWorks                                                                 developerWorks®



      The RSSHandler implements some very basic state handling to properly identify
      and store data as the SAX parser makes its way through the XML data stream.
      There are many right ways to manage state in the SAX approach. Though not
      necessarily relevant to the topic of RSS feed parsing in this tutorial, if you find that
      managing state while parsing a particular XML data source becomes too complex
      with SAX, you might consider switching to the DOM parser instead. A DOM parser
      works on the assumption that every element of the document is important and that
      your application will desire to explore and extract various elements in the XML data
      source. SAX works well for an RSS feed because the relationships are so simple.
      The implementation of RSSHandler.java is shown as Listing 6. Have a quick look at
      the methods to become familiar with the structure of the handler.

      Listing 6. RSSHandler.java

       package com.msi.androidrss;
       import org.xml.sax.helpers.DefaultHandler;
       import org.xml.sax.*;
       import android.util.Log;

       public class RSSHandler extends DefaultHandler
       {
             RSSFeed _feed;
             RSSItem _item;
             String _lastElementName = "";
             boolean bFoundChannel = false;
             final int RSS_TITLE = 1;
             final int RSS_LINK = 2;
             final int RSS_DESCRIPTION = 3;
             final int RSS_CATEGORY = 4;
             final int RSS_PUBDATE = 5;
             int depth = 0;
             int currentstate = 0;
             /*
               * Constructor
               */
             RSSHandler()
             {
             }
             /*
               * getFeed - this returns our feed when all of the parsing is complete
               */
             RSSFeed getFeed()
             {
                  return _feed;
             }

             public void startDocument() throws SAXException
             {
                 // initialize our RSSFeed object - this will hold our parsed contents
                 _feed = new RSSFeed();
                 // initialize the RSSItem object - you will use this as a crutch to grab
                         // the info from the channel
                 // because the channel and items have very similar entries..
                 _item = new RSSItem();




Build a mobile RSS reader                                                                   Trademarks
© Copyright IBM Corporation 2008. All rights reserved.                                     Page 15 of 33
developerWorks®                                                               ibm.com/developerWorks




             }
             public void endDocument() throws SAXException
             {
             }
             public void startElement(String namespaceURI, String localName,String qName,
                                                       Attributes atts) throws SAXException
             {
                 depth++;
                 if (localName.equals("channel"))
                 {
                     currentstate = 0;
                     return;
                 }
                 if (localName.equals("image"))
                 {
                     // record our feed data - you temporarily stored it in the item :)
                     _feed.setTitle(_item.getTitle());
                     _feed.setPubDate(_item.getPubDate());
                 }
                 if (localName.equals("item"))
                 {
                     // create a new item
                     _item = new RSSItem();
                     return;
                 }
                 if (localName.equals("title"))
                 {
                     currentstate = RSS_TITLE;
                     return;
                 }
                 if (localName.equals("description"))
                 {
                     currentstate = RSS_DESCRIPTION;
                     return;
                 }
                 if (localName.equals("link"))
                 {
                     currentstate = RSS_LINK;
                     return;
                 }
                 if (localName.equals("category"))
                 {
                     currentstate = RSS_CATEGORY;
                     return;
                 }
                 if (localName.equals("pubDate"))
                 {
                     currentstate = RSS_PUBDATE;
                     return;
                 }
                 // if you don't explicitly handle the element, make sure you don't wind
                        // up erroneously storing a newline or other bogus data into one of our
                        // existing elements
                 currentstate = 0;
             }
             public void endElement(String namespaceURI, String localName, String qName)
                                                                        throws SAXException
             {
                 depth--;
                 if (localName.equals("item"))
                 {
                     // add our item to the list!
                     _feed.addItem(_item);
                     return;
                 }
             }
             public void characters(char ch[], int start, int length)


Build a mobile RSS reader                                                                Trademarks
© Copyright IBM Corporation 2008. All rights reserved.                                  Page 16 of 33
ibm.com/developerWorks                                                             developerWorks®




             {
                  String theString = new String(ch,start,length);
                  Log.i("RSSReader","characters[" + theString + "]");
                  switch (currentstate)
                  {
                      case RSS_TITLE:
                          _item.setTitle(theString);
                          currentstate = 0;
                          break;
                      case RSS_LINK:
                          _item.setLink(theString);
                          currentstate = 0;
                          break;
                      case RSS_DESCRIPTION:
                          _item.setDescription(theString);
                          currentstate = 0;
                          break;
                      case RSS_CATEGORY:
                          _item.setCategory(theString);
                          currentstate = 0;
                          break;
                      case RSS_PUBDATE:
                          _item.setPubDate(theString);
                          currentstate = 0;
                          break;
                      default:
                          return;
                  }
             }
       }



      RSSHandler explained
      Next examine the RSSHandler class a little further. Note that the class has a single
      instance of the RSSFeed class. The purpose of the RSSHandler class is to
      implement callbacks from the SAX parser, and in the process of doing so, assemble
      a representation of the RSS data for the application to use.

      The startElement method assigns which data element was found while the
      characters method actually performs the assignment to one of the RSSItem
      members through the appropriate set method. The endElement checks for the end
      of the item element and when found adds the current RSSItem to the RSSFeed.

      The RSSHandler is designed to be self contained for SAX parsing. The methods all
      react to the parser's events, building up the RSSFeed and then the class makes the
      fully populated RSSFeed object available through the getFeed method.


      Setting up SAX
      Now that you have a feel for what happens when the SAX parser is operating, look
      at the invocation of the SAX parser. The relevant code is found in the RSSFeed
      class in the getFeed() method, in Listing 7.


Build a mobile RSS reader                                                              Trademarks
© Copyright IBM Corporation 2008. All rights reserved.                                Page 17 of 33
developerWorks®                                                                    ibm.com/developerWorks



      Listing 7. getFeed() method in RSSFeed.java

             private RSSFeed getFeed(String urlToRssFeed)
             {
                 try
                 {
                      // setup the url
                     URL url = new URL(urlToRssFeed);
                      // create the factory
                      SAXParserFactory factory = SAXParserFactory.newInstance();
                      // create a parser
                      SAXParser parser = factory.newSAXParser();
                      // create the reader (scanner)
                      XMLReader xmlreader = parser.getXMLReader();
                      // instantiate our handler
                      RSSHandler theRssHandler = new RSSHandler();
                      // assign our handler
                      xmlreader.setContentHandler(theRssHandler);
                      // get our data through the url class
                      InputSource is = new InputSource(url.openStream());
                      // perform the synchronous parse
                      xmlreader.parse(is);
                      // get the results - should be a fully populated RSSFeed instance,
                              // or null on error
                      return theRssHandler.getFeed();
                  }
                  catch (Exception ee)
                  {
                      // if you have a problem, simply return null
                      return null;
                  }
             }


      Following along with the code in Listing 7, you see that you instantiate both the
      classes required by the SAX parser and your RSSHandler class. Once you assign
      our RSSHandler to the XMLReader instance, you can commence with the parse.
      Remember, the hard work in SAX is defining your handler! But before you can parse
      data, you have to retrieve it.


      Fetching XML data
      The HTTP transaction to fetch the XML data stream takes place through the URL
      class, passing its Stream to a new instance of the InputSource class. The SAX
      parser/scanner uses the InputSource to navigate the XML data stream and
      execute the parsing operation by invoking the methods in the assigned handler. In
      this case, those methods are found in the RSSHandler class. Once the parse is
      complete, the RSSFeed is retrieved from the RSSHandler which built up an
      instance of the RSSFeed class during each callback operation along the way.

      A parsing operation is attempted within a try/catch block. If the operation is
      successful, an instance of RSSFeed is returned. If an error occurs, the exception is
      caught and the function returns null.



Build a mobile RSS reader                                                                     Trademarks
© Copyright IBM Corporation 2008. All rights reserved.                                       Page 18 of 33
ibm.com/developerWorks                                                              developerWorks®



      With a complete an instance of the RSSFeed class available it is time to render the
      data to the user.




      Section 5. 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


Build a mobile RSS reader                                                                 Trademarks
© Copyright IBM Corporation 2008. All rights reserved.                                   Page 19 of 33
developerWorks®                                                                  ibm.com/developerWorks




                • 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.



Build a mobile RSS reader                                                                   Trademarks
© Copyright IBM Corporation 2008. All rights reserved.                                     Page 20 of 33
ibm.com/developerWorks                                                                   developerWorks®



      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


Build a mobile RSS reader                                                                    Trademarks
© Copyright IBM Corporation 2008. All rights reserved.                                      Page 21 of 33
developerWorks®                                                                     ibm.com/developerWorks



      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


Build a mobile RSS reader                                                                      Trademarks
© Copyright IBM Corporation 2008. All rights reserved.                                        Page 22 of 33
ibm.com/developerWorks                                                              developerWorks®




                • 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




Build a mobile RSS reader                                                               Trademarks
© Copyright IBM Corporation 2008. All rights reserved.                                 Page 23 of 33
developerWorks®                                          ibm.com/developerWorks




Build a mobile RSS reader                                           Trademarks
© Copyright IBM Corporation 2008. All rights reserved.             Page 24 of 33
ibm.com/developerWorks                                                                 developerWorks®



      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


Build a mobile RSS reader                                                                  Trademarks
© Copyright IBM Corporation 2008. All rights reserved.                                    Page 25 of 33
developerWorks®                                                                 ibm.com/developerWorks



      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




      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


Build a mobile RSS reader                                                                  Trademarks
© Copyright IBM Corporation 2008. All rights reserved.                                    Page 26 of 33
ibm.com/developerWorks                                                                 developerWorks®



      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




Build a mobile RSS reader                                                                      Trademarks
© Copyright IBM Corporation 2008. All rights reserved.                                        Page 27 of 33
developerWorks®                                          ibm.com/developerWorks




Build a mobile RSS reader                                           Trademarks
© Copyright IBM Corporation 2008. All rights reserved.             Page 28 of 33
ibm.com/developerWorks                                                                developerWorks®



      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!




      Section 6. Summary

Build a mobile RSS reader                                                                  Trademarks
© Copyright IBM Corporation 2008. All rights reserved.                                    Page 29 of 33
developerWorks®                                                             ibm.com/developerWorks




      Wrapping up
      This tutorial demonstrated how to build an RSS reader application for Android. A
      discussion of the structure of RSS data feeds established that the SAX parsing
      approach was ideal for the simple XML structure of RSS version 2.0. The five
      methods used by the callback handler for processing XML data with SAX permitted
      the efficient parsing of RSS data. Once the RSS data was parsed and organized, the
      data was rendered through a custom View. For who are interested, the tutorial even
      includes some hooks to extend this sample application to be an RSS reader richer in
      features.




Build a mobile RSS reader                                                              Trademarks
© Copyright IBM Corporation 2008. All rights reserved.                                Page 30 of 33
ibm.com/developerWorks                                                         developerWorks®




      Downloads
       Description                                 Name               Size   Download
                                                                             method
      Tutorial source code                         x-androidrss.zip   60KB   HTTP

       Information about download methods




Build a mobile RSS reader                                                            Trademarks
© Copyright IBM Corporation 2008. All rights reserved.                              Page 31 of 33
developerWorks®                                                                ibm.com/developerWorks




      Resources
      Learn
         • Develop Android applications with Eclipse (Frank Ableson, developerWorks,
           February 2008): Take this tutorial to get started with Android application
           development within the Eclipse environment.
         • Android Development Community at anddev.org: Visit an excellent source for
           Android tutorials.
         • RSS 2.0 Specification: Read more on this Web content syndication format that
           is a dialect of XML.
         • RSS 2.0 versus ATOM: Review a summary of the differences between the RSS
           2.0 and Atom 1.0 syndication languages.
         • Introduction to Syndication, (RSS) Really Simple Syndication (Vincent Lauria,
           developerWorks, March 2006): Learn about RSS, Atom, and feed readers.
         • IBM XML certification: Find out how you can become an IBM-Certified
           Developer in XML and related technologies.
         • XML technical library: See the developerWorks XML Zone for a wide range of
           technical articles and tips, tutorials, standards, and IBM Redbooks.
         • developerWorks XML zone: Learn all about XML.
         • developerWorks technical events and webcasts: Stay current with technology in
           these sessions.
         • The technology bookstore: Browse for books on these and other technical
           topics.
         • Podcasts: Tune in and catch up with IBM technical experts.
         • Open source developer events: Check out upcoming conferences, trade shows,
           webcasts, and other events around the world that are of interest to IBM open
           source developers.
      Get products and technologies
         • IBM trial software: Build your next development project with trial software
           available for download directly from developerWorks.
         • Android project Web site: Try the first complete, open, and free mobile platform.
         • Android Developer Tools (the Eclipse Plugin): Install a custom plugin called
           Android Development Tools (ADT) if the Eclipse IDE is your development
           environment for Android apps.
      Discuss


Build a mobile RSS reader                                                                  Trademarks
© Copyright IBM Corporation 2008. All rights reserved.                                    Page 32 of 33
ibm.com/developerWorks                                                              developerWorks®



         • Participate in the discussion forum for this content.
         • XML zone discussion forums: Participate in any of several XML-related
           discussions.
         • developerWorks XML zone: Share your thoughts: After you read this article,
           post your comments and thoughts in this forum. The XML zone editors
           moderate the forum and welcome your input.
         • developerWorks blogs: Check out these blogs and get involved in the
           developerWorks community.



      About the author
      Frank Ableson
                  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.




      Trademarks
      Adobe, the Adobe logo, PostScript, and the PostScript logo are either registered
      trademarks or trademarks of Adobe Systems Incorporated in the United States,
      and/or other countries.
      IBM, DB2, Lotus, Rational, WebSphere, and pureXML are trademarks of IBM
      Corporation in the United States, other countries, or both.
      Java and all Java-based trademarks are trademarks of Sun Microsystems, Inc. in the
      United States, other countries, or both.
      Microsoft, Windows, and the Windows logo are trademarks of Microsoft Corporation
      in the United States, other countries, or both.
      Linux is a trademark of Linus Torvalds in the United States, other countries, or both.
      UNIX is a registered trademark of The Open Group in the United States and other
      countries.
      Other company, product, or service names may be trademarks or service marks of
      others.




Build a mobile RSS reader                                                                Trademarks
© Copyright IBM Corporation 2008. All rights reserved.                                  Page 33 of 33

				
DOCUMENT INFO
Shared By:
Categories:
Tags: Reader, Android
Stats:
views:31
posted:4/16/2012
language:English
pages:33