7

I have this url here: http://www.webpronews.com/feeds

Now i need to get the feeds and display it in android. Any clue?

Muhammad Maqsoodur Rehman
  • 33,681
  • 34
  • 84
  • 124

3 Answers3

5

I use the lib xmlpull_1_1_3_4c.jar and for example read twitter feeds (rss) like below.

XML Pull is open source. You just need to adjust the tags according to your feed. If you cannot find the jar online, I can email it to you. I don't remember where I got it from, it used to be at xmlpull.org, but not sure where it is now. I got it somewhere linked from http://www.ibm.com/developerworks/opensource/library/x-android/

import org.developerworks.android.FeedParser;
import org.developerworks.android.FeedParserFactory;
import org.developerworks.android.Message;
import org.developerworks.android.ParserType;
import org.xmlpull.v1.XmlSerializer;

....
loadFeed(ParserType.ANDROID_SAX);
....



private void loadFeed(ParserType type){
     try{
      Log.i("AndroidNews", "ParserType="+type.name());
      FeedParser parser = FeedParserFactory.getParser(type);
      long start = System.currentTimeMillis();
      messages = parser.parse();
      long duration = System.currentTimeMillis() - start;
      String xml = writeXml();      
      titles = new ArrayList<String>(messages.size());
      for (Message msg : messages){
       titles.add(msg.getTitle());
      }
     } catch (Throwable t){
      Log.e("AndroidNews",t.getMessage(),t);
     }
    }

private String writeXml() {


 XmlSerializer serializer = Xml.newSerializer();
  StringWriter writer = new StringWriter();
  try {
   serializer.setOutput(writer);
   serializer.startDocument("UTF-8", true);
   serializer.startTag("", "messages");
   serializer.attribute("", "number", String.valueOf(messages.size()));
   for (Message msg: messages){
    serializer.startTag("", "message");
    serializer.attribute("", "date", msg.getDate());
    serializer.startTag("", "title");
    serializer.text(msg.getTitle());
    serializer.endTag("", "title");
    serializer.startTag("", "url");
    serializer.text(msg.getLink().toExternalForm());
    serializer.endTag("", "url");
    serializer.startTag("", "body");
    serializer.text(msg.getDescription());
    serializer.endTag("", "body");
    serializer.endTag("", "message");
   }
   serializer.endTag("", "messages");
   serializer.endDocument();
   return writer.toString();
  } catch (Exception e) {
   throw new RuntimeException(e);
  }
 }

Edit:

This is the entire class that populates the feeds to a list view, using a ArrayAdapter, there's no cursor on any database though, since I don't store the feeds locally:

import android.app.ProgressDialog;
import android.content.Intent;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.text.Html;
import android.util.Log;
import android.util.Xml;
import android.view.Gravity;
import android.view.View;
import android.widget.*;
import org.developerworks.android.FeedParser;
import org.developerworks.android.FeedParserFactory;
import org.developerworks.android.Message;
import org.developerworks.android.ParserType;
import org.xmlpull.v1.XmlSerializer;

import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;

