1.RSS格式结构
http://rss.sina.com.cn/blog/tech/kj.xml
<?xml version="1.0" encoding="utf-8"?> <?xml-stylesheet type="text/xsl" title="XSL Formatting" href="/show_new_final.xsl" media="all"?> <!-- SINA Corporation (NASDAQ: SINA) is a leading online media company and value-added information service (VAS) provider for China and for Chinese communities worldwide. With a branded network of localized websites targeting Greater China and overseas Chinese, SINA provides services through five major business lines including SINA.com (online news and content), SINA Mobile (mobile value-added services), SINA Online (community-based services and games), SINA.net (search and enterprise services) and SINA E-commerce (online shopping), offering Internet users and government and business clients an array of services including online media and entertainment, online fee-based VAS/wireless VAS, and e-commerce and enterprise e-solutions. With 230 million registered users worldwide, 450 million daily page views and over 60 million active users for a variety of fee-based services, SINA is the most recognized Internet brand name in China and among Chinese communities globally. In various surveys and polls, SINA has been recognized as the most valuable brand and the most popular website in China. For 2003 and 2005, SINA was ranked the "Most Preferred Website" in China according to the Chinese Academy of Social Sciences and considered "The Most Respected Chinese Company" for three consecutive years in 2003, 2004 and 2005 by the Economic Observer and the Management Case Study Center of Beijing University. At the same time, South China Weekend in both 2003 and 2004 honored SINA with the prestigious award of the "Chinese Language Medium of the Year." ****[pid:346,tid:121,did:20,fid:3468]****--> <rss version="2.0"> <channel> <title> <![CDATA[IT-新浪博客]]> </title> <image> <title> <![CDATA[新浪博客频道]]> </title> <link>http://blog.sina.com.cn</link> <url>http://www.sinaimg.cn/blog/main/index2010/blog_logo.png</url> </image> <description> <![CDATA[IT博客列表]]> </description> <link>http://blog.sina.com.cn/lm/tech/</link> <language>zh-cn</language> <generator>WWW.SINA.COM.CN</generator> <ttl>5</ttl> <copyright> <![CDATA[Copyright 1996 - 2013 SINA Inc. All Rights Reserved]]> </copyright> <pubDate>Mon, 18 Nov 2013 07:39:30 GMT</pubDate> <category> <![CDATA[]]> </category> <item> <title> <![CDATA[案例解读:电商企业如何做出差异]]> </title> <link>http://go.rss.sina.com.cn/redirect.php?url=http://blog.sina.com.cn/s/blog_6f3c35310101qkhr.html</link> <author>WWW.SINA.COM.CN</author> <guid>http://go.rss.sina.com.cn/redirect.php?url=http://blog.sina.com.cn/s/blog_6f3c35310101qkhr.html</guid> <category> <![CDATA[IT博客]]> </category> <pubDate>Mon, 18 Nov 2013 06:53:46 GMT</pubDate> <comments></comments> <description> <![CDATA[]]> </description> </item> <item> <title> <![CDATA[iOS 7:时尚与易用的平衡]]> </title> <link>http://go.rss.sina.com.cn/redirect.php?url=http://blog.sina.com.cn/s/blog_604f5cca0102e5tr.html</link> <author>WWW.SINA.COM.CN</author> <guid>http://go.rss.sina.com.cn/redirect.php?url=http://blog.sina.com.cn/s/blog_604f5cca0102e5tr.html</guid> <category> <![CDATA[IT博客]]> </category> <pubDate>Mon, 18 Nov 2013 06:40:45 GMT</pubDate> <comments></comments> <description> <![CDATA[]]> </description> </item> </channel> </rss>
2.登录
界面:
login.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <!-- 登陆图片 --> <ImageView android:id="@+id/login_rss" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/rss" android:layout_gravity="center_horizontal" android:layout_marginTop="30dp" /> <!-- 登陆文本 --> <TextView android:id="@+id/logining" android:layout_width="fill_parent" android:layout_height="wrap_content" android:gravity="center_horizontal" android:text="@string/logining" android:visibility="invisible" android:layout_marginTop="20dp" /> <!-- 登陆按钮 --> <Button android:id="@+id/login_in" android:layout_width="200dp" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:text="@string/login_in" android:layout_marginTop="10dp" /> </LinearLayout>
loginActivity.java
package com.rss.activity; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.ImageView; import android.widget.TextView; public class LoginActivity extends Activity { //登陆按钮 private Button loginButton; //登陆文本 private TextView loginText; //登陆图片 private ImageView imagView; //图片透明度 private int i_alpha = 255; private Handler mHandler = new Handler(); boolean isShow = false; private Thread thread; private Intent intent; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.login); //初始化界面元素 loginButton = (Button)findViewById(R.id.login_in); loginText = (TextView)findViewById(R.id.logining); imagView = (ImageView)findViewById(R.id.login_rss); //初始化图片分辨率 imagView.setAlpha(i_alpha); isShow = true; //更改图片分辨率 mHandler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); imagView.setAlpha(i_alpha); } }; //开启线程每隔100ms更新一次图片透明度 thread = new Thread(new Runnable() { public void run() { while(isShow) { try { Thread.sleep(100); updateAlpha(); }catch (InterruptedException e) { e.printStackTrace(); } } } }); //登陆按键监听器 loginButton.setOnClickListener(new OnClickListener() { public void onClick(View v) { intent = new Intent(); intent.setClass(LoginActivity.this, SelectChannel.class); //启动线程 thread.start(); //设置登陆按钮不可见 loginButton.setVisibility(View.INVISIBLE); //设置登陆文本显示 loginText.setVisibility(View.VISIBLE); } }); } //更新图片透明度 protected void updateAlpha() { //每次减25 if((i_alpha-25) >= 0) { i_alpha = i_alpha - 25; }else { //当透明度低于25,关闭当前界面,启动新界面 i_alpha = 0; isShow = false; startActivity(intent); LoginActivity.this.finish(); } //传递消息 mHandler.sendMessage(mHandler.obtainMessage()); } }
3.数据库存储
RSSProvider.java
package com.rss.db; import android.content.ContentProvider; import android.content.ContentUris; import android.content.ContentValues; import android.content.Context; import android.content.UriMatcher; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import android.database.sqlite.SQLiteQueryBuilder; import android.net.Uri; import android.text.TextUtils; import android.util.Log; //Rss数据内容管理 public class RssProvider extends ContentProvider { //rss内容数据库文件名 private static final String RSS_DATABASE = "rss.db"; //数据库表名 private static final String RSS_TABLE = "rss_item"; private static final int RSS_DATABASE_VERSION = 1; private static final String TAG = "RssProvider"; //URI public static final Uri RSS_URI = Uri.parse("content://com.rss.activity/rss"); //列名 public static final String RSS_ID = "_id"; public static final String RSS_TITLE = "title"; public static final String RSS_DESCRIPTION = "description"; public static final String RSS_LINK = "link"; public static final String RSS_PUBDATE = "pubDate"; //列的索引 public static final int TITLE_INDEX = 1; public static final int DESCRIPTION_INDEX = 2; public static final int LINK_INDEX = 3; public static final int PUBDATE_INDEX = 4; //创建表的sql语句 private static final String RSS_SQL = "CREATE TABLE " + RSS_TABLE + "(" + RSS_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + RSS_TITLE + " TEXT, " + RSS_DESCRIPTION + " TEXT, " + RSS_LINK + " TEXT, " + RSS_PUBDATE + " DATE);"; SQLiteDatabase rssDb = null; //创建用来区分不同URI的常量 private static final int RSS = 1; private static final int RSSID = 2; //uri地址匹配器 private static UriMatcher uriMatcher; static { uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); uriMatcher.addURI("com.rss.activity", "rss", RSS); uriMatcher.addURI("com.rss.activity", "rss/#", RSSID); } //创建管理数据的helper类 private static class RssDatabaseHelper extends SQLiteOpenHelper { //构造函数 public RssDatabaseHelper(Context context) { super(context, RSS_DATABASE, null, RSS_DATABASE_VERSION); Log.v(TAG, "Rss database create successfully!"); } //第一次创建数据库时调用 @Override public void onCreate(SQLiteDatabase db) { db.execSQL(RSS_SQL); Log.v(TAG, "Rss table create successfully!"); } //升级时调用 @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { db.execSQL("DROP TABLE IF EXISTS " + RSS_TABLE); onCreate(db);//重新创建表 } } @Override public int delete(Uri uri, String where, String[] whereArgs) { return 0; } //取得uri地址对应的操作 @Override public String getType(Uri uri) { switch (uriMatcher.match(uri)) { case RSS: return "vnd.android.cursor.dir/com.rss.activity"; case RSSID: return "vnd.android.cursor.item/com.rss.activity"; default: throw new IllegalArgumentException("Unsupport URI:" + uri); } } //存储数据 @Override public Uri insert(Uri _uri, ContentValues values) { Uri uri = null; long rowId = rssDb.insert(RSS_TABLE, null, values); //返回的rowId > 0 if(rowId > 0) { uri = ContentUris.withAppendedId(RSS_URI, rowId); getContext().getContentResolver().notifyChange(uri, null); } return uri; } //初始化函数 @Override public boolean onCreate() { Context context = getContext(); //实例化数据库帮助类 RssDatabaseHelper rssDbHelper = new RssDatabaseHelper(context); //获得对应的是数据库 rssDb = rssDbHelper.getWritableDatabase(); return (rssDb == null) ? false : true; } //查询 @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { SQLiteQueryBuilder sqb = new SQLiteQueryBuilder(); sqb.setTables(RSS_TABLE);//设置查询的表 //筛选uri地址 switch (uriMatcher.match(uri)) { //查询单个RSS信息 case RSSID: sqb.appendWhere(RSS_ID + "=" + uri.getPathSegments().get(1)); break; default: break; } String orderBy; if(TextUtils.isEmpty(sortOrder)) { orderBy = RSS_PUBDATE; }else { orderBy = sortOrder; } //对底层数据库的应用查询 Cursor c = sqb.query(rssDb, projection, selection, selectionArgs, null, null, orderBy); c.setNotificationUri(getContext().getContentResolver(), uri); return c; } //更新数据 @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { int count; //匹配uri地址 switch (uriMatcher.match(uri)) { case RSS: count = rssDb.update(RSS_TABLE, values, selection, selectionArgs); break; case RSSID: String segment = uri.getPathSegments().get(1); count = rssDb.update(RSS_TABLE, values, RSS_ID + "=" + segment + (!TextUtils.isEmpty(selection) ? " AND (" + selection +')' : ""), selectionArgs); break; default: throw new IllegalArgumentException("Unkown URI " + uri); } //通知更改 getContext().getContentResolver().notifyChange(uri, null); return count; } }
ChannelDataHelper.java
package com.rss.data; import java.util.ArrayList; import java.util.List; import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase.CursorFactory; import android.database.sqlite.SQLiteOpenHelper; import android.util.Log; //RSS数据库操作类 public class ChannelDataHelper { //数据库名称 private static String DB_NAME = "RssChannel.db"; //数据库版本 private static int DB_VERSION = 1; private SQLiteDatabase db; private SqliteHelper dbHelper; //构造函数 public ChannelDataHelper(Context context){ //实例化数据库帮组类 dbHelper=new SqliteHelper(context,DB_NAME, null, DB_VERSION); //获得当前数据库 db= dbHelper.getWritableDatabase(); } //关闭数据库 public void Close() { db.close(); dbHelper.close(); } //获取所有的RSS源信息 public List<String> GetChannelList() { List<String> ChannelList = new ArrayList<String>(); //获得数据表中的所有数据 Cursor cursor=db.query(SqliteHelper.TB_NAME, null, null, null, null, null, ID+" DESC"); //将游标移动到开始 cursor.moveToFirst(); //循环遍历整个数据库 while(!cursor.isAfterLast()&& (cursor.getString(1)!=null)){ //取得源标题信息 String channel=cursor.getString(1); //添加到数组 ChannelList.add(channel); //移动游标到下一个元素 cursor.moveToNext(); } cursor.close(); return ChannelList; } //通过url名称获得RSS源url地址 public String getUrlByChannel(String name) { Cursor cursor=db.query(SqliteHelper.TB_NAME, null, NAME+"=?", new String[]{name}, null, null, null); //将游标移动到开始 cursor.moveToFirst(); if(!cursor.isAfterLast()&& (cursor.getString(1)!=null)) return cursor.getString(2); return null; } //添加记录 public Long SaveChannelInfo(String name,String url) { ContentValues values = new ContentValues(); values.put(NAME, name); values.put(URL, url); //插入新纪录 Long id = db.insert(SqliteHelper.TB_NAME, null, values); Log.e("SaveChannelInfo",id+""); return id; } //删除指定channle的记录 public int DelChannelInfo(String name){ int id= db.delete(SqliteHelper.TB_NAME, NAME +"='"+name+"'", null); Log.e("DelChannelInfo",id+""); return id; } //数据表的列信息 static String ID="id"; static String NAME="name"; static String URL="url"; //数据库帮助类 class SqliteHelper extends SQLiteOpenHelper{ //用来保存 RSS频道的表名 public static final String TB_NAME="channel"; public SqliteHelper(Context context, String name, CursorFactory factory, int version) { super(context, name, factory, version); } //创建表 @Override public void onCreate(SQLiteDatabase db) { db.execSQL("CREATE TABLE IF NOT EXISTS "+ TB_NAME+"("+ ID+" integer primary key,"+ NAME+" varchar,"+ URL+" varchar"+ ")" ); Log.e("Database","onCreate"); } //更新表 @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { db.execSQL("DROP TABLE IF EXISTS " + TB_NAME); onCreate(db); Log.e("Database","onUpgrade"); } } }
RSSItem.java
package com.rss.data; //Rssitem信息,用于存放RSS的每一个item public class RssItem { public static final String TITLE = "title"; public static final String PUBDATE = "pubDate"; //标题 private String title; //详细内容 private String description; //链接 private String link; //来源 private String source; //日期 private String pubDate; //获得标题 public String getTitle() { 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 getSource() { return source; } //设置来源 public void setSource(String source) { this.source = source; } //取得日期 public String getPubDate() { return pubDate; } //设置日期 public void setPubDate(String pubDate) { this.pubDate = pubDate; } //转化成string public String toString() { if(title.length() > 20) { return title.substring(0, 42) + "..."; }else { return title; } } }
RssFeed.java
package com.rss.data; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Vector; public class RssFeed { //标题 private String title; //日期 private String pubdate; //数量 private int itemcount; //用于存放RSS信息的列表 private List<RssItem> itemlist; public RssFeed() { itemlist = new Vector<RssItem>(0); } //添加元素 public int addItem(RssItem item) { itemlist.add(item); itemcount++; return itemcount; } //取得元素 public RssItem getItem(int location) { return itemlist.get(location); } //取得所有列表需要的信息,存储到List public List getAllItemsForListView() { List<Map<String, Object>> data = new ArrayList<Map<String, Object>>(); int size = itemlist.size(); for(int i=0; i<size; i++) { HashMap<String, Object> item = new HashMap<String, Object>(); item.put(RssItem.TITLE, itemlist.get(i).getTitle()); item.put(RssItem.PUBDATE, itemlist.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; } //获得信息数组 public List<RssItem> getItemlist() { return itemlist; } //设置信息数组 public void setItemlist(List<RssItem> itemlist) { this.itemlist = itemlist; } }
4.选择频道
selectChannel.java
package com.rss.activity; import java.util.ArrayList; import java.util.List; import com.rss.data.ChannelDataHelper; import android.app.ListActivity; import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.view.View.OnClickListener; import android.widget.BaseAdapter; import android.widget.Button; import android.widget.LinearLayout; import android.widget.TextView; import android.widget.Toast; //RSS源选择界面 public class SelectChannel extends ListActivity{ //menu菜单的id private static final int MENU_ADD = Menu.FIRST; private static final int MENU_QUIT = MENU_ADD + 1; //RSS源适配器 ChannelAdapter mAdapter; //RSS源数据库类 ChannelDataHelper mChannel; //RSS源数组 List<String> channelList=new ArrayList<String>(); @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mChannel=new ChannelDataHelper(this); //取得数据库所有内容 channelList=mChannel.GetChannelList(); mAdapter=new ChannelAdapter(this); //数据库无内容 if(mAdapter.getCount() == 0) Toast.makeText(this, "尚未添加任何频道", Toast.LENGTH_SHORT).show(); setTitle("频道选择"); //设置适配器 setListAdapter(mAdapter); } //ListView是适配器 class ChannelAdapter extends BaseAdapter { private LayoutInflater mInflator; //构造函数 public ChannelAdapter(Context context) { this.mInflator = LayoutInflater.from(context); } //取得数组大小 public int getCount() { return channelList.size(); } //取得当前位置的元素 public String getItem(int position) { return channelList.get(position); } //取得当前位置的id public long getItemId(int position) { return 0; } //取得当前位置的视图 public View getView(int position, View convertView, ViewGroup parent) { ViewHolder vRss = null; //记录当前的位置 final int row = position; //初始化界面元素类 vRss = new ViewHolder(); //膨胀出界面 convertView = mInflator.inflate(R.layout.item, null); //取得界面元素 vRss.textLayout=(LinearLayout)convertView.findViewById(R.id.textLayout); vRss.channel = (TextView)convertView.findViewById(R.id.title); //设置标题字体大小 vRss.channel.setTextSize(25); vRss.delBtn = (Button)convertView.findViewById(R.id.del_btn); //取得标题的文本内容 String title = channelList.get(position); vRss.channel.setText(title); Log.e("guojs",channelList.get(row)); //设置按键检监听器 vRss.textLayout.setOnClickListener(new OnClickListener(){ @Override public void onClick(View v) { // TODO Auto-generated method stub String channelName=channelList.get(row); Intent it=new Intent(); Log.e("channel-url",mChannel.getUrlByChannel(channelName)); //传递当前点击RSS源对应的URL地址 it.putExtra("channel", mChannel.getUrlByChannel(channelName)); it.setClass(SelectChannel.this, ActivityMain.class); //启动显示当前RSS源对应信息的界面 startActivity(it); } }); //删除当前RSS源 vRss.delBtn.setOnClickListener(new OnClickListener() { public void onClick(View v) { delRssInfo(); } private void delRssInfo() { //删除成功 if(-1 != mChannel.DelChannelInfo(channelList.get(row))) { Toast.makeText(SelectChannel.this, "删除成功!", Toast.LENGTH_SHORT).show(); //移除数组元素 channelList.remove(row); //通知改变界面 mAdapter.notifyDataSetChanged(); //删除失败 }else{ Toast.makeText(SelectChannel.this, "删除失败!", Toast.LENGTH_SHORT).show(); } } }); return convertView; } } //每一行元素的界面元素组成 final class ViewHolder { public LinearLayout textLayout; public TextView channel; public Button delBtn; } //创建menu菜单 @Override public boolean onCreateOptionsMenu(Menu menu) { //添加RSS源 menu.add(0, MENU_ADD, 0, R.string.add_rss); //退出程序 menu.add(0,MENU_QUIT,1,R.string.rss_quit); return super.onCreateOptionsMenu(menu); } //为menu菜单按键绑定监听器 @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { //添加RSS源 case MENU_ADD: Intent intent = new Intent(); intent.setClass(SelectChannel.this, AddRss.class); startActivity(intent); return true; //退出程序 case MENU_QUIT: SelectChannel.this.finish(); default: break; } return super.onOptionsItemSelected(item); } }
5.添加频道
界面
add_rss_dialog.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <!-- 标题 --> <TextView android:id="@+id/show_title" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/title_show" /> <!-- RSS源地址 --> <EditText android:layout_marginTop="3dp" android:id="@+id/rss_add" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text=""/> <!-- 按键布局 --> <LinearLayout android:layout_marginTop="30dp" android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="wrap_content"> <!-- 验证按钮 --> <Button android:id="@+id/verify_rss" android:layout_width="80dp" android:layout_height="wrap_content" android:layout_marginLeft="5dp" android:text="@string/rss_verify" /> <!-- 添加按钮 --> <Button android:id="@+id/add_rss" android:layout_width="80dp" android:layout_height="wrap_content" android:layout_marginLeft="5dp" android:text="@string/rss_add" /> <!-- 退出程序 --> <Button android:id="@+id/quit_rss" android:layout_width="80dp" android:layout_height="wrap_content" android:layout_marginLeft="5dp" android:text="@string/rss_quit" /> </LinearLayout> </LinearLayout>
ADDRss.java
package com.rss.activity; import java.net.URL; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import org.xml.sax.Attributes; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.XMLReader; import org.xml.sax.helpers.DefaultHandler; import com.rss.data.ChannelDataHelper; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; import android.widget.Toast; import android.os.Handler; import android.os.Message; //RSS源添加界面 public class AddRss extends Activity { // 添加按钮 private Button addRss; // 检验按钮 private Button verifyRss; // 退出按钮 private Button quit; // RSS源地址 private EditText rssText; // RSS源数据库操作类 ChannelDataHelper mChannelData; Context mContext; Handler handler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case 0x123: Toast.makeText(mContext, "验证通过", Toast.LENGTH_SHORT).show(); break; case 0x234: Toast.makeText(mContext, "验证失败", Toast.LENGTH_SHORT).show(); break; } } }; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.add_rss_dialog); mContext = this; // 实例化RSS源数据库操作类 mChannelData = new ChannelDataHelper(this); // 初始化界面元素 addRss = (Button) findViewById(R.id.add_rss); verifyRss = (Button) findViewById(R.id.verify_rss); quit = (Button) findViewById(R.id.quit_rss); rssText = (EditText) findViewById(R.id.rss_add); // 设置按键监听器 addRss.setOnClickListener(clickListener); verifyRss.setOnClickListener(clickListener); quit.setOnClickListener(clickListener); } // 按键监听器 OnClickListener clickListener = new OnClickListener() { @Override public void onClick(View v) { switch (v.getId()) { // 添加按钮 case R.id.add_rss: saveRss(); break; // 检验地址 case R.id.verify_rss: verifyRss(rssText.getText().toString()); break; // 退出添加界面 case R.id.quit_rss: Intent it = new Intent(); it.setClass(AddRss.this, SelectChannel.class); // 进入RSS源选择界面 startActivity(it); AddRss.this.finish(); break; default: break; } } }; String rssAddress,rssName; // 保存RSS源 protected void saveRss() { //rssAddress = rssText.getText().toString().trim(); //rssName = "";//verifyRss(rssAddress); // RSS源地址正确并正确保存 if (rssName != null && rssName != "默认" && (-1 != mChannelData.SaveChannelInfo(rssName, rssAddress))) { Toast.makeText(mContext, "保存成功!", Toast.LENGTH_SHORT).show(); rssText.setText(""); } else { Toast.makeText(mContext, "保存失败!", Toast.LENGTH_SHORT).show(); } } // 验证RSS源地址的正确性,返回RSS源的标题 private void verifyRss(final String urlString) { new Thread() { public void run() { try { rssAddress = urlString; URL url = new URL(urlString); // 实例化SAX解析工厂类 SAXParserFactory factory = SAXParserFactory.newInstance(); // SAX解析器 SAXParser parser = factory.newSAXParser(); XMLReader xmlReader = parser.getXMLReader(); // SAX处理类 getRssChannel rssHandler = new getRssChannel(); xmlReader.setContentHandler(rssHandler); // 取得url网址内容 InputSource is = new InputSource(url.openStream()); // 解析url网址内容 xmlReader.parse(is); Log.e("channelName", rssHandler.getChannel()); rssName = rssHandler.getChannel(); if(rssName!="默认") { Message msg = new Message(); msg.what = 0x123; msg.obj = ""; handler.sendMessage(msg); } else { Message msg = new Message(); msg.what = 0x234; msg.obj = ""; handler.sendMessage(msg); } } catch (Exception e) { Log.e("channnelName", e.toString()); } } }.start(); } class getRssChannel extends DefaultHandler { // 标志位,用于表示RSS源的位置 int flag = 1; String channel = "默认"; public getRssChannel() { } // 返回channel信息 public String getChannel() { return channel; } // 文档开始 @Override public void startDocument() throws SAXException { } // 文档结尾 @Override public void endDocument() throws SAXException { super.endDocument(); } // 开始解析标签 @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { super.startElement(uri, localName, qName, attributes); if (localName.equals("channel")) { flag = 1; return; } // 一旦进入了item,则将标志为设置为0 if (localName.equals("item")) { flag = 0; return; } // 在item外面遇到title标签将标志位设置为2 if (flag == 1) { if (localName.equals("title")) { flag = 2; } } } // 标签结束 @Override public void endElement(String uri, String localName, String qName) throws SAXException { } // 解析标签内容 @Override public void characters(char[] ch, int start, int length) throws SAXException { if (length <= 5) return; String theString = new String(ch, start, length); // 当标志位为2表明当前正在 解析RSS源标题的标签 if (flag == 2) { // 保存RSS源标题 Log.e("channel", theString); channel = theString; flag = 0; } } } }
6.RSS数据处理,SAX
RssHandler.java
package com.rss.sax; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.ext.DefaultHandler2; import org.xml.sax.helpers.DefaultHandler; import android.util.Log; import com.rss.data.RssFeed; import com.rss.data.RssItem; //RSS数据SAX解析 public class RssHandler extends DefaultHandler { RssFeed rssFeed; RssItem rssItem; private static boolean a = false; String lastElementName = ""; final int RSS_TITLE = 1; final int RSS_LINK = 2; final int RSS_DESCRIPTION = 3; final int RSS_PUBDATE = 5; int currentstate = 0; public RssHandler() { } //返回rssFeed形式的信息 public RssFeed getFeed() { return rssFeed; } //开始解析文档 public void startDocument()throws SAXException { System.out.println("startDocument"); //实例化RssFeed类和RssItem类 rssFeed = new RssFeed(); rssItem = new RssItem(); } //文档结束 @Override public void endDocument() throws SAXException { super.endDocument(); } //开始解析标签 @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { super.startElement(uri, localName, qName, attributes); //channel标签 if(localName.equals("channel")) { currentstate = 0; return; } //item标签 if(localName.equals("item")) { rssItem = new RssItem(); return; } //title标签 if(localName.equals("title")) { currentstate = RSS_TITLE; return; } //详细信息标签 if(localName.equals("description")) { //跳过第一次遇到的description标签 if(a == true) { currentstate = RSS_DESCRIPTION; return; } else { a = true; return; } } //链接 if(localName.equals("link")) { currentstate = RSS_LINK; return; } //日期 if(localName.equals("pubDate")) { currentstate = RSS_PUBDATE; return; } currentstate = 0; } //标签结束 @Override public void endElement(String uri, String localName, String qName) throws SAXException { //将信息添加到rssFeed中 if(localName.equals("item")) { rssFeed.addItem(rssItem); return; } } //解析标签间的文本 @Override public void characters(char[] ch, int start, int length) throws SAXException { if(length <= 5) return ; String theString = new String(ch, start, length); switch (currentstate) { //标题 case RSS_TITLE: rssItem.setTitle(theString); Log.e("title",theString); currentstate = 0; break; //链接 case RSS_LINK: rssItem.setLink(theString); currentstate = 0; break; //详细信息 case RSS_DESCRIPTION: System.out.println("RSS_DESCRIPTION=" + theString); if(a == true) { rssItem.setDescription(theString); currentstate = 0; }else { a = true; } break; //日期 case RSS_PUBDATE: rssItem.setPubDate(theString); currentstate = 0; break; default: return; } } }
7.查看
item.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="fill_parent" > <!-- 文本区域 --> <LinearLayout android:id="@+id/textLayout" android:orientation="vertical" android:layout_width="270dp" android:layout_height="fill_parent"> <!-- 标题 --> <TextView android:id="@+id/title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="#FFFFFFFF" android:textSize="15dp" /> <!-- 日期 --> <TextView android:id="@+id/pubdate" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="#FFFFFFFF" android:textSize="10dp" /> </LinearLayout> <!--删除按键 --> <Button android:id="@+id/del_btn" android:layout_width="50dp" android:layout_height="wrap_content" android:text="删除" android:layout_gravity="right" /> </LinearLayout>
ActivityMain.java
package com.rss.activity; import java.net.URL; import java.util.List; import java.util.Map; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import org.xml.sax.InputSource; import org.xml.sax.XMLReader; import android.app.ListActivity; import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.Button; import android.widget.LinearLayout; import android.widget.TextView; import com.rss.data.RssFeed; import com.rss.sax.RssHandler; import android.os.Handler; import android.os.Message; //RSS文本解析 public class ActivityMain extends ListActivity { // RSS源地址 public String RSS_URL = ""; public final String TAG = "RssReader"; // RSS信息类 private RssFeed feed; // private List<Map<String, Object>> mList; Handler handler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case 0x123: feed = (RssFeed) msg.obj; // 将RSS信息显示到列表中 showListView(); break; } } }; // 初始化函数 @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Bundle b = getIntent().getExtras(); // 取得RSS地址 RSS_URL = b.getString("channel"); Log.e("guojs-->get url", RSS_URL); // 取得对应RSS源地址的信息 getFeed(RSS_URL); } // 取得对应RSS源地址的信息 private void getFeed(final String urlString) { new Thread() { public void run() { try { URL url = new URL(urlString); // 采用SAX解析 SAXParserFactory factory = SAXParserFactory.newInstance(); SAXParser parser = factory.newSAXParser(); XMLReader xmlReader = parser.getXMLReader(); // SAX解析类 RssHandler rssHandler = new RssHandler(); xmlReader.setContentHandler(rssHandler); // 取得网页信息 InputSource is = new InputSource(url.openStream()); // 解析网页内容 xmlReader.parse(is); Message msg = new Message(); msg.what = 0x123; msg.obj = rssHandler.getFeed(); handler.sendMessage(msg); } catch (Exception e) { e.printStackTrace(); } } }.start(); } // 显示RSS信息到列表中 @SuppressWarnings("unchecked") private void showListView() { if (feed == null) { setTitle("RSS阅读器"); return; } // 取得RSS信息数组 mList = feed.getAllItemsForListView(); MyAdapter adapter = new MyAdapter(this); // 设置适配器 setListAdapter(adapter); setSelection(0); } // 新建数据适配器类 class MyAdapter extends BaseAdapter { private LayoutInflater mInflator; // 构造函数 public MyAdapter(Context context) { this.mInflator = LayoutInflater.from(context); } // 取得列表数量 public int getCount() { System.out.println("mList.size()=" + mList.size()); return mList.size(); } public Object getItem(int position) { return null; } // 取得item的id public long getItemId(int position) { return 0; } // 取得每一行元素的视图 public View getView(int position, View convertView, ViewGroup parent) { ViewRss vRss = null; final int row = position; // 实例化界面元素类 vRss = new ViewRss(); // 膨胀出界面元素的视图 convertView = mInflator.inflate(R.layout.item, null); // 初始化界面元素 vRss.mLayout = (LinearLayout) convertView .findViewById(R.id.textLayout); vRss.title = (TextView) convertView.findViewById(R.id.title); vRss.pubdate = (TextView) convertView.findViewById(R.id.pubdate); vRss.delBtn = (Button) convertView.findViewById(R.id.del_btn); // 设置删除按钮不可见 vRss.delBtn.setVisibility(View.INVISIBLE); convertView.setTag(vRss); // 取得日期 String pubDate = (String) mList.get(position).get("pubDate"); // 取得标题 String title = (String) mList.get(position).get("title"); // 设置标题 vRss.title.setText(title); // 设置日期 vRss.pubdate.setText(pubDate); // 为textLayout设置按键监听器 vRss.mLayout.setOnClickListener(new OnClickListener() { public void onClick(View v) { Intent intent = new Intent(ActivityMain.this, ActivityShowDescription.class); Bundle b = new Bundle(); // 绑定数据 b.putString("title", feed.getItem(row).getTitle()); b.putString("description", feed.getItem(row) .getDescription()); b.putString("link", feed.getItem(row).getLink()); b.putString("pubdate", feed.getItem(row).getPubDate()); intent.putExtra("com.rss.data.RssFeed", b); // 启动查看RSS详细信息界面 startActivity(intent); } }); return convertView; } } // RSS界面元素类,用于存放RSS界面元素 public final class ViewRss { public LinearLayout mLayout; // 标题 public TextView title; // 日期 public TextView pubdate; // 删除按键 public Button delBtn; } }
showDescriptionActivity.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <WebView android:id="@+id/content" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1.0" /> <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <Button android:layout_width="100dp" android:layout_height="wrap_content" android:layout_marginLeft="50dp" android:text="收藏" android:id="@+id/store" /> <Button android:layout_width="100dp" android:layout_height="wrap_content" android:layout_marginRight="50dp" android:text="返回" android:id="@+id/back" /> </LinearLayout> </LinearLayout>
ActivityShowDescription.java
package com.rss.activity; import com.rss.db.RssProvider; import android.app.Activity; import android.content.ContentResolver; import android.content.ContentValues; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.webkit.WebView; import android.widget.Button; import android.widget.Toast; //RSS详细信息显示 public class ActivityShowDescription extends Activity { //标题 private String title = null; //日期 private String pubdate = null; //详细信息 private String description = null; //链接 private String link = null; //初始化函数 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.showdescription); String content = null; Intent intent = getIntent(); //取得intent携带的信息 if(intent != null) { Bundle bundle = intent.getBundleExtra("com.rss.data.RssFeed"); title = bundle.getString("title"); pubdate = bundle.getString("pubdate"); description = bundle.getString("description"); if(description== null) description=""; link = bundle.getString("link"); content ="内容:<br />" + description.replace('\n', ' ') + "<br /><br />链接:\n<a href=\"" + link +"\">"+link+"</a>" + "<br /><br />日期: " + pubdate; }else { content = "error!"; } //设置当前界面的标题 ActivityShowDescription.this.setTitle(title); //初始化页面元素 WebView textView = (WebView)findViewById(R.id.content); //将content显示到网页中 textView.loadDataWithBaseURL("",content, "text/html", "UTF-8",""); Button backButton = (Button)findViewById(R.id.back); Button storeButton = (Button)findViewById(R.id.store); //为按键绑定监听器 storeButton.setOnClickListener(new OnClickListener() { public void onClick(View v) { //保存RSS数据到数据库中 storeDataRss(); Toast.makeText(ActivityShowDescription.this, "收藏成功!", Toast.LENGTH_LONG).show(); } }); backButton.setOnClickListener(new OnClickListener() { //关闭当前页面 public void onClick(View v) { ActivityShowDescription.this.finish(); } }); } //保存RSS数据到数据库中 protected void storeDataRss() { ContentResolver cr = getContentResolver(); ContentValues values = new ContentValues(); values.put(RssProvider.RSS_TITLE, title); values.put(RssProvider.RSS_DESCRIPTION, description); values.put(RssProvider.RSS_PUBDATE, pubdate); values.put(RssProvider.RSS_LINK, link); cr.insert(RssProvider.RSS_URI, values); } }
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.rss.activity" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="10" /> <uses-permission android:name="android.permission.INTERNET" > </uses-permission> <application android:icon="@drawable/icon" android:label="@string/app_name" > <activity android:name=".LoginActivity" android:label="@string/login" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".ActivityMain" android:label="@string/app_name" > </activity> <activity android:name=".SelectChannel" > </activity> <activity android:name=".ActivityShowDescription" > </activity> <activity android:name=".AddRss" > </activity> <provider android:name="com.rss.db.RssProvider" android:authorities="com.rss.activity" /> </application> </manifest>
strings.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="hello">Hello World, ActivityMain!</string> <string name="app_name">RSS阅读器</string> <string name="login">登入RSS阅读器</string> <string name="logining">正在进入中....</string> <string name="login_in">进入RSS阅读器</string> <string name="add_rss">添加RSS源</string> <string name="add_rss_address">添加XML源地址</string> <string name="rss_add">添加</string> <string name="rss_verify">检验</string> <string name="rss_quit">退出</string> <string name="rss_browser">浏览器</string> <string name="title_show">请输入要添加的Rss源:</string> </resources>