Android开发RSS阅读器

               

        RSS阅读器的Logo:

                                       

        RSS阅读器是一种软件或是说一个程序,这种软件可以自由读取RSS和Atom两种规范格式的文档,且这种读取RSS和Atom文档的软件有多个版本,由不同的人或公司开发,有着不同的名字。如目前流行的有:RSSReader、Feeddemon、SharpReader等。这些软件能够实现大致相同的功能,其实质都是为了方便地读取RSS和Atom文档。Really Simple Syndication “聚合真的很简单”就是RSS的英文原意。把新闻标题、摘要(Feed)、内容按照用户的要求,“送”到用户的桌面就是RSS的目的。


注:下面给出的这个例子来自Google Android SDK开发,经过阅读,理解,并加上自己的和汇总写下这篇文章。


首先,给出实现本实例的截图,我用这个阅读器打开了我的博客。

1.


这是程序运行的主界面,实现这个界面的代码如下:

package irdc.ex08_13;/* import相关class */import android.app.Activity;import android.app.AlertDialog;import android.content.DialogInterface;import android.content.Intent;import android.os.Bundle;import android.view.View;import android.widget.Button;import android.widget.EditText;public class EX08_13 extends Activity/* 变量声明 */  private Button mButton;  private EditText mEditText;    @Override  public void onCreate(Bundle savedInstanceState)  {    super.onCreate(savedInstanceState);    setContentView(R.layout.main);    /* 初始化对象 */    mEditText=(EditText) findViewById(R.id.myEdit);    mButton=(Button) findViewById(R.id.myButton);    /* 设定Button的onClick事件 */    mButton.setOnClickListener(new Button.OnClickListener()     {       @Override       public void onClick(View v)       {         String path=mEditText.getText().toString();        if(path.equals(""))        {          showDialog("网址不可为空白!");        }        else        {          /* new一个Intent对象,并指定class */          Intent intent = new Intent();          intent.setClass(EX08_13.this,EX08_13_1.class);                    /* new一个Bundle对象,并将要传递的数据传入 */          Bundle bundle = new Bundle();          bundle.putString("path",path);          /* 将Bundle对象assign给Intent */          intent.putExtras(bundle);          /* 调用Activity EX08_13_1 */          startActivityForResult(intent,0);        }      }     });  }    /* 重写 onActivityResult()*/  @Override  protected void onActivityResult(int requestCode,int resultCode,                                  Intent data)  {    switch (resultCode)    {       /*       * 当由主程序唤起的EX08_13_1发生运行错误时,会返回resultCode=99的信息,主程序       * 在接收到信息时,将以Dialog显示错误信息       */      case 99:        /* 回传错误时以Dialog显示 */        Bundle bunde = data.getExtras();        String error = bunde.getString("error");        showDialog(error);        break;             default:         break;      }    }     /* 显示Dialog的method */  private void showDialog(String mess){    new AlertDialog.Builder(EX08_13.this).setTitle("Message")    .setMessage(mess)    .setNegativeButton("确定", new DialogInterface.OnClickListener()    {      public void onClick(DialogInterface dialog, int which)      {                }    })    .show();  }}

2.点击打开按钮,进入文档界面,实现的截图如下:



说明:

* 这是一个ListActivity,主要用来显示订阅的RSS内容列表
 * 当程序被主程序唤醒时,会先从Bundle对象中取得主程序传入的RSS网址,再调用自定义的getRss()方法
 * 对RSS网址发出request,并解析由服务器返回的XML格式的文件。
 * getRss()是自定义的方法,它除了会将RSS的request传送出去,在接收到服务器response时,会以
 * SAXParser作为解析XML的主要工具,利用自定义的MyHandler类来取得XML内的相关信息。
 * 调用getRss()时,会返回一个List<News>,内存的每一笔数据就是一个News对象,也就是所有新闻的列表;
 * 在取得List<News>之后,将List传入自定义的MyAdapter对象,再使用setListAdapter()将数据设置给ListView。
 * 程序中重写ListActivity的onListItemClick(),当ListView中的任一个item被单击时,onClick()会被触发,
 * 此时会先取得单击的News对象,并将相关信息传入Bundle中,再将Bundle对象assign给Intent,并唤起EX08_13_2这个
 * Activity。
 * 当程序发生错误时,会返回resultCode=99的信息给上一个Activity


下面给出实现代码:

