RSS新闻阅读器
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>
RSS新闻阅读器的更多相关文章
- 五个最佳RSS新闻阅读器
文章出自http://www.williamlong.info/archives/1591.html 在博客和在线新闻充斥的互联网上,大量信息已经使得用户阅读量过载,幸运的是,通过RSS Feed提供 ...
- (android高仿系列)今日头条 --新闻阅读器 (三) 完结 、总结 篇
从写第一篇今日头条高仿系列开始,到现在已经过去了1个多月了,其实大体都做好了,就是迟迟没有放出来,因为我觉得,做这个东西也是有个过程的,我想把这个模仿中一步一步学习的过程,按照自己的思路写下来,在根据 ...
- jQuery Mobile发展新闻阅读器,适应iphone和android打电话
程序猿是很不赖,你知道. 我们经常新浪,腾讯.雅虎等各大网站看到上述新闻.他们还推出了自己的移动新闻阅读器.今天,我自己用的jQuery Mobile 为了实现这一功能,.图像大小上传限制的大小250 ...
- (android高仿系列)今日头条 --新闻阅读器 (二)
高仿今日头条 --- 第一篇:(android高仿系列)今日头条 --新闻阅读器 (一) 上次,已经完毕了头部新闻分类栏目的拖动效果. 这篇文章是继续去完好APP 今日头条 这个新闻阅读器的其 ...
- jQuery Mobile开发的新闻阅读器,适应iphone和android手机
程序猿都非常赖.你懂的! 我们常常上新浪,腾讯.雅虎等各大站点上面看新闻.他们也都各自推出了自家的手机新闻阅读器.今天我自己使用jQuery Mobile 来实现这一功能.图片大小上传限制了大小250 ...
- Android 仿 新闻阅读器 菜单弹出效果(附源码DEMO)
这一系列博文都是:(android高仿系列)今日头条 --新闻阅读器 (一) 开发中碰到问题之后实现的,觉得可能有的开发者用的到或则希望独立成一个小功能DEMO,所以就放出来这么一个DEMO. 原本觉 ...
- 手机新闻网站,手持移动新闻,手机报client,jQuery Mobile手机新闻网站,手机新闻网站demo,新闻阅读器开发
我们坐在地铁.经常拿出新浪手机查看新闻.腾讯新闻,或者看新闻,等刷微信功能.你有没有想过如何实现这些目标. 移动互联网.更活泼. 由于HTML5未来,jQuery Moblie未来. 今天我用jqm的 ...
- 手机新闻网站,掌上移动新闻,手机报client,jQuery Mobile手机新闻网站,手机新闻网站demo,新闻阅读器开发
我们坐在地铁,经常来查看新浪手机新闻,腾讯新闻.或者刷微信看新闻更多功能.你有没有想过如何实现这些目标.移动互联网,更活泼. 因为HTML5到,jQuery Moblie到.今天我用jqm为了给你一个 ...
- (android高仿系列)今日头条 --新闻阅读器 (转载)
非常不错,原文地址:http://blog.csdn.net/vipzjyno1/article/details/26514543
随机推荐
- Spring事务配置的五种方式 巨全!不看后悔,一看必懂!
前段时间对Spring的事务配置做了比较深入的研究,在此之间对Spring的事务配置虽说也配置过,但是一直没有一个清楚的认识.通过这次的学习发觉Spring的事务配置只要把思路理清,还是比较好掌握的. ...
- Java 判断一段网络资源是否存在
package cn.ycmedia.common.utils; import java.io.InputStream; import java.net.URL; import java.net.UR ...
- XMPPFrameWork IOS 开发(二)- xcode配置
原始地址:XMPPFrameWork IOS 开发(二) 译文地址: Getting started using XMPPFramework on iOS 介绍 ios上的XMPPFramewor ...
- Android---用动画来处理布局的变化
本文译自:http://developer.android.com/training/animation/layout.html 布局动画一种系统预装的动画,每次布局配置发生变化时,系统会运行它.你所 ...
- 案例:计算1!+2!+3!+......+n!
/* * 1!+2!+3!+......+n! * */ import java.util.Scanner; public class ForTest{ public static void main ...
- 挖掘微信Web版通信的全过程
昨天是周末,在家闲得无聊,于是去weiphone.com逛了一圈,偶然发现有人发了一帖叫<微信 for Mac>,这勾起了我的好奇心,国内做Mac开发的人确实很少,对于那些能够独自开发一些 ...
- win10的独立存储
win10的独立存储和win8的大致相同 Windows.Storage.ApplicationDataContainer roamingSettings = Windows.Storage.Appl ...
- jquery的ajax方法:ajaxStart()和ajaxStop()
ajaxStart()方法: 当AJAX请求开始时,显示加载中的提示. $("#divMessage").ajaxStart(function(){ $(this).show(); ...
- 获取Html中所有img的src
/// <summary> /// 获取所有Img中的Src /// </summary> /// <param name="htmlText"> ...
- 导入excel错误:外部表不是预期的格式 解决方案(Oledb)
-----转载:http://blog.csdn.net/zhou349398998/article/details/8740424 环境:win7+iis7+Office2007 在asp.net网 ...