手机天气预报系统毕业设计
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
目录
摘
要 ................................................................................................................................................. 1 需求分
析 ........................................................................................................................................ 2 一、开发背
景 ............................................................................................................................... 2 二、项目需求分
析 ....................................................................................................................... 2 总体设
计 ........................................................................................................................................ 2 一、系统规
划 ............................................................................................................................... 2 二、系统功能界
面 ....................................................................................................................... 3 1. 设置预报城市界面: ..................................................................................................... 3 2.天气显示界面: ............................................................................................................ 4 3.Widget 桌面小部件界面: ............................................................................................. 5 三.设计目标 ............................................................................................................................... 6 系统设
计 ........................................................................................................................................ 6 一、开发及运行环
境 ................................................................................................................... 6 二、数据库设
计 ........................................................................................................................... 6 三、主要方法及步
骤 ................................................................................................................... 7 四、主要方法及技
术 ................................................................................................................... 7 主要模
块 ........................................................................................................................................ 7 一、项目框
架 ............................................................................................................................... 7 二、主要功能实
现 ....................................................................................................................... 8 1.获取城市码db_weather.db 数据库文件 .......................................................................... 8 2.实现可伸缩性列表的的构建与过
滤 ............................................................................... 12 3.GPS 定位功能的实
现 ..................................................................................................... 15 4.Widget 窗体小部件的更新 ............................................................................................ 18 功能测试 ...................................................................................................................................... 19 结
论
(23)
摘要
Window操作系统的诞生成就了微软帝国,同时也造就了PC时代的繁荣,
然而如今,以Android和iPhone手机为代表的智能移动设备的发明与互联网云
技术的兴起却敲响了PC时代的丧钟!这也预示着移动互联网时代(3G)已经来临。
在这个互联网繁荣的时代,有一颗超新星,以它独特性能优势与人性化的UI设计使它在短短的几年迅速的占领了智能移动设备的市场份额,它就是Google的Android!这也意味着Google在移动互联网时代开始抢跑并领跑。
Android是基于Linux平台完全开源的手机操作系统,同时开发语言为Java,这对于Java开发的我们是何等的诱人,程序员的技术要与时代同行,因此我选择了以Android为平台的手机天气预报系统来作为我的毕业设计,选择手机天气预报系统不仅可以提升技术,同时也很实用,为人们时刻了解天气状况和出行带来了方便。
需求分析
一、开发背景
近几年来随着3G技术成熟和智能手机的不断普及,移动应用的需求与日俱增,移动应用开发成为当下最热门的技术之一。
在Google和Android手机联盟
的共同推动下,Android在众多移动应用开发平台中脱颖而出。
Android是一个真正意义上的开源智能手机操作系统,该系统一经推出立即受到全球移动设备厂商和开发者的热捧。
为顺应潮流,本设计旨在搭载Android的移动设备上运行,实现天气状况的实时动态更新与显示,方便人们的出行与生活。
二、项目需求分析
根据功能的需求,分析此项目的主要功能应具备以下几点:
1. 精确查询定位全国各地城市未来几天内的实时天气状况
2. 系统要具的实用性,符合用户查看信息习惯,界面设计优美
3. 系统要具有稳定性,且在一定程度上节省流量的开销
总体设计
一、系统规划
由上述的需求,现将系统分为三大模块:天气显示界面模块、预报城市设置模块与Widget桌面小部件模块。
各系统模块功能如下:
1). 天气显示界面模块
显示指定城市三天内的天气状况,包括日期、城市名称、温度、风力与当日的建议,用户可通过按菜单键来显示菜单更新当前天气与设置天气显示的界面背景,以及跳转至设置预报城市界面来更换预报城市。
2). 预报城市设置模块
由自动设置预报城市与手动设置二部分组成,自动设置实现GPS定位功能,自动确定当前用户所在地;而手动设置则通过可伸展性下拉列表单击选择系统数据库中预存的城市来进行设置,同时为了方便用户查找,支持以输入框的形式来过滤查询预报城市。
当单击选中城市时跳转至天气显示界面,来显示该城市当三天内的天气状况;第一次运行时自动跳到该界面。
3). Widget桌面小部件模块
为了方便用户实时了解天气状况,特别添加在Android系统桌面上显示当前天气与时间的天气小部件,使用户拿起手机的第一时刻就能了解天气,同时当用户单击小部件时,自动跳转至天气显示界面,显示三天内的详细天气。
二、系统功能界面
1. 设置预报城市界面:
1.1 当第一次运行程序时,跳转至城市设置界面进行预报城市的选择:
1.2 用户可以通过单击选择“定位当前城市”的方式调用系统GPS功能自动定位预报城市:
1.3 用户可通过输入框过滤查询当前系统中预存的城市:
2.天气显示界面:
2.1 选择了预报城市后,系统跳转至天气显示界面,显示该城市三天内的实时天气:
2.2 在天气界面中用户可通过按菜单键来调出菜单,选择城市,更新天气与更换背景:
3.Widget桌面小部件界面:
方便用户第一时间了解天气动态,添加widget显示功能界面:
三.设计目标
设计完成一个实用稳定的天气预报系统,同时要廉价使其能滿足大部分用户的需求,因此针对上述要求,本设计应滿足:
1. 系统能及时的返反馈指定预报城市的天气情况
2. 自动定位用户所在城市,支持GPS定位
3. 节省流量开销,规定在指定的时间间隔内才更新天气,其它时段显示缓
存的天气
4. 操作方便快捷,使用简单,界面设计美观大方,支持widget
系统设计
一、开发及运行环境
JDK1.6.10
Eclipse3.5
Android Development Toolkit (ADT) 15.0.0
Android 2.2及以上
Windows XP及以上
二、数据库设计
由于在本系统中是通过中央气象台的WebService 提供的API访问得到的天气预报,在查询指定城市的天气时,需要用到它提供的城市码,而城市码相对稳定不变,所以在构建系统时将其事先通过Android的网络访问技术将其缓冲到本地SQLite数据库进行保存起来,方便以后的查询,同时节省了流量开销。
综上所述在本地建立db_weather.db的数据库,其中的表结构如下:
其中只存在两个表: provices和citys
City中存在city_num用天气的查询,同时还存在外键province_id与provices表形成1对n的关系。
三、主要方法及步骤
1. 搭建Android开发环境,并建立一个android
2.2版本名为WeatherSystem
项目
2. 首先编写网络访问代码,访问/data5/city.xml中央气
象站解析得到所有城市码并导出保存得到的db_weather.db数据文件
3. 在程序第一次运行时,将db_weatcher.db数据库文件导入到应用程序数据
库中
4. 建立设置城市界面,读取数据库文件,获取省份,城市以及对应的城市码。
5. 接收用户选择的城市码,访问:/data/<城市码>.html
得到天气信息
6. 解析天气信息,将城市码及天气信息缓冲下来,并为其设置有效时间,方
便下次启动时直接得到天气信息,过期则从网上更新
7. 定时由保存的城市码更新天气信息
四、主要方法及技术
1. Android手机的界面UI设计
2. Android的网络通信
3. Android的广播
4. GPS调用解析
5. Widget小部件编程
6. XML与JSON解析
7. SQLite数据库操作
8. Android文件操作
主要模块
一、项目框架
在装有ADT插件的Eclipse中新建一个名为WeatherSystem的Android2.2版本的项目,
项目主要文件结构如下:
WeatherSystem
|__src
| |_com.weather.app
| | |_MainActivity.java
| | |_SetCityActivity.java
| | |_UpdateWidgetService.java
| | |_WeatherWidget.java
| |_p
| | |_GPSListAdapter.java
| | |_MyListAdpater.java
| |_com.weather.dao
| | |_DBHelper.java
| |_com.weaher.utils
| |_LocationXMParser.java
| |_WeatherInfoParser.java
| |_WebAccessTools.java
|__res
| |_ drawable
| | |_(略)
| |_layout
| | |_gps.xml
| | |_main.xml
| | |_widget_layout.xml
| | |_set_city.xml
| |_menu
| | |_configure_menu.xml
| |_raw
| | |_db_weather.db
| |_values
| | |_color.xml
| | |_strings.xml
| |_xml
| |_weather_widget.xml
|
|_AndroidManifest.xml
二、主要功能实现
1.获取城市码db_weather.db 数据库文件
获取全国各地的城市码,是通过访问中央气象局网从省份直辖市到城镇一级 一级深入得到的,获得一个地区的城市码总共需要访问4次网络,分别如下:
1. 访问/data5/city.xml 得到省份直辖市列表与它的编
号:
2. 访问/data5/city<省份编号>.xml 得到该省份直辖市
的城市编号(如访问山东:/data5/city12.xml)
3. 访问/data5/city<城市编号>.xml 得到该城市的县区
编号(如访问济南:/data5/city1201.xml)
4. 访问/data5/city<县区编号>.xml 得到该县区的城市
码(如访问长清:/data5/city120102.xml)
01|北京,02|上海,03|天津,04|重庆,05|黑龙江,06|吉林,07|辽宁,08|内蒙古,…
1201|济南,1202|青岛,1203|淄博,1204|德州,1205|烟台,1206|潍
坊,…… 120101|济南,120102|长清,120103|商河,120104|章丘,120105|平阴,….
120102|101120102
首先实现上述功能需使用Android的网络访问技术,故编写工具类
WebAccessTools类如下:
/**
* 根据给定的url地址访问网络,得到响应内容(这里为GET方式访问)
* @param url 指定的url地址
* @return web服务器响应的内容,为<code>String</code>类型,当访问失败时,返回为null */
public String getWebContent(String url) {
//创建一个http请求对象
HttpGet request = new HttpGet(url);
//创建HttpParams以用来设置HTTP参数
HttpParams params=new BasicHttpParams();
//设置连接超时或响应超时
HttpConnectionParams.setConnectionTimeout(params, 3000);
HttpConnectionParams.setSoTimeout(params, 5000);
//创建一个网络访问处理对象
HttpClient httpClient = new DefaultHttpClient(params);
try{
//执行请求参数项
HttpResponse response = httpClient.execute(request);
//判断是否请求成功
if(response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
//获得响应信息
String content = EntityUtils.toString(response.getEntity());
return content;
} else {
//网连接失败,使用Toast显示提示信息
Toast.makeText(context, "网络访问失败,请检查您机器的联网设备!",
Toast.LENGTH_LONG).show();
}
}catch(Exception e) {
e.printStackTrace();
} finally {
//释放网络连接资源
httpClient.getConnectionManager().shutdown();
}
return null;
}
由上面访问的可知,得到的编码与名称都是“编码|名称”的形式,因此在这也编写一个解析得到城市码的工具类WeatherInfoParser,用于解析从服务器中得到的城市码:
/**
* 通过解析content,得到一个一维为城市编号,二维为城市名的二维数组
* 解析的字符串的形式为: <code>编号|城市名,编号|城市名,.....</code>
* @param content 需要解析的字符串
* @return 封装有城市编码与名称的二维数组
*/
public static String[][] parseCity(String content) {
//判断content不为空
if(content!=null&&content.trim().length()!=0) {
StringTokenizer st=new StringTokenizer(content, ",");
int count = st.countTokens();
String[][] citys = new String[count][2];
int i=0, index=0;
while(st.hasMoreTokens()) {
String city = st.nextToken();
index = city.indexOf('|');
citys[i][0] = city.substring(0, index);
citys[i][1] = city.substring(index+1);
i = i+1;
}
return citys;
}
return null;
}
编写这两个类后现在就是编写从服务器端用程序遍历得到全国各地的城市名与
城市码,并将它们分别的保存在String[][] provinces数组,String[][] childs数组与String[][] cityCode中:
WebAccessTools webTools = new WebAccessTools(this);
//得到访问网络的内容
String webContent=webTools.getWebContent("/data5/city.xml");
//第一次解析得到的为省份或一级直辖市
String[][] provinces = WeaterInfoParser.parseCity(webContent);
String[] groups = new String[provinces.length];
String[][] childs = new String[provinces.length][];
String[][] cityCode = new String[provinces.length][];
for(int i=0; i< provinces.length; i++) {
groups[i] = provinces[i][1];
//由省份码来得到城市码
StringBuffer urlBuilder= new StringBuffer("/data5/city");
urlBuilder.append(provinces[i][0]);
urlBuilder.append(".xml");
webContent = webTools.getWebContent(urlBuilder.toString());
String[][] citys = WeaterInfoParser.parseCity(webContent);
//用于保存所的有towns
String[][][] towns = new String[citys.length][][];
//计算总的城镇数
int sum=0;
for(int j=0; j<citys.length; j++) {
//由城市码来得到地方码
urlBuilder= new StringBuffer("/data5/city");
urlBuilder.append(citys[j][0]);
urlBuilder.append(".xml");
webContent = webTools.getWebContent(urlBuilder.toString());
towns[j] = WeaterInfoParser.parseCity(webContent);
sum = sum + towns[j].length;
}
childs[i] = new String[sum];
cityCode[i] = new String[sum];
sum=0;
for(int j=0; j<citys.length; j++) {
for(int n=0; n<towns[j].length; n++) {
if(n==0)
childs[i][sum] = towns[j][n][1];
else
childs[i][sum] = towns[j][0][1] + "." + towns[j][n][1];
urlBuilder= new StringBuffer("/data5/city");
urlBuilder.append(towns[j][n][0]);
urlBuilder.append(".xml");
webContent = webTools.getWebContent(urlBuilder.toString());
String[][] code=WeaterInfoParser.parseCity(webContent);
cityCode[i][sum] = code[0][1];
sum = sum + 1;
}
}
urlBuilder=null;
}
接下来就是将得到的上面的三个数组建立数据库文件db_weather.db保存起来,
用到android.database.sqlite.SQLiteDatabase类的静态方法:
SQLiteDatabase openOrCreateDatabase(String path, CursorFactory factory)来创建一个数据库文件,其中的path表示数据库存放的路径,而factory中游标工厂,这
里可将它设为空,从而得到SQLiteDatabase对象,则再调用它的execSQL(String
sql)方法来执行保存数据库的操作,从而将上面的三个数组转换为数据库中的数
据,最后使用ADT插件中的DDMS工具将得到的数据库文件从Android模拟器
中导出,最终就得到了db_weather.db文件。
以后上述的代码就可以不使用,直
接将db_weather.db文件放入资源文件夹res目录中的raw目录中,则在程序第一
次运行时导入到/data/data/com.weather.app/databases目录中就行了,其中关于数
据库的导入实际是Java中文件的复制。
2.实现可伸缩性列表的的构建与过滤
实现可伸缩性列表是通过继承android.widget.BaseExpandableListAdapter适
配器实现的,其中主要实现它的public View getGroupView()得列表的一级列表和public void getChildView()得到列表的二级子列表实现的,在这里由于只是实现文
本显示功能,故用TextView组件来填充就行了,如果要构造这个自定义的适配
器,则只需在提供存放省份直辖市的一级列表的数组String[] groups和存放对应
的城镇的二级列表的String[][] childs就行了。
同时为了兼具过滤功能,还要需再实现android.widget.Filterable接口,这个
接口有一个getFilter()返回Filter过滤器的列表,故还要提供一个Filter过滤类,
在本系统中,实现的是一个内部类CityFilter,它继承android.widget.Filter类,覆盖实现了两个方法,一个是performFiltering()得到FilterResults过滤结果对象方法,另一个是根据得到的FilterResults对象更新适配器的publishResults()方法。
其中的performFiltering(CharSequence constraint)方法的实现是通过constraint 这个关键字以省份直辖市为单位进行匹配,如果匹配成功,则添加该省份以下的
所有城市,如果匹配不成功,则再逐一与这个省份的下的城市配匹,则只添加匹
配的城市,其中匹配的结果放在Map<Integer, ArrayList<Integer>> values这样的
向量中,再由新建的FilterResults封装返回,(具体实现如下):
1. 首先是对关键字进行判断是否为空,如为空则由values添加所有省份与城
市,其中的allGroups和allChilds保存的是所有的省份与对应的城市:
//当过滤条件为空时,返回所有的省份与城市
if(constraint == null || constraint.length() == 0) {
for(int i=0; i<allGroups.length; i++) {
ArrayList<Integer> index = new ArrayList<Integer>();
//添加所有与之对应的城市
for(int j=0; j<allChilds[i].length; j++) {
index.add(j);
}
values.put(i, index);
}
}
2. 如果关键字constraint不为空,则以省份为单位进行匹配,省份匹配的添
加下面的所在城镇,如果不匹配,则进行步深入匹配城镇,添加符合条件
的城镇:
String filterStr = constraint.toString();
for(int i=0; i<allGroups.length; i++) {
//查找省名是否包含用户输入的字符串
if(allGroups[i].contains(filterStr)) {
ArrayList<Integer> index = new ArrayList<Integer>();
//添加所有与之对应的城市
for(int j=0; j<allChilds[i].length; j++) {
index.add(j);
}
values.put(i, index);
} else {
ArrayList<Integer> index = new ArrayList<Integer>();
//如果省份名没有,则查找它下面的城市名是否包含
for(int j=0; j<allChilds[i].length; j++) {
if(allChilds[i][j].contains(filterStr)) {
index.add(j);
}
}
//如果添加进入了城市,说明存在,则它的省份也添加进去
if(index.size() > 0) {
values.put(i, index);
} else {
index = null;
}
}
}
3. 得到过滤的结果后将其用FilterResource封装后返回:
FilterResults results = new FilterResults();
results.values = values;
results.count = values.size();
另外的publishResults(CharSequence constraint, FilterResults results)方法就是根据上面得到的results对象来得到新的String[] groups与String[][] Childs数组,再调用BaseExpandableListAdapter父类的notifyDataSetChanged()方法来更新列
表,从而实现过滤后结果的显示(具体实现如下):
1. 首先将参数FiltersResuls对象转换为Map<Integer, ArrayList<Integer>>
filterResult,然后来判断过滤后的结果长度时否为0,如果长度为0则说
明过滤后的结果为空,则调用父类的notifyDataSetInvalidated()方法来阻
止列表的更新:
2. 如果长度不为0,则说明存在过滤结果,则将它转换为groups数组与childs
数组,并调用notifyDataSetChanged()方法实再更新:
String[] newGroups = new String[count];
String[][] newChilds = new String[count][];
int index = 0;
int length = 0;
//得到新的groups和childs
for(int i=0; i<allGroups.length; i++) {
if(filterResult.containsKey(i)) {
newGroups[index] = allGroups[i];
//符合条件的城市
ArrayList<Integer> citys = filterResult.get(i);
length = citys.size();
newChilds[index] = new String[length];
for(int j = 0; j< length; j++) {
newChilds[index][j] = allChilds[i][citys.get(j)];
}
index = index + 1;
}
}
//设置groups和childs
groups = newGroups;
childs = newChilds;
//更新列表
notifyDataSetChanged();
//判断是否展开列表
count = getGroupCount();
if(count < 34) {
//展开伸缩性列表
for(int i=0; i<count; i++) {
provinceList.expandGroup(i);
}
} else {
//收缩伸缩性列表
for(int i=0; i<count; i++) {
provinceList.collapseGroup(i);
}
}
如上所述则就实现了带有过滤性可伸展性列表适配性的实现,则在使用时在
XML组件配置文件中使用ExpandableListView列表,并调用它的setAdapter()方
法来,加载自定义的适配器。
而在使用它的过滤功能时则调用自定义适配器的
getFilter()得到过滤Filter对象,再调用Filter对象的filter(String)方法实现的,在本系统中才用的时触发文本输入框EditText的TextChangedListener事件时调用从
而实现手动选择预报城市的过滤查询。
3.GPS定位功能的实现
Android中调用GPS功能,首先要获取GPS定位管理器LocationManager,
获取LocationManager后就是获取LocationProvider,可以通过Criteria对象设置
过滤条件来获得最符合用户需求的LocationProvider,得到LocationProvider后就
可通过调用LocationMananger对象的getLastKnownLocation()方法来获取
Location地址封装对象,最后由实例化的Geocoder将Location中的经度和纬度
反编译为地址信息集合List对象,从而由List对象来得到当前用户地址名。
在
开发过程中通过Eclipse中的ADT插件的DDMS可以为Android模拟器指定任
意地址,如下:
当在模拟器控制面板中指定经纬度后,则会在模拟器中出现GPS的标志:
但在实际开发调用GPS功能过程时,只能获取经度与纬度,而在使用Geocoder
反编译地址时报错:
使用的调用代码如下:
后来通过网上搜索得知在Android2.2模拟器中调用Geocoder需要backend服务:
”The Geocoder class requires a backend service that is not included in the core android framework. The Geocoder query methods will return an empty list if there no backend service in the platform.“
但并有说此服务要怎么得到,这看起来像是Android2.2模拟器的一个Bug,故而
在本设计中采用访问[/maps/geo?output=xml&q=经度,纬度]
的形式来得到详备的地址信息(来源于:/problems/69517),
如下访问/maps/geo?output=xml&q=30.659269,104.065762:
其中的output参数指定的是服务器响应的格式,除了XML格式还可以为JSON,
CSV等格式。
由此可知,为了实现GPS的定位功能还需要实现一个解析XML的工具类,在本
系统中由工具类LocationXMParser完成,它继承至org.xml.sax.helpers.DefaultHandler 类,用于专门用于解析XML文件。
上述的GPS功能具体实现过程如下:
1. 得到LocationManager系统定位服务管理者:
LocationManager locationManager =
(LocationManager)getSystemService(Context.LOCATION_SERVICE);
2. 设置Geocoder对象,过滤得到符合条件的LocationProvider,再由
LocationProvider得到封装经纬度信息的Location对象:
//设置一个Criteria标准用于过滤LocationProvider
Criteria criteria = new Criteria();
//设置不需要高度信息
criteria.setAltitudeRequired(false);
//设置不需要方位信息
criteria.setBearingRequired(false);
//得到最好的可用的Provider
String provider = locationManager.getBestProvider(criteria, true);
//得到当前的位置对象
Location location = locationManager.getLastKnownLocation(provider);
double latitude = location.getLatitude(); //得到经度
double longitude = location.getLongitude(); //得到纬度
3. 得到经纬度后再访问/maps/geo来得到含地址信息的
XML文本内容,并用自定义的LocationXMParser工具类解析封装得到此
经纬度对应的城市名:
//根据经纬度得到详细的地址信息
//定义的一个网络访问工具类
WebAccessTools webTools = new WebAccessTools(this);
String addressContext = webTools.getWebContent
("/maps/geo?output=xml&q="+
latitude+","+longitude);
//解析地址信息
SAXParserFactory spf = SAXParserFactory.newInstance();
try {
SAXParser parser = spf.newSAXParser();
XMLReader reader = parser.getXMLReader();
LocationXMLParser handler = new LocationXMLParser();
reader.setContentHandler(handler);
StringReader read = new StringReader(addressContext);
// 创建新的输入源SAX 解析器将使用 InputSource 对象来确定如何读取 XML 输入
InputSource source = new InputSource(read);
//开始解析
reader.parse(source);
//判断是否存在地址
if(handler.hasAddress())
return handler.getDetailAddress();
} catch (Exception e) {
e.printStackTrace();
}
上面代码中的getDetailAdress()方法返回的是一个Map对象,其中封装了从XML中解析得到的国家、省份、县区和城市四个信息,在得到这些信息后,系
统将与数据库中预存的省份城市相比较,最终匹配得到该地区的城市码完成GPS 自动定位功能的实现。
4.Widget窗体小部件的更新
由于widget中的时钟关系,需要对widget显示进行时刻的更新用来保持与
系统中时间的一致。
实现这个功能需要用到AlarmManager类,这个类专门用来设定在某个指定的时间去完成指定的事件。
设计思路是在Widget的onUpdate方法中启动一个自定义更新后台服务,更新widget,并设定下一分钟再次调用此服务。
具体实现过步骤如下:
1. 首先自定义一个后台运行服务类继承至Service类,实现它的服务开始运
行调用的onStart()方法:
super.onStart(intent, startId);
//得到widget的布局对象
RemoteViews views = WeatherWidget.getWeatherView(this);
//得到AppWidgetManager widget管理器
AppWidgetManager appWidgetManager=AppWidgetManager.getInstance(this);
int[] appids=appWidgetManager.getAppWidgetIds(new ComponentName(this,
WeatherWidget.class)); //得到城市码,并更新天气
SharedPreferences sp=getSharedPreferences(
SetCityActivity.CITY_CODE_FILE,
SetCityActivity.MODE_PRIVATE); String cityCode= sp.getString("code", "");
if(cityCode!=null&&cityCode.trim().length() > 0) {
WeatherWidget.updateAppWidget(views, this,
appWidgetManager, cityCode);
}
appWidgetManager.updateAppWidget(appids, views);
//获取当前时间设置警报服务
Date date = new Date();
long now =date.getTime();
long unit=60000;//间隔一分钟
int s=date.getSeconds(); //得到秒数
unit=60000-s*1000; //将时间精确到秒
pintent=PendingIntent.getService(this, 0, intent, 0);
//计时器
alarm=(AlarmManager)getSystemService(Context.ALARM_SERVICE);
//AlarmManager.RTC_WAKEUP设置服务在系统休眠时同样会运行
//第二个参数是下一次启动service时间
alarm.set(AlarmManager.RTC_WAKEUP, now+unit, pintent);
2. 然后在实现AppWidgetProvider的widget类的onUpdate方法中启动这个
自定义的服务:
//启动一个自定义更新widget的后台服务
context.startService(new Intent(context,UpdateWidgetService.class));
3. 除了启动这个服务是不够的,当用户删除widget部件时,后台服务也必
须停止,这样就必须实现Service类中的另一个方法onDestroy()方法,该
方法在Service停止时调用,在这里用于取消AlarmManager设置的警报
服务:
//当widget中通过调用context.stopService方法来指定销毁service时,被调用
public void onDestroy() {
//取消定时管理
if(alarm!=null) {
alarm.cancel(pintent);
}
super.onDestroy();
}
4. 则在widget类的onDisabled()方法中调用stopService方法来停止后台服务,
其中的onDisabled方法在widget被用户删除时由系统自动调用:
public void onDisabled(Context context) {
super.onDisabled(context);
//关闭后台服务
context.stopService(new Intent(context,UpdateWidgetService.class));
}
在自定了一个Service服务后,系统必须在清单文件AndroidManifest.xml中声明自定义的服务:
<!-- 自定义的后台更新widget服务 -->
<service android:name=".UpdateWidgetService"></service>
这样就实现了widget的更新功能,其实在配制widget的AppWidgetProviderInfo的配制文件中通过设置android:updatePeriodMillis属性来设置widget的自动更新,它的单位中毫秒,但由于自动更新对性能的损坏,故
它有一个最低值,这最低值长于一分钟,故而与该系统的要求不符,故以调用后
台Service的方式来解决。
功能测试
本系统的的测试,主要是通过手动操作该系统,查看是否存在异常或操作的
结果是否符合设计初衷来完成的,现将系统的主要操作结果截图展示如下:
一. 当系统初次启动时,由于没有设置预报城市,则自动由MianActivity天
气显示视图跳转到SetCityActivity城市设置视图,并要求用户选择预报城市,如下:
二. 接下来点击确定选择城市,则系统确定用户单击城市的城市码跳转至天
气显示界面,如下:
三. 跳转到天气显示界面后,可单击“菜单”按钮来显示天气的菜单:
四. 选择“壁纸”菜单项可以更换程序背景图片如下:
五. 选择“设置城市”菜单项,则跳转至设置城市的视图界面,在这里可以
在输入城市的关键字在进行过滤查询,这样就及大的方便了用户的选择:
六. 如果要定位当前的城市,以单击“定位当前城市”自动设置城市,而在
此之前必须,在DDMS控制面板中在指定一个经纬度,来开启GPS功能:
七. widget窗体小部件的添加是通过长按桌面的空白处,出现一个选项菜单,
然后选择“窗体小部件”,接着在弹出的选项中选择“天气精灵”即本系统,则设计的小窗体部件将会出现在主屏幕的桌面上:
结论
本系统基本实现了需求的中的天气预报的功能,界面设计也较漂亮,具有一
定的实用性。
其中的天气数据全部来源于网络,故在运行时一定要确保系统所处环境的网络流畅性。
由于开发过程是在Android2.2版本的模拟器上运行的,故测试的结果可能存在一定的局性性。
同时在设计之初考虑问题的不全面,使得在无网状态下设计不完善,运行本系统在无网状态下时会异常停止。
而且由于本人的技术有限,使得在GPS自动定位时功能不稳定。
通过本系统的开发使得我对于Android平台的应用开发有了一定的了解,特
别是其中的GPS功能与Widget的更新功能的实现让我体会到了实践的意义,只
有自己认真动手才能算真正的掌握,书本上的知识也不一定完全准确,在遇到问题时可以通过网上搜索的方式得到解决。
同时在本系统中反映的问题也让我意识到了自己的一些不足,明解了以后学习时的基本方向。
参考文献:
《Android应用开发揭秘》杨丰盛机械工业出版社
《Android应用开发详解》郭宏志电子出版社
Google Android API。