public class EX08_13_1 extends ListActivity/* 变量声明 */  private TextView mText;  private String title=""private List<News> li=new ArrayList<News>();    @Override  public void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    /* 设定layout为newslist.xml */    setContentView(R.layout.newslist);        mText=(TextView) findViewById(R.id.myText);    /* 取得Intent中的Bundle对象 */    Intent intent=this.getIntent();    Bundle bunde = intent.getExtras();    /* 取得Bundle对象中的数据 */    String path = bunde.getString("path");    /* 调用getRss()取得解析后的List */    li=getRss(path);    mText.setText(title);    /* 设定自定义的MyAdapter */    setListAdapter(new MyAdapter(this,li));  }    /* 设定ListItem被按下时要做的动作 */  @Override  protected void onListItemClick(ListView l,View v,int position,                                 long id)  {    /* 取得News对象 */    News ns=(News)li.get(position);    /* new一个Intent对象,并指定class */    Intent intent = new Intent();    intent.setClass(EX08_13_1.this,EX08_13_2.class);    /* new一个Bundle对象,并将要传递的数据传入 */    Bundle bundle = new Bundle();    bundle.putString("title",ns.getTitle());    bundle.putString("desc",ns.getDesc());    bundle.putString("link",ns.getLink());    /* 将Bundle对象assign给Intent */    intent.putExtras(bundle);    /* 调用Activity EX08_13_2 */    startActivity(intent);  }    /* 剖析XML的method */  private List<News> getRss(String path)  {    List<News> data=new ArrayList<News>();    URL url = null;         try    {        url = new URL(path);      /* 产生SAXParser对象 */       SAXParserFactory spf = SAXParserFactory.newInstance();       SAXParser sp = spf.newSAXParser();       /* 产生XMLReader对象 */       XMLReader xr = sp.getXMLReader();       /* 设定自定义的MyHandler给XMLReader */       MyHandler myExampleHandler = new MyHandler();       xr.setContentHandler(myExampleHandler);           /* 解析XML */      xr.parse(new InputSource(url.openStream()));      /* 取得RSS标题与内容列表 */      data =myExampleHandler.getParsedData();       title=myExampleHandler.getRssTitle();    }    catch (Exception e)    {       /* 发生错误时回传result回上一个activity */      Intent intent=new Intent();      Bundle bundle = new Bundle();      bundle.putString("error",""+e);      intent.putExtras(bundle);      /* 错误的回传值设定为99 */      EX08_13_1.this.setResult(99, intent);      EX08_13_1.this.finish();    }    return data;  }}

在上一个类中用到了Handler对象,下面给出这个类的介绍:


 * 自定义的Handler对象,用来解析XML文件,并取得文件中的相关信息
 * RSS返回的XML文件中,每一则新闻内容的起始为<item>,结束为</item>,格式如下:
 * 
 * <item>
 * <title>新闻标题</title>
 * <guid isPermaLink="false">ID</guid>
 * <link>新闻连接</link>
 * <description>新闻描述</description>
 * <pubDate>发布时间</pubDate>
 * </item>
 * 
 * MyHandler在解析上述XML文件内容的流程如下:
 * 1.运行startDocument(),生成一个List<News>,作为存放News对象之用
 * 2.当程序解析到Element的起始时,会运行startElement(),程序依据Element名称的不同,将其所对应的boolean
 * 参数设置为true。
 * 3.当程序解析到文件中的字符时(character),会运行characters()这个方法,将字符附加到(append)StringBuffer中
 * 4.当程序解析到Element的结尾时会运行endElement(),程序依据Element名称的不同,将由StringBuffer转换成的字符串,
 * 以setXXX()的方式把该属性写入News对象中,并把相对应的boolean变量设置为false。


实现代码如下:

