RSS阅读器(使用android解析技术解析xml文件并以列表的形式显示出来)
要在Android平台中开发RSS客户端,首先需要了解什么是RSS,RSS怎样工作,及怎样用XML编程RSS等知识。闲言少叙,我们开始吧。
首先,我们必须要了解什么是RSS:
1. RSS指Really Simple Syndication(真正简易联合)
2. RSS使您有能力聚合(syndicate)网站的内容
3. RSS定义了非常简单的方法来共享和查看标题和内容
4. RSS文件可被自动更新
5. RSS允许为不同的网站进行视图的个性化
6. RSS使用XML编写
RSS被设计用来展示选定的数据。如果没有 RSS,用户就不得不每日都来您的网站检查新的内容。对许多用户来说这样太费时了。通过RSS feed(RSS 通常被称为 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阅读器就完成了~相应的项目已上传至资源中、欢迎下载~
更多相关文章
- 浅谈Android布局
- 通用代码库之listview和GridView
- ffmpeg 移植到 android
- 转 20个Android很有用的代码片段
- Android开发:集成dropbox网盘功能
- Android(安卓)Studio 4.1 更新内容
- android 实现在文本内容超过固定宽度可手动左右滚动查看效果
- 布局优化:使用include、merge、ViewStub
- android登录tomcat服务器并查找数据库的内容