安卓开发日记1——虫虫新闻

时间:2022-05-23 20:39:29

一.应用背景

21世纪是信息时代,每天信息量巨大。特别是网络信息每天都铺天盖地。但是,无疑每个人都具有自己的兴趣点,而关注信息时也只会选择自己感兴趣的信息。但是不可避免地,人们就需要每天花费一定的时间去对信息进行筛选。另外,有些信息还具有时效性,在一定的时间内获取信息具有很大价值,但是错过这个时间可能就失去价值了。因此可以得出结论,一款能够帮助人筛选信息的应用能够对人们产生很大的帮助,具有一定的开发价值。


二.功能定位

本应用主要功能使能够帮助人筛选新闻,并在有新的新闻时提醒用户查看。




三.应用简介

应用名称:虫虫新闻


应用功能:根据用户给出的网页关键字信息帮助用户筛选新闻,并给予提醒。


应用开发平台:安卓平台


应用logo: 
安卓开发日记1——虫虫新闻

使用介绍: 
1.首先用户需要设置自己想要监视的网页的网址,以及自己感兴趣的新闻中包含的关键字,比如说用户对出国交流感兴趣,那么用户就可以设置交流为关键字,虫虫新闻只会爬取具有该关键字的新闻而不会爬取相关新闻,这一点需要注意,比如如果设置了关键字为出国交流,那么如果新闻中只出现了交流,如果出现了对外交流,那么虫虫新闻是不会捕捉该条新闻的,这一点需要注意。
2.另外用户可以设置爬虫运行的周期,比如如果设置了周期为8小时,那么虫虫新闻每过8小时会查看一次网页。另外每次打开虫虫新闻或者点击主界面的刷新时,也会运行一次爬虫程序。
3.虫虫新闻开机会自动后台运行,如果不希望这样。可以在系统中设置。
使用注意:在输入地址时需要把完整地址输入,包括最后的/。






四.程序架构

虫虫新闻几个主要功能模块为,1.记录保存用户的配置信息。2.根据用户的设置信息从网站捕捉相关信息并在本地呈现。3.在有新的信息时给予用户提醒。4.与用户交互的UI设计实现。下面是程序架构图。

安卓开发日记1——虫虫新闻
 




五.实现技术分析

虫虫新闻在实现上没有大的技术难点,下面将选择几个实现要点进行分析。

1.保存配置信息

虫虫新闻需要保存两类信息,分别是用户设置的爬虫捕捉新闻周期和设置的网址和关键字信息。关于爬虫周期,因为信息量比较小,所以可以使用sharedPreferes类进行保存。具体的类库为
android.content.SharedPreferences;
在使用时主要使用了以下几个类函数。

 
 
sharedPreferences=this.getSharedPreferences("SP",MODE_WORLD_READABLE);//取得该应用的名为”SP”的sharedPreferences的类对象。
intPeriod=sharedPreferences.getInt("PERIOD", 1);
//获得该sharedpreferences对象中的名为PERIOD的Int类型内容。默认值为1
editor=sharedPreferences.edit();
//获得对该对象进行操作的editor对象。
editor.putInt("PERIOD",intPeriod );
editor.commit();
//使用editor对象对sharedpreferes进行写操作。
 
而对于设置的网址和关键字信息,因为信息量相对较大,且不确定具体数量,所以,这里选择使用文件来保存这些信息。这里选择操作的文件位置为/data/data中的相对应于该应用的packet中的文件。
为了进行文件操作,这里需要引入以下类库。
java.io.FileInputStream;
java.io.FileOutputStream;
在使用时的主要方法如下。

写文件。

FileOutputStream fos= this.openFileOutput("Preferences.txt", MODE_WORLD_READABLE+MODE_APPEND);
//采用追加形式打开Preferences.txt的文件输出流。
fos.write(buff);
//将buff数组中的数据写入文件
fos.flush();
//确认写入提交,这时写入的内容会正式从缓冲区被写入文件。

读文件

 
FileInputStream fis= openFileInput("Preferences.txt");
//打开文件输入流
fis.read(buffer);
//从文件中读取数据到buffer数组中,读取的长度为buffer数组的length

2.定时爬虫的实现

这里的爬虫需要具备以下几项能力。
从配置文件中读取用户保存的配置信息。
根据配置信息从网站下载新闻。
定时开始运行爬虫线程。
根据以上的功能,爬虫有以下一个技术要点。

1)为了让爬虫定时执行,这里需要使用Timer类。
需要引入java.util.Timer; java.util.TimerTask;这两个类库。
具体的设置定时线程的代码如下:

