要在Android平台中开发RSS客户端,首先需要了解什么是RSSRSS怎样工作,及怎样用XML编程RSS等知识。闲言少叙,我们开始吧。

首先,我们必须要了解什么是RSS

1. RSSReally Simple Syndication(真正简易联合)

2. RSS使您有能力聚合(syndicate)网站的内容

3. RSS定义了非常简单的方法来共享和查看标题和内容

4. RSS文件可被自动更新

5. RSS允许为不同的网站进行视图的个性化

6. RSS使用XML编写

RSS被设计用来展示选定的数据。如果没有 RSS,用户就不得不每日都来您的网站检查新的内容。对许多用户来说这样太费时了。通过RSS feedRSS 通常被称为 News feed RSS feed),用户们可以使用 RSS 聚合器来更快地检查您的网站更新(RSS 聚合器是用来聚集并分类 RSS feed 的网站或软件)。由于RSS 数据很小巧并可快速加载,它可轻易地被类似移动电话或 PDA 的服务使用。拥有相似内容的网站环(Web-rings)可以轻易地在它们的网站共享内容,使这些网站更出色更有价值。

谁应当使用RSS

那些极少更新内容的网管们不需要RSS

RSS对那些频繁更新内容的网站是很有帮助的,比如:

新闻站点 列出新闻的标题、日期以及描述

企业 列出新闻和新产品

日程表 列出即将来临的安排和重要日期

站点更新 列出更新过的页面或新的页面

RSS如何工作

使用RSS,您在名为聚合器的公司注册您的内容。

步骤之一是,创建一个RSS 文档,然后使用.xml 后缀来保存它。然后把此文件上传到您的网站。接下来,通过一个RSS 聚合器来注册。每天,聚合器都会到被注册的网站搜索RSS文档,校验其链接,并显示有关 feed 的信息,这样客户就能够链接到使他们产生兴趣的文档。

一个RSS实例文档

RSS文档使用一种简单的自我描述的语法:

让我们看一个简单的RSS文档:

XML/HTML代码:

<?xml version="1.0" encoding="ISO-8859-1" ?>   <rss version="2.0">      <channel>     <title>W3School Home Page</title>     <link>http://www.w3school.com.cn</link>     <description>Free web building tutorials</description>     <item>       <title>RSS Tutorial</title>       <link>http://www.w3school.com.cn/rss</link>       <description>New RSS tutorial on W3School</description>     </item>     <item>       <title>XML Tutorial</title>       <link>http://www.w3school.com.cn/xml</link>       <description>New XML tutorial on W3School</description>     </item>   </channel>      </rss>  

文档中的第一行:XML声明 - 定义了文档中使用的XML 版本和字符编码。此例子遵守1.0规范,并使用ISO-8859-1 (Latin-1/West European) 字符集。

下一行是标识此文档是一个RSS文档的RSS 声明(此例是 RSS version 2.0)。

下一行含有 <channel> 元素。此元素用于描述RSS feed

<channel> 元素有三个必需的子元素:

<title> - 定义频道的标题。(比如 w3school 首页)

