Android RSS Reader – Multicategory reader, Tab Layout example

Today we have another Android RSS Reader application’s code for you – this time our code deals with multicategories. Application displays RSS feed data from 3 channels in separate tabs. You can easily extend it to display data from any number of RSS channels you wish. When you tap on a list element it displays the article contents by opening a browser. Our application looks like this.

ITCuties - Android RSS Reader - Multicategory

ITCuties – Android RSS Reader – Multicategory

In this tutorial we have combined knowledge from our previous tutorials:

Project structure looks like this.

ITCuties - Android RSS Reader - Multicategory - Eclipse project structure

ITCuties – Android RSS Reader – Multicategory – Eclipse project structure

Here is our code.

AndroidManifest.xml

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

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="16" />
    
    <uses-permission android:name="android.permission.INTERNET"/>

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        
        <activity
            android:name="com.itcuties.multicategoryrssreader.RssTabsActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        
        <activity android:name="com.itcuties.multicategoryrssreader.RssChannelActivity" />
        
    </application>

</manifest>

Here we configure all the application’s activities and Internet access permission.

Activity layout- activity_rss_tabs.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".RssTabsActivity" >

    <TabHost
        android:id="@android:id/tabhost"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true" >

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical" >

            <TabWidget
                android:id="@android:id/tabs"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" >
            </TabWidget>

            <FrameLayout
                android:id="@android:id/tabcontent"
                android:layout_width="match_parent"
                android:layout_height="match_parent" >

                <LinearLayout
                    android:id="@+id/tab_art"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent" >
                </LinearLayout>

                <LinearLayout
                    android:id="@+id/tab_tech"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent" >
                </LinearLayout>

                <LinearLayout
                    android:id="@+id/tab_sports"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent" >
                </LinearLayout>
                
            </FrameLayout>
        </LinearLayout>
    </TabHost>

</RelativeLayout>
ITCuties - Android RSS Reader - Multicategory - activity_rss_tabs layout

ITCuties – Android RSS Reader – Multicategory – activity_rss_tabs layout

This is our application’s tabs layout. The most important element here is the TabHost component which encapsulates 3 tabs.

Tab selectors – rss_tab_art.xml, rss_tab_sports.xml, rss_tab_tech.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"/>

Each tab has its selector. In our case this selectors are “empty” because our tabs don’t have icons.

Activity layout – activity_rss_channel.xml

<?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="@+id/rssChannelListView"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" >
    </ListView>

</LinearLayout>
ITCuties - Android RSS Reader - Multicategory - activity_rss_channel layout

ITCuties – Android RSS Reader – Multicategory – activity_rss_channel layout

Here is each tab’s content layout which is a list. ListView element is used here.

Activity – RssTabsActivity

package com.itcuties.multicategoryrssreader;

import android.app.TabActivity;
import android.content.Intent;
import android.os.Bundle;
import android.widget.TabHost;
import android.widget.TabHost.TabSpec;

/**
 * Main activity. It displays tabs.
 * 
 * @author itcuties
 *
 */
