目录摘要 (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系统桌面上显示当前天气与时间的天气小部件,使用户拿起手机的第一时刻就能了解天气,同时当用户单击小部件时,自动跳转至天气显示界面,显示三天内的详细天气。
2二、系统功能界面1.设置预报城市界面:1.1当第一次运行程序时,跳转至城市设置界面进行预报城市的选择:1.2 用户可以通过单击选择“定位当前城市”的方式调用系统 GPS 功能自动定位预报城市:1.3 用户可通过输入框过滤查询当前系统中预存的城市:2.天气显示界面:2.1 选择了预报城市后,系统跳转至天气显示界面,显示该城市三天内的实时天气:2.2 在天气界面中用户可通过按菜单键来调出菜单,选择城市,更新天气与更换背景:3.Widget 桌面小部件界面:方便用户第一时间了解天气动态,添加widget显示功能界面:三.设计目标设计完成一个实用稳定的天气预报系统,同时要廉价使其能滿足大部分用户的需求,因此针对上述要求,本设计应滿足:1.系统能及时的返反馈指定预报城市的天气情况2.自动定位用户所在城市,支持GPS定位3.节省流量开销,规定在指定的时间间隔内才更新天气,其它时段显示缓存的天气4.操作方便快捷,使用简单,界面设计美观大方,支持widget系统设计一、开发及运行环境JDK1.6.10Eclipse3.5Android Development Toolkit (ADT) 15.0.0Android 2.2 及以上Windows XP 及以上二、数据库设计由于在本系统中是通过中央气象台的WebService提供的API访问得到的天气预报,在查询指定城市的天气时,需要用到它提供的城市码,而城市码相对稳定不变,所以在构建系统时将其事先通过Android的网络访问技术将其缓冲到本地SQLite 数据库进行保存起来,方便以后的查询,同时节省了流量开销。
综上所述在本地建立db_weather.db的数据库,其中的表结构如下:其中只存在两个表: provices和citysCity 中存在 city_num 用天气的查询,同时还存在外键 province_id 与 provices 表形成1对n的关系。
三、主要方法及步骤1.搭建Android开发环境,并建立一个android2.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.java7| |_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得到省份直辖市列表与它的编号:01|北京,02|上海,03|天津,04|重庆,05|黑龙江,06|吉林,07|辽宁,08|内蒙古,…2.访问/data5/city<省份编号>.xml得到该省份直辖市的城市编号(如访问山东:/data5/city12.xml)1201|济南,1202|青岛,1203|淄博,1204|德州,1205|烟台,1206|潍坊,……3.访问/data5/city<城市编号>.xml得到该城市的县区编号(如访问济南:/data5/city1201.xml)120101|济南,120102|长清,120103|商河,120104|章丘,120105|平阴,….4.访问/data5/city<县区编号>.xml得到该县区的城市码(如访问长清:/data5/city120102.xml)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); //用于保存所的有townsString[][][] 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(intn=0; n<towns[j].length; n++) {if(n==0)childs[i][sum] = towns[j][n][1];elsechilds[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(Stringsql)方法来执行保存数据库的操作,从而将上面的三个数组转换为数据库中的数据,最后使用ADT插件中的DDMS工具将得到的数据库文件从Android模拟器中导出,最终就得到了db_weather.db文件。