public class Twitter extends BaseActivity implements
        AdapterView.OnItemClickListener {

    private List<Message> messages;
    private List<String> titles;

    //TweetsAdapter ta = new TweetsAdapter(this);
    public ListView lstTweets = null;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.twitter);

        // set header title
        ((TextView)findViewById(R.id.txtHeaderTitle)).setText( Html.fromHtml("<b>" + getResources().getString(R.string.activity_title_twitter) +"</b>"));

        // highlight icon
        ImageButton btn = (ImageButton)findViewById(R.id.btnTwitter);
        btn.setBackgroundResource(R.drawable.menu_icon_twitter_active);

        // load list of tweets
        lstTweets = (ListView)findViewById(R.id.lstTweets);
        lstTweets.setOnItemClickListener(this);

        new AsyncTask<Void, Void, Void>() {

            ProgressDialog p;
            boolean success = false;

            @Override
            protected void onPostExecute(Void aVoid) {
                p.dismiss();
                if (!success) {

                    Twitter.this.runOnUiThread(new Runnable() {
                        public void run() {
                            Toast toast = Toast.makeText(Twitter.this, "Sorry, could not connect to Twitter.", Toast.LENGTH_LONG);
                            toast.setGravity(Gravity.CENTER_VERTICAL|Gravity.CENTER_HORIZONTAL, 0, 0);
                            toast.show();
                        }
                    });

                } else {
                    ArrayAdapter<String> adapter =
                        new ArrayAdapter<String>(Twitter.this, R.layout.twitter_list_row,titles);
                    lstTweets.setAdapter(adapter);
                }
            }

            @Override
            protected void onPreExecute() {
                p  = ProgressDialog.show(Twitter.this,"Loading...","...please wait a moment.");
            }

            @Override
            protected Void doInBackground(Void... params) {
                try {
                    loadFeed(ParserType.ANDROID_SAX);
                    if (messages!=null&&messages.size()>0) success = true;
                } catch (RuntimeException e) {}
                catch (Exception e) {}
                return null;
            }
        }.execute();



    }


    public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
  Intent viewMessage = new Intent(Intent.ACTION_VIEW,
    Uri.parse(messages.get(position).getLink().toExternalForm()));
  this.startActivity(viewMessage);
    }


 private void loadFeed(ParserType type){
     try{
      Log.i("AndroidNews", "ParserType="+type.name());
      FeedParser parser = FeedParserFactory.getParser(type);
      long start = System.currentTimeMillis();
      messages = parser.parse();
      long duration = System.currentTimeMillis() - start;
      String xml = writeXml();      
      titles = new ArrayList<String>(messages.size());
      for (Message msg : messages){
       titles.add(msg.getTitle());
      }
     } catch (Throwable t){
      Log.e("AndroidNews",t.getMessage(),t);
     }
    }

    private String writeXml(){
  XmlSerializer serializer = Xml.newSerializer();
  StringWriter writer = new StringWriter();
  try {
   serializer.setOutput(writer);
   serializer.startDocument("UTF-8", true);
   serializer.startTag("", "messages");
   serializer.attribute("", "number", String.valueOf(messages.size()));
   for (Message msg: messages){
    serializer.startTag("", "message");
    serializer.attribute("", "date", msg.getDate());
    serializer.startTag("", "title");
    serializer.text(msg.getTitle());
    serializer.endTag("", "title");
    serializer.startTag("", "url");
    serializer.text(msg.getLink().toExternalForm());
    serializer.endTag("", "url");
    serializer.startTag("", "body");
    serializer.text(msg.getDescription());
    serializer.endTag("", "body");
    serializer.endTag("", "message");
   }
   serializer.endTag("", "messages");
   serializer.endDocument();
   return writer.toString();
  } catch (Exception e) {
   throw new RuntimeException(e);
  }
 }
}
Mathias Conradt
  • 28,420
  • 21
  • 138
  • 192
  • I guess this is the URL: http://www.extreme.indiana.edu/xgws/xsoap/xpp/. Can you explain more in detail what really we have to here. Also can you shed some light on the other answer that involves 4 steps(DavLink's reply? Thanks – Muhammad Maqsoodur Rehman Oct 29 '10 at 10:50
  • what's your use case? do you really need to store the news in a DB locally? in my app for example, i just show the twitter feeds in a listview withouth storing them, so steps 3,4 are optional I would say, depending on your usecase. You need the news persistent / available offline as well? – Mathias Conradt Oct 29 '10 at 11:25
  • see the edited reply with a whole class sample how to show the feeds in a list view. – Mathias Conradt Oct 29 '10 at 11:29
  • Yes! It is my app's requirement to store news in a DB locally. BTW lets say if we do not want to use a DB, then how can we store the feeds...in a folder i suppose? – Muhammad Maqsoodur Rehman Oct 29 '10 at 11:33
  • 1
    There are different way to store data, i.e. files, take a look at http://developer.android.com/intl/fr/guide/topics/data/data-storage.html. But I think DB would be the best way. – Mathias Conradt Oct 29 '10 at 11:59
  • Fine.Would you care to email me your project at maqsood_rahman@hotmail.com. Thanks – Muhammad Maqsoodur Rehman Oct 29 '10 at 12:04
  • I'm getting a fatal exception: Parser exception for C:\Workspace\AndroidFeedsReader\AndroidManifest.xml: The processing instruction target matching "[xX][mM][lL]" is not allowed. [2010-11-01 13:02:56 - AndroidFeedsReader] Error in an XML file: aborting build. – Muhammad Maqsoodur Rehman Nov 01 '10 at 08:06
  • 1
    What file are you parsing? Is it valid rss/atom? can you pastebin the xml file or give the url. – Mathias Conradt Nov 01 '10 at 08:21
  • My url is: http://www.webpronews.com/feeds. What do you mean by valid rss/atom? How can i retrieve the feeds of this url? – Muhammad Maqsoodur Rehman Nov 02 '10 at 05:01
  • 1
    webpronews.com/feeds is not an xml file, it's a html web page. You need to point the parser to a rss feed. From the url you mentioned you pick the relevant feed (see the list of orange icons at the bottom) and then copy/paste it's url, i.e. http://feeds.feedburner.com/Webpronews-Technology?format=xml. RSS feeds are xml format, not html. – Mathias Conradt Nov 02 '10 at 06:19
  • Right! Just pasted feeds.feedburner.com/Webpronews-Technology?format=xml in my FeedParserFactory.java class as feeds and i gotthe reult in a ListView. – Muhammad Maqsoodur Rehman Nov 02 '10 at 06:38
  • Now i need to store the feed in a database file prior to display it in a ListView. I want my user to access the news even when he is offline. Any clue? – Muhammad Maqsoodur Rehman Nov 02 '10 at 06:49
  • I'm almost done now. I just like to know what this method does in AndroidSaxFeedParser.java class? Xml.parse(this.getInputStream(), Xml.Encoding.ISO_8859_1, root.getContentHandler()); We have various encodings for XML.Encoding, can you explain please? Thanks – Muhammad Maqsoodur Rehman Nov 04 '10 at 06:08
  • the method parses the feed content and makes reusable object out of the input stream. you pass the encoding you need for the relevant feed. if your feeds are utf-8, then you just pass another param,i.e. utf-8 to the method. – Mathias Conradt Nov 04 '10 at 07:04
  • Fine.I'm still having trouble with insert query. Data having commas couldn't be inserted. How would i know that comma is there or not? How can i eliminate this error. Thanks – Muhammad Maqsoodur Rehman Nov 04 '10 at 07:29
