天气预报APP论文.docx_第1页
天气预报APP论文.docx_第2页
天气预报APP论文.docx_第3页
天气预报APP论文.docx_第4页
天气预报APP论文.docx_第5页
已阅读5页,还剩29页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

目录 摘要 . 1 需求分析 . 2 一、开发背景 . 2 二、项目需求分析 . 2 总体设计 . 2 一、系统规划 . 2 二、系统功能界面 . 3 1. 设置预报城市界面: . 3 2天气显示界面: . 4 3Widget桌面小部件界面: . 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 在天气界面中用户可通过按菜单键来调出菜单,选择城市,更新天气与更换背景: 3Widget桌面小部件界面: 方便用户第一时间了解天气动态,添加 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 开发环境,并建立一个 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.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 得到省份直辖市列表与它的编号: 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服务器响应的内容,为String类型,当访问失败时,返回为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,得到一个一维为城市编号,二维为城市名的二维数组 * 解析的字符串的形式为: 编号|城市名,编号|城市名,. * 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 Stringcount2; int i=0, index=0; while(st.hasMoreTokens() String city = st.nextToken(); index = city.indexOf(|); citysi0 = city.substring(0, index); citysi1 = 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 Stringprovinces.length; String childs = new Stringprovinces.length; String cityCode = new Stringprovinces.length; for(int i=0; i provinces.length; i+) groupsi = provinces i1; /由省份码来得到城市码 StringBuffer urlBuilder= new StringBuffer(/data5/city); urlBuilder.append(provincesi0); urlBuilder.append( .xml); webContent = webTools.getWebContent(urlBuilder.toString(); String citys = WeaterInfo Parser.parseCity(webContent); /用于保存所的有 towns String towns = new Stringcitys.length; /计算总的城镇数 int sum=0; for( int j=0; jcitys.length; j+) / 由城市码来得到地方码 urlBuilder= new StringBuffer(/data5/city); urlBuilder.append(city sj0); urlBuilder.append( .xml); webContent = webTools.getWebContent(urlBuilder.toString(); townsj = WeaterInfoParser. parseCity(webContent); sum = sum + townsj. length; childsi = new Stringsum; cityCodei = new Stringsum; sum=0; for( int j=0; jcitys.length; j+) for (int n=0; ntownsj.length; n+) if(n=0) childsisum = townsjn1; else childsisum = townsj01 + . + townsjn1; urlBuilder= new StringBuffer(/data5/city); urlBuilder.append(townsjn0); urlBuilder.append(.xml); webContent = webTools.getWebContent(urlBuilder.toString(); String code=WeaterInfoParser.parseCity(webContent); cityCodeisum = code01; 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 这个关键字以省份直辖市为单位进行匹配,如果匹配成功,则添加该省份以下的所有城市,如果匹配不成功,则再逐一与这个省份的下的城市配匹,则只添加匹配的城市,其中匹配的结果放在 MapInteger, ArrayList values 这样的向量中,再由新建的 FilterResults 封装返回,(具体实现如下): 1. 首先是对关键字进行判断是否为空,如为空则由 values 添加所有省份与城市,其中的 allGroups 和 allChilds 保存的是所有的省份与对应的城市: /当过滤条件为空时,返回所有的省份与城市 if(constraint = null | constraint.length() = 0) for(int i=0; iallGroups.length; i+) ArrayList index = new ArrayList(); /添加所有与之对应的城市 for(int j=0; jallChildsi.length; j+) index.add(j); values.put(i, index); 2. 如果关键字 constraint 不为空,则以省份为单位进行匹配,省份匹配的添加下面的所在城镇,如果不匹配,则进行步深入匹配城镇,添加符合条件的城镇: String filterStr = constraint.toString(); for (int i=0; iallGroups.length; i+) /查找省名是否包含用户输入的字符串 if(allGroupsi.contains(filterStr) ArrayList index = new ArrayList(); /添加所有与之对应的城市 for(int j=0; jallChildsi.length; j+) index.add(j); values.put(i, index); else ArrayList index = new ArrayList(); /如果省份名没有,则查找它下面的城市名是否包含 for(int j=0; j 0) values.put(i, index); else index = null; 3. 得到过滤的结果后将其用 FilterResource 封装后返回: FilterResults res ults = new FilterResults(); results. values = values; results. count = values.size(); 另外的 publishResults(CharSequence constraint, FilterResults results)方法就是根据上面得到的results对象来得到新的String groups与String Childs数组,再调用 BaseExpandableListAdapter 父类的 notifyDataSetChanged()方法来更新列表,从而实现过滤后结果的显示(具体实现如下): 1. 首先将参数 FiltersResuls 对象转换为 MapInteger, ArrayList filterResult,然后来判断过滤后的结果长度时否为 0,如果长度为 0 则说明过滤后的结果为空,则调用父类的 notifyDataSetInvalidated()方法来阻止列表的更新: 2. 如果长度不为 0,则说明存在过滤结果,则将它转换为 groups 数组与 childs 数组,并调用 notifyDataSetChanged()方法实再更新: String newGroups = new Stringcount; String newChilds = new Stringcount; int index = 0; int length = 0; /得到新的 groups和childs for(int i=0; iallGroups.length; i+) if( filterResult.containsKey(i) newGroupsindex = allGroupsi; /符合条件的城市 ArrayList citys = filterResult.get(i); length = citys.size(); newChildsindex = new Stringlength; for(int j = 0; j length; j+) newChildsindexj = allChildsicitys.get(j); index = index + 1; /设置groups 和childs groups = newGroups; childs = newChilds; /更新列表 notifyDataSetChanged(); /判断是否展开列表 count = getGroupCount(); if(count 34) /展开伸缩性列表 for (int i=0; icount; i+) provinceList.expandGroup(i); else /收缩伸缩性列表 for (int i=0; icount; 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 = locationMa nager.getLastKnownLocation(provider); double latitude = location.getLatitude(); /得到经度 double longitude = location.getLongitude(); /得到纬度 3. 得到经纬度后再访问 /maps/geo 来得到含地

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论