<link> - 定义到达频道的超链接。(比如:www.w3school.com.cn

<description> - 描述此频道(比如免费的网站建设教程)

每个<channel>元素可拥有一个或多个 <item> 元素。

每个<item>元素可定义 RSS feed 中的一篇文章或 "story"

<item> 元素拥有三个必需的子元素:

<title> - 定义项目的标题。(比如 RSS 教程)

<link> - 定义到达项目的超链接。(比如:http://www.w3school.com.cn/rss

<description> - 描述此项目(比如 w3school RSS 教程)

最后,后面的两行关闭 <channel> <rss> 元素。

RSS中的注释

RSS 中书写注释的语法与HTML 的语法类似:

<!-- This is an RSS comment -->

RSS使用XML来编写

因为RSS也是XML,请记住:

1. 所有的元素必许拥有关闭标签

2. 元素对大小写敏感

3. 元素必需被正确地嵌套

4. 属性值必须带引号

了解了以上内容,我们就通过一个例子来学习RSS,如何对XML文件进行解析....

首先,展示一下完成之后项目的运行结果:

下面是程序的具体实现:

阶段一:界面的布局,具体代码如下:

activity_main.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" >    <ListView         android:id="@+id/list"         android:layout_width="fill_parent"        android:layout_height="fill_parent" />    </RelativeLayout>

activity_show_description.xml:

<LinearLayout 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"    android:orientation="vertical" >    <TextView        android:id="@+id/content"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:autoLink="web"        android:text="" />    <Button        android:id="@+id/back"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_gravity="right"        android:text="@string/back" /></LinearLayout>

阶段二:编写实体类RssFeed及RssItem

RssFeed.java:

package com.lks.rss_saxparser.entity;import java.util.ArrayList;import java.util.HashMap;import java.util.List;public class RssFeed {private String title; // 标题private String pubdate; // 发布日期private int itemCount; // 用于计算列表的数目private List<RssItem> rssItems; // 用于描述列表itempublic RssFeed() {rssItems = new ArrayList<RssItem>();}// 添加RssItem条目,返回列表长度public int addItem(RssItem rssItem) {rssItems.add(rssItem);itemCount++;return itemCount;}// 根据下标获取RssItempublic RssItem getItem(int position) {return rssItems.get(position);}public List<HashMap<String, Object>> getAllItems() {List<HashMap<String, Object>> data = new ArrayList<HashMap<String, Object>>();for (int i = 0; i < rssItems.size(); i++) {HashMap<String, Object> item = new HashMap<String, Object>();item.put(RssItem.TITLE, rssItems.get(i).getTitle());item.put(RssItem.PUBDATE, rssItems.get(i).getPubdate());data.add(item);}return data;}public String getTitle() {return title;}public void setTitle(String title) {this.title = title;}public String getPubdate() {return pubdate;}public void setPubdate(String pubdate) {this.pubdate = pubdate;}public int getItemCount() {return itemCount;}public void setItemCount(int itemCount) {this.itemCount = itemCount;}}

RssItem.java:

package com.lks.rss_saxparser.entity;public class RssItem {private String title;private String description;private String link;private String category;private String pubdate;public static final String TITLE = "title";public static final String PUBDATE = "pubdate";public RssItem() {}public String getTitle() {if (title.length() > 20) {return title.substring(0, 19) + "...";}return title;}public void setTitle(String title) {this.title = title;}public String getDescription() {return description;}public void setDescription(String description) {this.description = description;}public String getLink() {return link;}public void setLink(String link) {this.link = link;}public String getCategory() {return category;}public void setCategory(String category) {this.category = category;}public String getPubdate() {return pubdate;}public void setPubdate(String pubdate) {this.pubdate = pubdate;}@Overridepublic String toString() {return "RssItem [title=" + title + ", description=" + description+ ", link=" + link + ", category=" + category + ", pubdate="+ pubdate + "]";}}

阶段三:编写解析XML文件时的处理类,用自定义的RssHandler继承自DefaultHandler,然后重载DefaultHandler的五个方法。具体代码如下:

package com.lks.rss_saxparser.service;import org.xml.sax.Attributes;import org.xml.sax.SAXException;import org.xml.sax.helpers.DefaultHandler;import android.util.Log;import com.lks.rss_saxparser.entity.RssFeed;import com.lks.rss_saxparser.entity.RssItem;public class RssHandler extends DefaultHandler {RssFeed rssFeed;RssItem rssItem;String lastElementName = "";// 标记变量,用于标记在解析过程中我们关心的几个标签,若不是我们关心的标签记做0final int RSS_TITLE = 1;// 若是 title 标签,记做1,注意有两个title,但我们都保存在item的成员变量中final int RSS_LINK = 2;// 若是 link 标签,记做2final int RSS_DESCRIPTION = 3;// 若是 description 标签,记做3final int RSS_CATEGORY = 4;// 若是category标签,记做 4final int RSS_PUBDATE = 5; // 若是pubdate标签,记做5,注意有两个pubdate,但我们都保存在item的pubdate成员变量中int currentFlag = 0;public RssHandler() {}@Overridepublic void startDocument() throws SAXException {super.startDocument();rssFeed = new RssFeed();rssItem = new RssItem();}@Overridepublic void characters(char[] ch, int start, int length)throws SAXException {super.characters(ch, start, length);// 获取字符串String text = new String(ch, start, length);Log.i("i", "要获取的内容:" + text);switch (currentFlag) {case RSS_TITLE:rssItem.setTitle(text);currentFlag = 0;// 设置完后,重置为开始状态break;case RSS_PUBDATE:rssItem.setPubdate(text);currentFlag = 0;// 设置完后,重置为开始状态break;case RSS_CATEGORY:rssItem.setCategory(text);currentFlag = 0;// 设置完后,重置为开始状态break;case RSS_LINK:rssItem.setLink(text);currentFlag = 0;// 设置完后,重置为开始状态break;case RSS_DESCRIPTION:rssItem.setDescription(text);currentFlag = 0;// 设置完后,重置为开始状态break;default:break;}}@Overridepublic void startElement(String uri, String localName, String qName,Attributes attributes) throws SAXException {super.startElement(uri, localName, qName, attributes);if ("chanel".equals(localName)) {// 这个标签内没有我们关心的内容,所以不作处理,currentFlag=0currentFlag = 0;return;}if ("item".equals(localName)) {rssItem = new RssItem();return;}if ("title".equals(localName)) {currentFlag = RSS_TITLE;return;}if ("description".equals(localName)) {currentFlag = RSS_DESCRIPTION;return;}if ("link".equals(localName)) {currentFlag = RSS_LINK;return;}if ("pubDate".equals(localName)) {currentFlag = RSS_PUBDATE;return;}if ("category".equals(localName)) {currentFlag = RSS_CATEGORY;return;}}@Overridepublic void endElement(String uri, String localName, String qName)throws SAXException {super.endElement(uri, localName, qName);// 如果解析一个item节点结束,就将rssItem添加到rssFeed中。if ("item".equals(localName)) {rssFeed.addItem(rssItem);return;}}@Overridepublic void endDocument() throws SAXException {super.endDocument();}public RssFeed getRssFeed() {return rssFeed;}}

阶段四:从SAXParser解析器中获得解析xml文件的xmlReader ,使用阶段三中自定义的xml解析器作为xmlReader的处理器,然后使用url打开流,并将流作为 xmlReader解析的输入源并解析。具体代码如下:

package com.lks.rss_saxparser.saxparser;import java.io.IOException;import java.net.URL;import javax.xml.parsers.ParserConfigurationException;import javax.xml.parsers.SAXParser;import javax.xml.parsers.SAXParserFactory;import org.xml.sax.InputSource;import org.xml.sax.SAXException;import org.xml.sax.XMLReader;import com.lks.rss_saxparser.entity.RssFeed;import com.lks.rss_saxparser.service.RssHandler;public class RssFeed_SAXParser {public RssFeed getFeed(String urlStr) throws ParserConfigurationException, SAXException, IOException{URL url = new URL(urlStr);SAXParserFactory saxParserFactory = SAXParserFactory.newInstance(); //构建SAX解析工厂SAXParser saxParser = saxParserFactory.newSAXParser(); //解析工厂生产解析器XMLReader xmlReader = saxParser.getXMLReader(); //通过saxParser构建xmlReader阅读器RssHandler rssHandler=new RssHandler();xmlReader.setContentHandler(rssHandler);//使用url打开流,并将流作为 xmlReader解析的输入源并解析InputSource inputSource = new InputSource(url.openStream());xmlReader.parse(inputSource);return rssHandler.getRssFeed();}}

阶段五:编写MainActivity,将解析的XML文件以列表的形式显示出来,具体代码如下:

package com.lks.rss_saxparser;import java.io.IOException;import javax.xml.parsers.ParserConfigurationException;import org.xml.sax.SAXException;import com.lks.rss_saxparser.R;import com.lks.rss_saxparser.entity.RssFeed;import com.lks.rss_saxparser.entity.RssItem;import com.lks.rss_saxparser.saxparser.RssFeed_SAXParser;import android.os.Bundle;import android.app.Activity;import android.content.Intent;import android.view.Menu;import android.view.MenuItem;import android.view.View;import android.widget.AdapterView;import android.widget.AdapterView.OnItemClickListener;import android.widget.ListView;import android.widget.SimpleAdapter;import android.support.v4.app.NavUtils;public class MainActivity extends Activity implements OnItemClickListener {// 从网络获取RSS地址public final String RSS_URL = "http://ent.qq.com/movie/rss_movie.xml";public final String tag = "RSSReader";private RssFeed feed = null;@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);try {feed = new RssFeed_SAXParser().getFeed(RSS_URL);} catch (ParserConfigurationException e) {e.printStackTrace();} catch (SAXException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}showListView();}/* * 把RSS内容绑定到ui界面进行显示 */private void showListView() {ListView itemList = (ListView) this.findViewById(R.id.list);if (feed == null) {setTitle("访问的RSS无效");return;}SimpleAdapter simpleAdapter = new SimpleAdapter(this,feed.getAllItems(), android.R.layout.simple_list_item_2,new String[] { RssItem.TITLE, RssItem.PUBDATE }, new int[] {android.R.id.text1, android.R.id.text2 });itemList.setAdapter(simpleAdapter);itemList.setOnItemClickListener(this);itemList.setSelection(0);}@Overridepublic boolean onCreateOptionsMenu(Menu menu) {getMenuInflater().inflate(R.menu.activity_main, menu);return true;}@Overridepublic void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {Intent intent = new Intent();intent.setClass(this, ShowDescriptionActivity.class);Bundle bundle = new Bundle();bundle.putString("title", feed.getItem(position).getTitle());bundle.putString("description",feed.getItem(position).getDescription());bundle.putString("link", feed.getItem(position).getLink());bundle.putString("pubdate", feed.getItem(position).getPubdate());// 用android.intent.extra.INTENT的名字来传递参数intent.putExtra("android.intent.extra.rssItem", bundle);startActivityForResult(intent, 0);}}

编写ShowDescriptionActivity,用于显示每条新闻的详情,具体代码如下:

package com.lks.rss_saxparser;import android.os.Bundle;import android.app.Activity;import android.content.Intent;import android.view.Menu;import android.view.MenuItem;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.TextView;import android.support.v4.app.NavUtils;public class ShowDescriptionActivity extends Activity {    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_show_description);        String content =null;                Intent intent = getIntent();        if(intent!=null){        Bundle bundle = intent.getBundleExtra("android.intent.extra.rssItem");        if(bundle==null){        content = "不好意思程序出错啦";        }else{        content = bundle.getString("title") + "\n\n"+ bundle.getString("pubdate") + "\n\n"+ bundle.getString("description").replace('\n', ' ')+ "\n\n详细信息请访问以下网址:\n" + bundle.getString("link");        }        }else{        content = "不好意思程序出错啦";        }                TextView contentText = (TextView) this.findViewById(R.id.content);        contentText.setText(content);                Button backButton = (Button) this.findViewById(R.id.back);        backButton.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {finish();}});    }    @Override    public boolean onCreateOptionsMenu(Menu menu) {        getMenuInflater().inflate(R.menu.activity_show_description, menu);        return true;    }}

最后,不要忘了在AndroidManifest.xml文件中添加访问网络的权限:

<uses-permission android:name="android.permission.INTERNET"/>

这样,RSS阅读器就完成了~相应的项目已上传至资源中、欢迎下载~


更多相关文章

  1. 浅谈Android布局
  2. 通用代码库之listview和GridView
  3. ffmpeg 移植到 android
  4. 转 20个Android很有用的代码片段
  5. Android开发:集成dropbox网盘功能
  6. Android(安卓)Studio 4.1 更新内容
  7. android 实现在文本内容超过固定宽度可手动左右滚动查看效果
  8. 布局优化:使用include、merge、ViewStub
  9. android登录tomcat服务器并查找数据库的内容

随机推荐

  1. Android-UI——TextView各属性详解
  2. eclipse:打开 eclipse 出现 “android sdk
  3. MediaPlayer框架概述(一)
  4. Android存储之SharedPreferences
  5. Android开发常用网站汇总
  6. //tools/emulator" java.io.IOException:
  7. Android(安卓)Design Support Library(3)-
  8. Android L之 VectorDrawable
  9. Android通知栏的变化
  10. Android ThreadLocal 源码分析