public class MyHandler extends DefaultHandler{   /* 变量声明 */  private boolean in_item = false;   //News对象的四个属性标记  private boolean in_title = falseprivate boolean in_link = falseprivate boolean in_desc = falseprivate boolean in_date = false;    private boolean in_mainTitle = falseprivate List<News> li;  private News news;  private String title=""private StringBuffer buf=new StringBuffer();  /* 将转换成List<News>的XML数据回传 */  public List<News> getParsedData()  {     return li;   }  /* 将解析出的RSS title回传 */  public String getRssTitle()  {     return title;   }  /* XML文件开始解析时调用此method */  @Override   public void startDocument() throws SAXException  {     li = new ArrayList<News>();   }   /* XML文件结束解析时调用此method */  @Override   public void endDocument() throws SAXException  {  }   /* 解析到Element的开头时调用此method */  @Override   public void startElement(String namespaceURI, String localName,                String qName, Attributes atts) throws SAXException  {     if (localName.equals("item"))    {       this.in_item = true;      /* 解析到item的开头时new一个News对象 */      news=new News();    }    else if (localName.equals("title"))    {       if(this.in_item)      {        this.in_title = true;      }      else      {        this.in_mainTitle = true;      }    }    else if (localName.equals("link"))    {       if(this.in_item)      {        this.in_link = true;      }    }    else if (localName.equals("description"))    {       if(this.in_item)      {        this.in_desc = true;      }    }    else if (localName.equals("pubDate"))    {       if(this.in_item)      {        this.in_date = true;      }    }   }  /* 解析到Element的结尾时调用此method */  @Override   public void endElement(String namespaceURI, String localName,                         String qName) throws SAXException  {     if (localName.equals("item"))    {       this.in_item = false;      /* 解析到item的结尾时将News对象写入List中 */      li.add(news);    }    else if (localName.equals("title"))    {       if(this.in_item)      {        /* 设定News对象的title */        news.setTitle(buf.toString().trim());        buf.setLength(0);        this.in_title = false;      }      else      {        /* 设定RSS的title */        title=buf.toString().trim();        buf.setLength(0);        this.in_mainTitle = false;      }    }    else if (localName.equals("link"))    {       if(this.in_item)      {        /* 设定News对象的link */        news.setLink(buf.toString().trim());        buf.setLength(0);        this.in_link = false;      }    }    else if (localName.equals("description"))    {       if(in_item)      {        /* 设定News对象的description */        news.setDesc(buf.toString().trim());        buf.setLength(0);        this.in_desc = false;      }    }    else if (localName.equals("pubDate"))    {       if(in_item)      {        /* 设定News对象的pubDate */        news.setDate(buf.toString().trim());        buf.setLength(0);        this.in_date = false;      }    }   }   /* 取得Element的开头结尾中间夹的字符串 */  @Override   public void characters(char ch[], int start, int length)  {     if(this.in_item||this.in_mainTitle)    {      /* 将char[]加入StringBuffer */      buf.append(ch,start,length);    }  } }

在前两个类中都用到了News这个类对象,这是对阅读文档对象的定义,代码文件如下:

* 这是一个JavaBean的类,用来存放每一篇新闻的详细信息。简单的说,每一个News对象就代表了一则新闻,News对象中的
 *定义了的四个属性
 *1.新闻的标题_title
 *2.新闻的描述_desc
 *3.网站的连接_link
 *4.发布时间_date


public class News{   /* News的四个变数 */  private String _title=""private String _link=""private String _desc=""private String _date="";    public String getTitle()  {     return _title;   }   public String getLink()  {     return _link;   }  public String getDesc()  {     return _desc;   }   public String getDate()  {     return _date;   }  public void setTitle(String title)  {     _title=title;   }   public void setLink(String link)  {     _link=link;   }  public void setDesc(String desc)  {     _desc=desc;   }   public void setDate(String date)  {     _date=date;   }}

第二个文件的主布局是一个ListView用来显示可阅读文档,下面给出提供数据的Adapter文件:

package irdc.ex08_13;/* import相关class */import java.util.List;import android.content.Context;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter;import android.widget.TextView;/* 自定义的Adapter,继承android.widget.BaseAdapter */public class MyAdapter extends BaseAdapter/* 变量声明  */  private LayoutInflater mInflater;  private List<News> items;  /* MyAdapter的建构子,传入两个参数  */    public MyAdapter(Context context,List<News> it)  {    /* 参数初始化 */    mInflater = LayoutInflater.from(context);    items = it;  }    /* 因继承BaseAdapter,需重写以下method */  @Override  public int getCount()  {    return items.size();  }  @Override  public Object getItem(int position)  {    return items.get(position);  }    @Override  public long getItemId(int position)  {    return position;  }    @Override  public View getView(int position,View convertView,ViewGroup par)  {    ViewHolder holder;        if(convertView == null)    {      /* 使用自定义的news_row作为Layout */      convertView = mInflater.inflate(R.layout.news_row, null);      /* 初始化holder的text与icon */      holder = new ViewHolder();      holder.text = (TextView) convertView.findViewById(R.id.text);            convertView.setTag(holder);    }    else    {      holder = (ViewHolder) convertView.getTag();    }    News tmpN=(News)items.get(position);    holder.text.setText(tmpN.getTitle());        return convertView;  }    /* class ViewHolder */  private class ViewHolder  {    TextView text;  }}

之后,当我们点击一条信息之后,就会进入下一界面,实现的截图如下:



我们只需要点击其中的链接,就可以打开相应的网页文件,截图如下:


实现的代码如下:

注意,打开网页是调用系统自带的浏览器:

package irdc.ex08_13;/* import相关class */import android.app.Activity;import android.content.Intent;import android.os.Bundle;import android.text.util.Linkify;import android.widget.TextView;public class EX08_13_2 extends Activity/* 变量声明 */  private TextView mTitle;  private TextView mDesc;  private TextView mLink;    @Override  public void onCreate(Bundle savedInstanceState)  {    super.onCreate(savedInstanceState);    /* 设定layout为newscontent.xml */    setContentView(R.layout.newscontent);    /* 初始化对象 */    mTitle=(TextView) findViewById(R.id.myTitle);    mDesc=(TextView) findViewById(R.id.myDesc);    mLink=(TextView) findViewById(R.id.myLink);    /* 取得Intent中的Bundle对象 */    Intent intent=this.getIntent();    Bundle bunde = intent.getExtras();    /* 取得Bundle对象中的数据 */    mTitle.setText(bunde.getString("title"));    mDesc.setText(bunde.getString("desc")+"....");    mLink.setText(bunde.getString("link"));    /* 设定mLink为网页连结 */    Linkify.addLinks(mLink,Linkify.WEB_URLS);  }}


           

再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow

猜你喜欢

转载自blog.csdn.net/yffhhffv/article/details/86636110