@SuppressWarnings("deprecation") 
// @SuppressWarnings annotation is here since we are using TabActivity which is deprecated in Android 4+
// Alternative way of constructing Tab Layout is to use ActionBar API
public class RssTabsActivity extends TabActivity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		
		// First, set the content view
		setContentView(R.layout.activity_rss_tabs);

		// Then get the TabHost
		TabHost tabHost = getTabHost();
		
		// Art tab
		Intent artIntent = new Intent().setClass(this, RssChannelActivity.class);
		// Set Art category RSS URL
		artIntent.putExtra("rss-url", "http://feeds.reuters.com/news/artsculture?format=xml");
		
		// The name of the art tab taken from the String resources
		String artTabName = getResources().getString(R.string.tab_art);
		TabSpec artTabSpec = tabHost.newTabSpec(artTabName)
									.setIndicator(artTabName, getResources().getDrawable(R.drawable.rss_tab_art))
									.setContent(artIntent);
		// Add art tab to the TabHost
		tabHost.addTab(artTabSpec);
	
		
		// Tech tab
		Intent techIntent = new Intent().setClass(this, RssChannelActivity.class);
		// Set Tech category RSS URL
		techIntent.putExtra("rss-url", "http://feeds.reuters.com/reuters/technologyNews?format=xml");
		
		// Tech tab name taken from the string resources
		String techTabName = getResources().getString(R.string.tab_tech);
		TabSpec techTabSpec = tabHost.newTabSpec(techTabName)
									 .setIndicator(techTabName, getResources().getDrawable(R.drawable.rss_tab_tech))
									 .setContent(techIntent);
		// Add tech tab to the TabHost
		tabHost.addTab(techTabSpec);
		
		
		// Sports tab
		Intent sportsIntent = new Intent().setClass(this, RssChannelActivity.class);
		// Set Sports category RSS URL
		sportsIntent.putExtra("rss-url", "http://feeds.reuters.com/reuters/sportsNews?format=xml");
		
		// Sports tab name - string resources
		String sportsTabName = getResources().getString(R.string.tab_sports);
		TabSpec sportsTabSpec = tabHost.newTabSpec(sportsTabName)
									   .setIndicator(sportsTabName, getResources().getDrawable(R.drawable.rss_tab_sports))
				  					   .setContent(sportsIntent);
		// Add sports tab to the TabHost
		tabHost.addTab(sportsTabSpec);
		
		
		// Set current tab to Technology
		tabHost.setCurrentTab(1);
	}

}

This code is responsible for filling in each tab’s content. This activity extends TabActivity. At the beginning of the code we set the content view to acitvity_rss_tabs layout. Then TabHost reference is obtained by calling the TabActivity.getTabHost(). Next we construct each tab’s contents. An Intent is created and String object containing RSS channel URL is being send to activity using Intent.putExtra method. Then a TabSpec object is created, where we set the content with the reference to the Intent object that was created for each tab. At the end TabSpec object is added to the tabHost variable.

The same operations take place for other tabs. At the end of the code current selected tab is set by calling TabHost.setCurrentTab method – tabs numbers start from 0.

Activity – RssChannelActivity

package com.itcuties.multicategoryrssreader;

import java.util.List;

import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.widget.ArrayAdapter;
import android.widget.ListView;

import com.itcuties.multicategoryrssreader.data.RssItem;
import com.itcuties.multicategoryrssreader.listeners.ListListener;
import com.itcuties.multicategoryrssreader.util.RssReader;

/**
 * Each category tab activity.
 * @author itcuties
 *
 */
public class RssChannelActivity extends Activity {
	
	// A reference to this activity
    private RssChannelActivity local;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		
		setContentView(R.layout.activity_rss_channel);
		
		// Get the RSS URL that was set in the RssTabActivity
		String rssUrl = (String)getIntent().getExtras().get("rss-url");
		
		// Set reference to this activity
        local = this;
         
        GetRSSDataTask task = new GetRSSDataTask();
         
        // Start process RSS task
        task.execute(rssUrl);
		
	}
	
	/**
	 * This class downloads and parses RSS Channel feed.
	 * 
	 * @author itcuties
	 *
	 */
	private class GetRSSDataTask extends AsyncTask<String, Void, List<RssItem> > {
        @Override
        protected List<RssItem> doInBackground(String... urls) {
            try {
                // Create RSS reader
                RssReader rssReader = new RssReader(urls[0]);
             
                // Parse RSS, get items
                return rssReader.getItems();
             
            } catch (Exception e) {
                Log.e("RssChannelActivity", e.getMessage());
            }
             
            return null;
        }
         
        @Override
        protected void onPostExecute(List<RssItem> result) {
             
            // Get a ListView from the RSS Channel view
            ListView itcItems = (ListView) findViewById(R.id.rssChannelListView);
                         
            // Create a list adapter
            ArrayAdapter<RssItem> adapter = new ArrayAdapter<RssItem>(local,android.R.layout.simple_list_item_1, result);
            // Set list adapter for the ListView
            itcItems.setAdapter(adapter);
                         
            // Set list view item click listener
            itcItems.setOnItemClickListener(new ListListener(result, local));
        }
    }
	
}