new Timer().schedule(new TimerTask() {
//创建一个schedule类,并使用schedule安排一个定时线程,也就是TimerTask类
@Override
public void run() {
CrawlerAsy c = new CrawlerAsy();
//创建爬虫线程对象
c.execute("");
//开始执行爬虫线程
Log.i("in crawler","crawler done");
}
}, 0,period);

2)根据配置网页地址获得网页内容
为了进行网页操作,需要引入
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
这几个关键的类库。
具体的操作网页操作代码如下。

 
HttpClient hc = new DefaultHttpClient();
//HttpClient负责执行http请求
HttpGet request = new HttpGet(url);
//HttpGet包含了请求内容
HttpResponse hr;
//HttpReponse包含了请求结果
hr= hc.execute(request);
InputStream is=hr.getEntity().getContent();
ByteArrayOutputStream b = new ByteArrayOutputStream();
byte [] htmlData = b.toByteArray();
//………………….这里省略了从inputStream读取数据到ByteArrayOutputStream的过程。
content=new String(htmlData,0,htmlData.length,"GBK");
//以GBK编码方式获得网页文本

3)捕捉相关新闻信息
为了从下载的网页文本中捕捉与关键字相关的网页信息。这里需要使用引入
import java.util.regex.Matcher;
import java.util.regex.Pattern;
这两个正则表达式相关的库。

 
str = "href=\"(.+?)\".+>(.*?)"+keyWord.get(i)+"(.*?)<";
//str为正则表达式字符串
Pattern pattern = Pattern.compile(str);
//编译正则表达式
Matcher matcher = pattern.matcher(content);
//获取正则表达式匹配对象,其中包含了需要匹配的内容
newInformation.urlString=matcher.group(1);
//使用正则表达式进行匹配
newInformation.newsTitle=matcher.group(2)
+keyWord.get(i)+matcher.group(3);



4)爬虫操作线程
因为网页操作是阻塞操作,所以不能在主线程中进行,所以这里所有的网页操作都要放到AnyscTask中进行。
需要引入库import android.os.AsyncTask;然后新建一个extends asyncTask的类。

 
public class CrawlerAsy extends AsyncTask<String,Integer, String>{
//新建extends asynctask的类
@Override
protected String doInBackground(String... params) {
//重写doInBackground类方法
ArrayList<NewsInformation> news=new ArrayList<NewsInformation>();
news = theCrawler();
//开始文件操作,将爬取到的新闻放入文件中
if(news!=null){
writeFile(news);
}
return null;
}


2. 提醒用户功能实现

为了实现提醒用户的功能,需要使用notification的方法。需要引入以下两个类库
import android.app.Notification;
import android.app.NotificationManager;

NotificationManager
nManager=(NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
//创建通知栏管理类对象
int icon=R.drawable.my_launcher;
CharSequence textSequence="虫虫又有新新闻了!";
long when = System.currentTimeMillis();
Notification notification= new Notification(icon,textSequence,when);
//创建通知栏通知消息对象
PendingIntent pendingIntent= PendingIntent.getActivity(CrawlerThread.this, 0, new Intent(CrawlerThread.this,MainInterface.class), 0);
//创建当点击通知时跳转intent
notification.setLatestEventInfo(getApplicationContext(), "虫虫新闻", "虫虫又有新新闻了", pendingIntent);
//设置点击事件
notification.flags=Notification.FLAG_AUTO_CANCEL;
notification.defaults= Notification.DEFAULT_SOUND;
nManager.notify(0,notification);
//将通知放到通知栏第一个的位置




3.开机运行service

虫虫新闻具有实时性特点,所以需要在开机后就开启服务后台工作。为了实现这一功能,需要使用BroadcastReceiver接受广播。
 
public class BootReceiver extends BroadcastReceiver{


@Override
public void onReceive(Context context, Intent intent) {
Intent newIntent = new Intent(context,CrawlerThread.class);
context.startService(newIntent);
//开启服务
}


}


Android manifest中完成注册。
 
<receiver android:name="com.tanglikang.crawlernews.BootReceiver">
<intent-filter >
<action android:name="android.intent.action.BOOT_COMPLETED"/>
//接受广播为系统开机启动完成后发出的广播。
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</receiver>




4. 呈现新闻

本应用选择使用外部浏览器浏览新闻,为了实现点击新闻时调用外部浏览器,需要使用
import android.net.Uri;
类库。

 

String url = n.urlString;
Uri uri=Uri.parse(url);//在uri对象中绑定网址信息
Intent i = new Intent(Intent.ACTION_VIEW,uri);
startActivity(i);
//开启外部浏览器activity


六.测试

经过测试,本应用能够支持绝大多数校外网站。
能够支持包括计算机院网在内的大多数内网。

七.应用缺陷

不支持登陆功能,所以对于人人网等需要登陆的网站无法支持。


八.开发作者

汤利康
浙江大学计算机学院计算机技术与科学专业