这篇博文前天就想写了,最近发生了很多事,而且我确实心里比较浮躁,没在状态上,因此就一直拖着.今天上午起来看看时间,都快中秋了.哎,想想时间过的还真是快.自己先前计划的在8月底的时候做出来几个小东西,到现在才做出来一个,惭愧啊.算了,不多说了.一边写博文,一边等待聘用通知吧.
做android下的Rss阅读器,其实最核心的功能,并不是多难.先前我在博文上就已经贴出来rss核心解析的代码.
一.先说说我做这个android rss阅读器的思路吧.
1.界面部分:
在顶部是一个spinner,在这个地方可以选择rss的源.底下紧跟着的是一个listview,用来显示rss源中读取出来的新闻标题.
2.相关功能:
1.要能手动更新rss新闻.更新rss新闻时,会根据spinner处选择的rss源的不同来更新出不同的结果.
2.点击列表中的一条新闻,能打开对应的网页以方便使用者能查看具体的新闻
3.功能菜单
1.一个退出菜单,用来退出整个应用程序,这个是必须的
2.一个更新新闻菜单,用来加载最新rss新闻
3.一个关于菜单,用来挂广告的(呃,现在我还没考虑赚钱,先挂一个自我介绍的广告得了)
二.实现过程
1.rss解析
rss解析部分先前就已经实现了.只不过当时是做的一个java版本的没有界面的一个rss解析器,还不能称为阅读器
2.界面实现
在主界面的布局文件上:
定义了一个spinner和listview元素
1: <?xml version="1.0" encoding="utf-8"?>
2: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3: android:orientation="vertical" android:layout_width="fill_parent"
4: android:layout_height="fill_parent">
5: <TextView android:layout_width="fill_parent"
6: android:layout_height="wrap_content" android:text="@string/selectTip" />
7: <Spinner android:id="@+id/rssSourceSpinner"
8: android:layout_width="fill_parent" android:layout_height="wrap_content" />
9: <LinearLayout android:id="@+id/list_ll"
10: android:layout_width="fill_parent" android:layout_height="fill_parent">
11: <ListView android:id="@+id/android:list" android:layout_width="fill_parent"
12: android:layout_height="wrap_content" />
13: </LinearLayout>
14: </LinearLayout>
同时在另外一个布局文件中定义了listview中的每行的元素的格式布局
1: <?xml version="1.0" encoding="utf-8"?>
2: <TextView xmlns:android="http://schemas.android.com/apk/res/android"
3: android:id="@+id/title" android:layout_width="wrap_content"
4: android:layout_height="wrap_content"/>
3.菜单布置
菜单实现上,专门在res下建立了menu文件夹,在其下创建menu.xml,里面定义了三个菜单元素,分别对应着更新rss新闻,关于和退出
1: <?xml version="1.0" encoding="UTF-8"?>
2: <menu xmlns:android="http://schemas.android.com/apk/res/android">
3: <item android:id="@+id/refresh" android:title="更新新闻"></item>
4: <item android:id="@+id/about" android:title="关于"></item>
5: <item android:id="@+id/exit" android:title="退出"></item>
6: </menu>
4.前后端交互部分实现
1: package com.leipei.android;
2:
3: import java.util.ArrayList;
4: import java.util.List;
5:
6: import com.leipei.rss.Message;
7: import com.leipei.rss.RssSaxParser;
8:
9: import android.app.AlertDialog;
10: import android.app.ListActivity;
11: import android.content.DialogInterface;
12: import android.content.DialogInterface.OnClickListener;
13: import android.content.Intent;
14: import android.net.Uri;
15: import android.os.Bundle;
16: import android.view.Gravity;
17: import android.view.Menu;
18: import android.view.MenuInflater;
19: import android.view.MenuItem;
20: import android.view.View;
21: import android.widget.AdapterView;
22: import android.widget.AdapterView.OnItemSelectedListener;
23: import android.widget.ArrayAdapter;
24: import android.widget.ListView;
25: import android.widget.Spinner;
26: import android.widget.Toast;
27:
28: public class RssMainActivity extends ListActivity {
29:
30: private Spinner rssSelectSpinner;
31: private String[] rssurlarray;
32: private String currentRssurl;
33: private List<Message> messages;
34:
35: /** Called when the activity is first created. */
36: @Override
37: public void onCreate(Bundle savedInstanceState) {
38: super.onCreate(savedInstanceState);
39: setContentView(R.layout.main);
40: rssSelectSpinner = (Spinner) findViewById(R.id.rssSourceSpinner);
41: loadSpinner();
42: initRssUrlArray();
43: }
44:
45: /*
46: * 初始化Rss数据源的url数组 从先前定义好的rss源的xml文件中获取rss源的名称
47: */
48: public void initRssUrlArray() {
49: this.rssurlarray = getResources().getStringArray(R.array.source_url);
50: }
51:
52: /*
53: * 初始化rss源的下拉列表
54: */
55: public void loadSpinner() {
56: ArrayAdapter<CharSequence> spinnerAdapter = ArrayAdapter
57: .createFromResource(this, R.array.source_title,
58: R.layout.newstitle);
59: spinnerAdapter
60: .setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
61: rssSelectSpinner.setAdapter(spinnerAdapter);
62: rssSelectSpinner
63: .setOnItemSelectedListener(new OnItemSelectedListener() {
64:
65: public void onItemSelected(AdapterView<?> parent,
66: View view, int pos, long id) {
67: parent.setVisibility(View.VISIBLE);
68: RssMainActivity.this.currentRssurl = RssMainActivity.this.rssurlarray[pos];
69: }
70:
71: public void onNothingSelected(AdapterView parent) {
72: // Do nothing.
73: }
74: });
75: }
76:
77: /*
78: * (non-Javadoc)
79: *
80: * @see android.app.Activity#onCreateOptionsMenu(android.view.Menu)
81: * 初期只做三个菜单项,分别是更新rss,关于和退出
82: */
83: @Override
84: public boolean onCreateOptionsMenu(Menu menu) {
85: MenuInflater inflater = getMenuInflater();
86: inflater.inflate(R.menu.menu, menu);
87: return true;
88: }
89:
90: @Override
91: public boolean onOptionsItemSelected(MenuItem item) {
92: int item_id = item.getItemId();
93: switch (item_id) {
94: // 如果是点击了更新菜单,则重新加载一个rss新闻
95: case R.id.refresh:
96: this.loadRss();
97: break;
98: // 如果是点击了关于菜单,则弹出对话框,在其中显示一些关于我的信息,初期不挂赢利性广告
99: case R.id.about:
100: AlertDialog.Builder aboutDialog = new AlertDialog.Builder(this);
101: aboutDialog.setTitle(R.string.aboutme);
102: aboutDialog.setMessage(R.string.about_info);
103: aboutDialog.setPositiveButton("确定", new OnClickListener() {
104:
105: @Override
106: public void onClick(DialogInterface dialog, int which) {
107: dialog.dismiss();
108: }
109: });
110: aboutDialog.create().show();
111: break;
112: // 如果点击的是退出菜单,则退出Activity,由于整个应用程序只有一个Activity,则退出了应用程序
113: case R.id.exit:
114: this.finish();
115: break;
116: }
117: return true;
118: }
119:
120: /*
121: * 根据现在选中的spinner来加载对应的新闻
122: */
123: public void loadRss() {
124: if (this.currentRssurl == null) {
125: showTips("chose a rss url first!");
126: } else {
127: RssSaxParser rssparser = new RssSaxParser(this.currentRssurl);
128: System.out.println(this.currentRssurl);
129: this.messages = rssparser.parse();
130:
131: System.out.println("messages.size()" + this.messages.size());
132: List<String> titles = new ArrayList<String>(this.messages.size());
133: for (Message msg : this.messages) {
134: titles.add(msg.getTitle());
135: }
136: ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
137: R.layout.newstitle, titles);
138: this.setListAdapter(adapter);
139: }
140: }
141:
142: /*
143: * 显示一些提示信息
144: */
145: public void showTips(String tip) {
146: Toast toast = Toast.makeText(this, tip, Toast.LENGTH_SHORT);
147: toast.setGravity(Gravity.CENTER, 0, 10);
148: toast.show();
149: }
150:
151: /*
152: * (non-Javadoc)
153: *
154: * @see android.app.ListActivity#onListItemClick(android.widget.ListView,
155: * android.view.View, int, long)
156: * 重写ListActivity的方法,当listview中的某条新闻被点击选中,则打开对应新闻的url链接
157: */
158: @Override
159: protected void onListItemClick(ListView l, View v, int position, long id) {
160: super.onListItemClick(l, v, position, id);
161: Intent viewMessage = new Intent(Intent.ACTION_VIEW,
162: Uri.parse(this.messages.get(position).getLink()
163: .toExternalForm()));
164: this.startActivity(viewMessage);
165: }
166: }
三.一些补充
1.rss解析的额外改动
现在需要注意的是,因为android虚拟机的默认支持的编码和我本机的不一样,导致这样一个结果:
1: SAXParser parser = factory.newSAXParser();
2: RssHandler myxmlhandler = new RssHandler();
3: parser.parse(this.rssurl, myxmlhandler);
1: URL url=new URL(this.rssurl);
2: InputStream inputStream=url.openStream();
3: Charset charset = Charset.forName("GBK"); // 在此处声明GBK方式
4: Reader r = new InputStreamReader(inputStream, charset);
5: InputSource source = new InputSource(r);
6: parser.parse(source,myxmlhandler);
7: inputStream.close();