This code is explained in details in our previous tutorial – Android AsyncTask RSS Reader. Major modification here is that at the beginning of the method the RSS URL is read using getExtras method. Then RSS data is being read and parsed as in our previous tutorials.

RssReader, RssParseHandler, RssItem and ListListener classes were described in details in our previous tutorial – How to write Android RSS parser.

Download this sample code here.

Install this application from here.

This code is available on our GitHub repository as well.

38 Responses to "Android RSS Reader – Multicategory reader, Tab Layout example"

  1. Kevin says:

    Hi, i want to stroage the feed in apps and can read anytime, ( Offline , Online ).
    If my phone is online. the application will update them self or can update my self.
    I think you understand what i mean. sorry for my bad english.

    Thank

    Kevin

    Reply
  2. Remi Latinwo says:

    This is a very beautiful project.
    I have a problem though. I tried changing the feed link in the program to my feed
    http://www.punchng.com/feed
    but i keep getting this error: at line 14, column 2: mismatched tag
    The code works for all rss feed i have tried, except mine. Please help me.
    What am i doing wrong?

    Reply
    • itcuties says:

      Hello Remi,
      Something is not right with your RSS Feed. We have modified the RssParseHandler to debug your feed – some Log.d() calls were added.

      package com.itcuties.multicategoryrssreader.util;
      
      import java.util.ArrayList;
      import java.util.List;
      
      import org.xml.sax.Attributes;
      import org.xml.sax.SAXException;
      import org.xml.sax.helpers.DefaultHandler;
      
      import android.util.Log;
      
      import com.itcuties.multicategoryrssreader.data.RssItem;
      
      /**
       * SAX tag handler
       * 
       * @author ITCuties
       *
       */
      public class RssParseHandler extends DefaultHandler {
      
      	private List<RssItem> rssItems;
      	
      	// Used to reference item while parsing
      	private RssItem currentItem;
      	
      	// Parsing title indicator
      	private boolean parsingTitle;
      	// A buffer used to build current title being parsed
      	private StringBuffer currentTitleSb;
      	
      	// Parsing link indicator
      	private boolean parsingLink;
      	
      	public RssParseHandler() {
      		rssItems = new ArrayList<RssItem>();
      	}
      	
      	public List<RssItem> getItems() {
      		return rssItems;
      	}
      	
      	@Override
      	public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
      		
      		// DEBUG
      		Log.d("DEBUG", "start: " + qName);
      		
      		if ("item".equals(qName)) {
      			currentItem = new RssItem();
      		} else if ("title".equals(qName)) {
      			parsingTitle = true;
      			
      			currentTitleSb = new StringBuffer();
      		} else if ("link".equals(qName)) {
      			parsingLink = true;
      		}
      	}
      	
      	@Override
      	public void endElement(String uri, String localName, String qName) throws SAXException {
      		
      		// DEBUG
      		Log.d("DEBUG", "end: " + qName);
      		
      		if ("item".equals(qName)) {
      			rssItems.add(currentItem);
      			currentItem = null;
      		} else if ("title".equals(qName)) {
      			
      			parsingTitle = false;
      			
      			// Set item's title when we parse item->title tag not the channel title tag
      			if (currentItem != null) {
      				// Set item's title here
      				currentItem.setTitle(currentTitleSb.toString());
      			}
      			
      		} else if ("link".equals(qName)) {
      			parsingLink = false;
      		}
      	}
      	
      	@Override
      	public void characters(char[] ch, int start, int length) throws SAXException {
      		
      		// DEBUG
      		Log.d("DEBUG", "\t chars: " + new String(ch, start, length));
      		
      		if (parsingTitle) {
      			if (currentItem != null) {
      				// Here we append the title to the buffer due to network issues.
      				// Sometimes this characters method is called multiple times for a tag contents.
      				currentTitleSb.append(new String(ch, start, length));
      			}
      		} else if (parsingLink) {
      			if (currentItem != null) {
      				currentItem.setLink(new String(ch, start, length));
      				parsingLink = false;
      			}
      		}
      	}
      	
      }
      

      We get the following output while parsing your feed.

      05-08 22:09:56.751: D/DEBUG(1109): start: html
      05-08 22:09:56.751: D/DEBUG(1109): 	 chars: 
      05-08 22:09:56.761: D/DEBUG(1109): start: head
      05-08 22:09:56.761: D/DEBUG(1109): 	 chars: 
      05-08 22:09:56.761: D/DEBUG(1109): 	 chars: 
      05-08 22:09:56.761: D/DEBUG(1109): start: title
      05-08 22:09:56.761: D/DEBUG(1109): end: title
      05-08 22:09:56.771: D/DEBUG(1109): 	 chars: 
      05-08 22:09:56.771: D/DEBUG(1109): start: meta
      05-08 22:09:56.771: D/DEBUG(1109): end: meta
      05-08 22:09:56.771: D/DEBUG(1109): 	 chars: 
      05-08 22:09:56.771: D/DEBUG(1109): start: meta
      05-08 22:09:56.771: D/DEBUG(1109): end: meta
      05-08 22:09:56.771: D/DEBUG(1109): 	 chars: 
      05-08 22:09:56.771: D/DEBUG(1109): 	 chars:  
      05-08 22:09:56.771: D/DEBUG(1109): start: meta
      05-08 22:09:56.771: D/DEBUG(1109): end: meta
      05-08 22:09:56.771: D/DEBUG(1109): 	 chars: 
      05-08 22:09:56.782: D/DEBUG(1109): start: meta
      05-08 22:09:56.782: D/DEBUG(1109): end: meta
      05-08 22:09:56.782: D/DEBUG(1109): 	 chars: 
      05-08 22:09:56.782: D/DEBUG(1109): start: meta
      05-08 22:09:56.782: D/DEBUG(1109): end: meta
      05-08 22:09:56.782: D/DEBUG(1109): 	 chars: 
      05-08 22:09:56.782: D/DEBUG(1109): start: meta
      05-08 22:09:56.791: D/DEBUG(1109): end: meta
      05-08 22:09:56.791: D/DEBUG(1109): 	 chars: 
      05-08 22:09:56.791: D/DEBUG(1109): start: meta
      05-08 22:09:56.791: D/DEBUG(1109): 	 chars: 
      05-08 22:09:56.791: D/DEBUG(1109): start: link
      05-08 22:09:56.791: D/DEBUG(1109): end: link
      05-08 22:09:56.791: D/DEBUG(1109): 	 chars: 
      05-08 22:09:56.801: E/RssChannelActivity(1109): At line 14, column 2: mismatched tag
      

      There are no RSS tags in your feed when you connect to it with Android device!
      Please consult this case with your administrator that manages your HTTP server. Maybe the case is some error page is displayed by the Apache server when connection comes from the Android device. Let us know what you have found.

      Take care,
      itcuties

      Reply
      • Remi Latinwo says:

        Thank you very much for your effort. I really appreciate this.
        Meanwhile i’ll consult the Administrator and let you know the outcome.
        I am so grateful.

        Reply
  3. Hemant Ks says:

    Hi ITCuties,

    This post is really helpful to me, as I’m new to android programming.
    I have gone through your other android post also and found very useful.

    Really appreciate your creative work. Keep going on.

    Kind regards,
    Hemant

    Reply
  4. Ali Imran says:

    I want to use this code to read the rss feed from you tube, but am unsuccessful, probably the format is different please help

    Reply
  5. Biciila Octavian says:

    hy i am from romania and i am a beggenier. i want that your tutorial to use fragment tabs that extends fragment and implements OnTabChangeListener. becaouse tab activity is deprecated in api lvl 13. can you help me how to do it?

    Reply
    • itcuties says:

      Hello,

      You are not the first one to ask about this topic. We have “Android Fragments” tutorial on our TODO list :)

      Regards,
      itcuties

      Reply
  6. Karl says:

    Hello

    This is very nice tutorial for rss but can this app showing the thumbnail image not just the title

    Reply
  7. Nora says:

    Hello,I am using the same code as in how to write android RSS parser tutorial but when I running the program it is give me this error :Couldn’t open http://www.itcuties.com/feed/ but on my browser this linke will be open I do not know what is the problem,
    known as I do not have a firewall and I am using Internet permision also I am running the application on my phone(SAMSAUNG) please help me Thank you ^_^

    Reply
  8. Coderz says:

    Can you please post CustomAdapter tutorial on the same code

    Reply
  9. RmlllK says:

    Hi. Thx for usefull gide.
    Can you show how to make rss widget like this project.

    Reply
    • itcuties says:

      What project are you talking about?

      Reply
      • RmlllK says:

        Your project posted on this page. I need to create news widget supporting rss and your project is much closer but your project is an app. I need to make same but in widget form.
        sorry for my english.

        Reply
  10. Fev says:

    Would it be easy to tie notifications into an app like this for something like a breaking news article that needs to be pushed out from something like a WordPress RSS? I read GCM is something to look into for push notifications. Any direction would be helpful on this =).

    Reply
  11. AlexAung says:

    I am modifying this tutorial to fulfill my school project. I have 2 questions -:

    1. I would need to show thumbnail image. May I know where do I can get the image and where to show?

    2. How can I add multiple rss feed into tab.

    e.g. I have following rss feeds of two local newspaper. so that i just want to show both in politics tab.
    www. first-11.com/politics?format=feed
    www. 7daynewsjournal.com/taxonomy/term/30/all/feed

    Thanks,
    Alex

    Reply
  12. AMO says:

    Hi cuties,

    I am adding view pager and view pager adapter to sweep tab by tab. But can’t sweep.

    Could you please point me out how to add view pager to existing code.

    Thanks,
    AMO

    Reply
  13. Serkan Kaan Uygur says:

    Hi. Thanks too much. Could you help, how can we loading time and can we write loading while the RSS load.???

    Reply
  14. navid says:

    hi.how can i get description and images of my rss feed?
    For example in the left side of my news i have an image, and near that i want to show a description. of my news.
    Thank u so much. please help me.

    Reply
  15. Omer Rosenbaum says:

    Is there a way to open the item in the same webview instead of opening a browser when clicking on RSS item?

    Reply
  16. Ghanshyam says:

    How to use utf-8 encode or font from assets typeface multi languange using sax parse list news

    Reply
  17. Ghanshyam says:

    Thank you Advance,

    how to Utf-8 work or font from assets to support multiple language. how I use typeface in listview.

    Reply
  18. Ragshas says:

    Hi ITCUTIES,

    Thank you guys for the tutorial, it works fine but the problem is when there is no internet connection the app crashes, can you please suggest me how to solve this issue.

    Reply
  19. Calvin O'Brien says:

    Hi,

    How will i display the rss feed in a web view?

    Reply
  20. Kamarur Rama says:

    Hi
    This program really helped me finish my college project.
    I want to ask, how to alter when clicked him appear within the web view?

    where is the code if I want to change to display web view?

    thank you so much want to help me
    sorry my english is bad

    Reply

Leave a Reply

Want to join the discussion?
Feel free to contribute!

Leave a Reply

Your email address will not be published. Required fields are marked *


*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>