3

That's not simple to implement.

A RSS file is an XML file which structure complies to a standard (fixed tag names).

In your application, you would need to:

  • Download the RSS feed: use HttpClient, services...
  • Extract the data out of XML: use a XML parser, some are provided
  • Store the data: the best solution is a SQLite database
  • Display the data: ListView with CursorAdapter pointing to the database
DavGin
  • 8,205
  • 2
  • 19
  • 26
  • ok! So there are 4 steps there. I can manage to carry out the last 3 steps.Tell me about the first one. How can i download an RSS feed in android? – Muhammad Maqsoodur Rehman Oct 29 '10 at 10:26
  • Done it! :) I have the feeds being downloaded and having saved in a database file. I have a question here: What does this method does Xml.parse(this.getInputStream(), Xml.Encoding.ISO_8859_1, root.getContentHandler()); You maylook at the AndroidSaxFeedParser.java class. Cheers – Muhammad Maqsoodur Rehman Nov 04 '10 at 06:03
1

DavLink, is right. RSS parsing is not trivial.

It's fairly easy to setup an implementation of a SAX parser but the hard part is to be able to parse any and every feed under the sun.

You need to cater to all formats RSS 1, RSS 2, Atom etc. Even then you will have to contend with poorly formatted feeds.

I had faced similar problems in the past so decided to do my feed parsing on a server and just get the parsed contents. This allows me to run more complex libraries and parser which I can modify without pushing out updates for my app.

I have the following service running on AppEngine which allows for a much simpler XML / JSON parsing at your end. There is a fixed and simple structure to the response. You can use this for parsing

http://evecal.appspot.com/feedParser

You can send both POST and GET requests with the following parameters.

feedLink : The URL of the RSS feed response : JSON or XML as the response format

Examples:

For a POST request

curl --data-urlencode "feedLink=http://feeds.bbci.co.uk/news/world/rss.xml" --data-urlencode "response=json" http://evecal.appspot.com/feedParser

For GET request

evecal.appspot.com/feedParser?feedLink=http://feeds.nytimes.com/nyt/rss/HomePage&response=xml

My android app "NewsSpeak" uses this too.

After you get your information, you can use a simple listview with an arrayadapter having your array of items.

VNVN
  • 501
  • 1
  • 4
  • 7