版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、<p><b> 目錄</b></p><p><b> 摘要1</b></p><p><b> 需求分析2</b></p><p><b> 一、開發(fā)背景2</b></p><p> 二、項(xiàng)目需求分析2</p>
2、<p><b> 總體設(shè)計(jì)2</b></p><p><b> 一、系統(tǒng)規(guī)劃2</b></p><p> 二、系統(tǒng)功能界面3</p><p> 1. 設(shè)置預(yù)報(bào)城市界面:3</p><p> 2.天氣顯示界面:4</p><p> 3.Widg
3、et 桌面小部件界面:5</p><p><b> 三.設(shè)計(jì)目標(biāo)6</b></p><p><b> 系統(tǒng)設(shè)計(jì)6</b></p><p> 一、開發(fā)及運(yùn)行環(huán)境6</p><p><b> 二、數(shù)據(jù)庫(kù)設(shè)計(jì)6</b></p><p> 三
4、、主要方法及步驟7</p><p> 四、主要方法及技術(shù)7</p><p><b> 主要模塊7</b></p><p><b> 一、項(xiàng)目框架7</b></p><p> 二、主要功能實(shí)現(xiàn)8</p><p> 1.獲取城市碼 db_weather.db
5、數(shù)據(jù)庫(kù)文件8</p><p> 2.實(shí)現(xiàn)可伸縮性列表的的構(gòu)建與過(guò)濾12</p><p> 3.GPS 定位功能的實(shí)現(xiàn)15</p><p> 4.Widget 窗體小部件的更新18</p><p><b> 功能測(cè)試19</b></p><p><b> 結(jié)論23&l
6、t;/b></p><p><b> 摘要</b></p><p> Window 操作系統(tǒng)的誕生成就了微軟帝國(guó),同時(shí)也造就了 PC 時(shí)代的繁榮,然而如今,以 Android 和 iPhone 手機(jī)為代表的智能移動(dòng)設(shè)備的發(fā)明與互聯(lián)網(wǎng)云技術(shù)的興起卻敲響了 PC 時(shí)代的喪鐘!這也預(yù)示著移動(dòng)互聯(lián)網(wǎng)時(shí)代(3G)已經(jīng)來(lái)臨。</p><p>
7、在這個(gè)互聯(lián)網(wǎng)繁榮的時(shí)代,有一顆超新星,以它獨(dú)特性能優(yōu)勢(shì)與人性化的 UI 設(shè)計(jì)使它在短短的幾年迅速的占領(lǐng)了智能移動(dòng)設(shè)備的市場(chǎng)份額,它就是 Google 的 Android!這也意味著 Google 在移動(dòng)互聯(lián)網(wǎng)時(shí)代開始搶跑并領(lǐng)跑。</p><p> Android 是基于 Linux 平臺(tái)完全開源的手機(jī)操作系統(tǒng),同時(shí)開發(fā)語(yǔ)言為Java,這對(duì)于 Java 開發(fā)的我們是何等的誘人,程序員的技術(shù)要與時(shí)代同行,因此我選擇
8、了以 Android 為平臺(tái)的手機(jī)天氣預(yù)報(bào)系統(tǒng)來(lái)作為我的畢業(yè)設(shè)計(jì),選擇手機(jī)天氣預(yù)報(bào)系統(tǒng)不僅可以提升技術(shù),同時(shí)也很實(shí)用,為人們時(shí)刻了解天氣狀況和出行帶來(lái)了方便。</p><p><b> 1</b></p><p><b> 需求分析</b></p><p><b> 一、開發(fā)背景</b><
9、/p><p> 近幾年來(lái)隨著 3G 技術(shù)成熟和智能手機(jī)的不斷普及,移動(dòng)應(yīng)用的需求與日俱增,移動(dòng)應(yīng)用開發(fā)成為當(dāng)下最熱門的技術(shù)之一。在 Google 和 Android 手機(jī)聯(lián)盟的共同推動(dòng)下,Android 在眾多移動(dòng)應(yīng)用開發(fā)平臺(tái)中脫穎而出。Android 是一個(gè)真正意義上的開源智能手機(jī)操作系統(tǒng),該系統(tǒng)一經(jīng)推出立即受到全球移動(dòng)設(shè)備廠商和開發(fā)者的熱捧。為順應(yīng)潮流,本設(shè)計(jì)旨在搭載 Android 的移動(dòng)設(shè)備上運(yùn)行,實(shí)現(xiàn)天氣
10、狀況的實(shí)時(shí)動(dòng)態(tài)更新與顯示,方便人們的出行與生活。</p><p><b> 二、項(xiàng)目需求分析</b></p><p> 根據(jù)功能的需求,分析此項(xiàng)目的主要功能應(yīng)具備以下幾點(diǎn):</p><p> 精確查詢定位全國(guó)各地城市未來(lái)幾天內(nèi)的實(shí)時(shí)天氣狀況</p><p> 系統(tǒng)要具的實(shí)用性,符合用戶查看信息習(xí)慣,界面設(shè)計(jì)優(yōu)美&
11、lt;/p><p> 系統(tǒng)要具有穩(wěn)定性,且在一定程度上節(jié)省流量的開銷</p><p><b> 總體設(shè)計(jì)</b></p><p><b> 一、系統(tǒng)規(guī)劃</b></p><p> 由上述的需求,現(xiàn)將系統(tǒng)分為三大模塊:天氣顯示界面模塊、預(yù)報(bào)城市設(shè)置模塊與 Widget 桌面小部件模塊。各系統(tǒng)模塊功
12、能如下:</p><p> 1). 天氣顯示界面模塊</p><p> 顯示指定城市三天內(nèi)的天氣狀況,包括日期、城市名稱、溫度、風(fēng)力與當(dāng)日的建議,用戶可通過(guò)按菜單鍵來(lái)顯示菜單更新當(dāng)前天氣與設(shè)置天氣顯示的界面背景,以及跳轉(zhuǎn)至設(shè)置預(yù)報(bào)城市界面來(lái)更換預(yù)報(bào)城市。</p><p> 2). 預(yù)報(bào)城市設(shè)置模塊</p><p> 由自動(dòng)設(shè)置預(yù)報(bào)城市
13、與手動(dòng)設(shè)置二部分組成,自動(dòng)設(shè)置實(shí)現(xiàn) GPS 定位功能,自動(dòng)確定當(dāng)前用戶所在地;而手動(dòng)設(shè)置則通過(guò)可伸展性下拉列表單擊選擇系統(tǒng)數(shù)據(jù)庫(kù)中預(yù)存的城市來(lái)進(jìn)行設(shè)置,同時(shí)為了方便用戶查找,支持以輸入框的形式來(lái)過(guò)濾查詢預(yù)報(bào)城市。當(dāng)單擊選中城市時(shí)跳轉(zhuǎn)至天氣顯示界面,來(lái)顯示該城市當(dāng)三天內(nèi)的天氣狀況;第一次運(yùn)行時(shí)自動(dòng)跳到該界面。</p><p> 3). Widget 桌面小部件模塊</p><p> 為了
14、方便用戶實(shí)時(shí)了解天氣狀況,特別添加在 Android 系統(tǒng)桌面上顯示當(dāng)前天氣與時(shí)間的天氣小部件,使用戶拿起手機(jī)的第一時(shí)刻就能了解天氣,同時(shí)當(dāng)用戶單擊小部件時(shí),自動(dòng)跳轉(zhuǎn)至天氣顯示界面,顯示三天內(nèi)的詳細(xì)天氣。</p><p><b> 2</b></p><p><b> 二、系統(tǒng)功能界面</b></p><p><
15、b> 設(shè)置預(yù)報(bào)城市界面:</b></p><p> 1.1 當(dāng)?shù)谝淮芜\(yùn)行程序時(shí),跳轉(zhuǎn)至城市設(shè)置界面進(jìn)行預(yù)報(bào)城市的選擇:</p><p> 1.2 用戶可以通過(guò)單擊選擇“定位當(dāng)前城市”的方式調(diào)用系統(tǒng) GPS 功能自動(dòng)定位預(yù)報(bào)城市:</p><p><b> 3</b></p><p> 1.3
16、用戶可通過(guò)輸入框過(guò)濾查詢當(dāng)前系統(tǒng)中預(yù)存的城市:</p><p><b> 2.天氣顯示界面:</b></p><p> 2.1 選擇了預(yù)報(bào)城市后,系統(tǒng)跳轉(zhuǎn)至天氣顯示界面,顯示該城市三天內(nèi)的實(shí)時(shí)天氣:</p><p><b> 4</b></p><p> 2.2 在天氣界面中用戶可通過(guò)按菜單
17、鍵來(lái)調(diào)出菜單,選擇城市,更新天氣與更換背景:</p><p> 3.Widget 桌面小部件界面:</p><p> 方便用戶第一時(shí)間了解天氣動(dòng)態(tài),添加 widget 顯示功能界面:</p><p><b> 5</b></p><p><b> 三.設(shè)計(jì)目標(biāo)</b></p>
18、<p> 設(shè)計(jì)完成一個(gè)實(shí)用穩(wěn)定的天氣預(yù)報(bào)系統(tǒng),同時(shí)要廉價(jià)使其能滿足大部分用戶的需求,因此針對(duì)上述要求,本設(shè)計(jì)應(yīng)滿足:</p><p> 系統(tǒng)能及時(shí)的返反饋指定預(yù)報(bào)城市的天氣情況</p><p> 自動(dòng)定位用戶所在城市,支持 GPS 定位</p><p> 節(jié)省流量開銷,規(guī)定在指定的時(shí)間間隔內(nèi)才更新天氣,其它時(shí)段顯示緩存的天氣</p>
19、<p> 操作方便快捷,使用簡(jiǎn)單,界面設(shè)計(jì)美觀大方,支持 widget</p><p><b> 系統(tǒng)設(shè)計(jì)</b></p><p><b> 一、開發(fā)及運(yùn)行環(huán)境</b></p><p><b> JDK1.6.10</b></p><p> Eclipse3
20、.5</p><p> Android Development Toolkit (ADT) 15.0.0</p><p> Android 2.2 及以上</p><p> Windows XP 及以上</p><p><b> 二、數(shù)據(jù)庫(kù)設(shè)計(jì)</b></p><p> 由于在本系統(tǒng)中是
21、通過(guò)中央氣象臺(tái)的 WebService 提供的 API 訪問(wèn)得到的天氣預(yù)報(bào),在查詢指定城市的天氣時(shí),需要用到它提供的城市碼,而城市碼相對(duì)穩(wěn)定不變,所以在構(gòu)建系統(tǒng)時(shí)將其事先通過(guò) Android 的網(wǎng)絡(luò)訪問(wèn)技術(shù)將其緩沖到本地 SQLite 數(shù)據(jù)庫(kù)進(jìn)行保存起來(lái),方便以后的查詢,同時(shí)節(jié)省了流量開銷。綜上所述在本地建立 db_weather.db 的數(shù)據(jù)庫(kù),其中的表結(jié)構(gòu)如下:</p><p> 其中只存在兩個(gè)表: pro
22、vices 和 citys</p><p> City 中存在 city_num 用天氣的查詢,同時(shí)還存在外鍵 province_id 與 provices 表形成 1 對(duì) n 的關(guān)系。</p><p><b> 6</b></p><p><b> 三、主要方法及步驟</b></p><p>
23、; 搭建 Android 開發(fā)環(huán)境,并建立一個(gè) android2.2 版本名為 WeatherSystem</p><p><b> 項(xiàng)目</b></p><p> 首先編寫網(wǎng)絡(luò)訪問(wèn)代碼,訪問(wèn) http://m.weather.com.cn/data5/city.xml 中央氣象站解析得到所有城市碼并導(dǎo)出保存得到的 db_weather.db 數(shù)據(jù)文件</
24、p><p> 在程序第一次運(yùn)行時(shí),將 db_weatcher.db 數(shù)據(jù)庫(kù)文件導(dǎo)入到應(yīng)用程序數(shù)據(jù)庫(kù)中</p><p> 建立設(shè)置城市界面,讀取數(shù)據(jù)庫(kù)文件,獲取省份,城市以及對(duì)應(yīng)的城市碼。</p><p> 接收用戶選擇的城市碼,訪問(wèn):http://m.weather.com.cn/data/<城市碼>.html</p><p>
25、<b> 得到天氣信息</b></p><p> 解析天氣信息,將城市碼及天氣信息緩沖下來(lái),并為其設(shè)置有效時(shí)間,方便下次啟動(dòng)時(shí)直接得到天氣信息,過(guò)期則從網(wǎng)上更新</p><p> 定時(shí)由保存的城市碼更新天氣信息</p><p><b> 四、主要方法及技術(shù)</b></p><p> And
26、roid 手機(jī)的界面 UI 設(shè)計(jì)</p><p> Android 的網(wǎng)絡(luò)通信</p><p> Android 的廣播</p><p><b> GPS 調(diào)用解析</b></p><p> Widget 小部件編程</p><p> XML 與 JSON 解析</p>&
27、lt;p> SQLite 數(shù)據(jù)庫(kù)操作</p><p> Android 文件操作</p><p><b> 主要模塊</b></p><p><b> 一、項(xiàng)目框架</b></p><p> 在裝有 ADT 插件的 Eclipse 中新建一個(gè)名為 WeatherSystem 的 An
28、droid2.2 版本的項(xiàng)目,</p><p> 項(xiàng)目主要文件結(jié)構(gòu)如下:</p><p> WeatherSystem</p><p><b> 7</b></p><p><b> |</b></p><p> |_AndroidManifest.xml</
29、p><p><b> 二、主要功能實(shí)現(xiàn)</b></p><p> 1.獲取城市碼 db_weather.db 數(shù)據(jù)庫(kù)文件</p><p> 獲取全國(guó)各地的城市碼,是通過(guò)訪問(wèn)中央氣象局網(wǎng)從省份直轄市到城鎮(zhèn)一級(jí)一級(jí)深入得到的,獲得一個(gè)地區(qū)的城市碼總共需要訪問(wèn) 4 次網(wǎng)絡(luò),分別如下:</p><p> 訪問(wèn) http://
30、m.weather.com.cn/data5/city.xml 得到省份直轄市列表與它的編號(hào):</p><p> 01|北京,02|上海,03|天津,04|重慶,05|黑龍江,06|吉林,07|遼寧,08|內(nèi)蒙古,…</p><p> 訪問(wèn) http://m.weather.com.cn/data5/city<省份編號(hào)>.xml 得到該省份直轄市的城市編號(hào)(如訪問(wèn)山東:ht
31、tp://m.weather.com.cn/data5/city12.xml)</p><p> 1201|濟(jì)南,1202|青島,1203|淄博,1204|德州,1205|煙臺(tái),1206|濰坊,……</p><p> 訪問(wèn) http://m.weather.com.cn/data5/city<城市編號(hào)>.xml 得到該城市的縣區(qū)編號(hào)(如訪問(wèn)濟(jì)南:http://m.weath
32、er.com.cn/data5/city1201.xml)</p><p> 120101|濟(jì)南,120102|長(zhǎng)清,120103|商河,120104|章丘,120105|平陰,….</p><p> 訪問(wèn) http://m.weather.com.cn/data5/city<縣區(qū)編號(hào)>.xml 得到該縣區(qū)的城市碼(如訪問(wèn)長(zhǎng)清:http://m.weather.com.cn
33、/data5/city120102.xml)</p><p> 120102|101120102</p><p><b> 8</b></p><p> 首先實(shí)現(xiàn)上述功能需使用Android的網(wǎng)絡(luò)訪問(wèn)技術(shù),故編寫工具類</p><p> WebAccessTools 類如下:</p><p
34、><b> /**</b></p><p> 根據(jù)給定的url地址訪問(wèn)網(wǎng)絡(luò),得到響應(yīng)內(nèi)容(這里為GET方式訪問(wèn))</p><p> @param url 指定的url地址</p><p> @return web服務(wù)器響應(yīng)的內(nèi)容,為<code>String</code>類型,當(dāng)訪問(wèn)失敗時(shí),返回為null *
35、/</p><p> public String getWebContent(String url) {</p><p> //創(chuàng)建一個(gè)http請(qǐng)求對(duì)象</p><p> HttpGet request = new HttpGet(url);</p><p> //創(chuàng)建HttpParams以用來(lái)設(shè)置HTTP參數(shù)</p>
36、<p> HttpParams params=new BasicHttpParams();</p><p> //設(shè)置連接超時(shí)或響應(yīng)超時(shí)</p><p> HttpConnectionParams.setConnectionTimeout(params, 3000);</p><p> HttpConnectionParams.setSoTime
37、out(params, 5000);</p><p> //創(chuàng)建一個(gè)網(wǎng)絡(luò)訪問(wèn)處理對(duì)象</p><p> HttpClient httpClient = new DefaultHttpClient(params); try{</p><p><b> //執(zhí)行請(qǐng)求參數(shù)項(xiàng)</b></p><p> HttpRespo
38、nse response = httpClient.execute(request);</p><p> //判斷是否請(qǐng)求成功</p><p> if(response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {</p><p><b> //獲得響應(yīng)信息</b></
39、p><p> String content = EntityUtils.toString(response.getEntity()); return content;</p><p><b> } else {</b></p><p> //網(wǎng)連接失敗,使用Toast顯示提示信息</p><p> Toast.mak
40、eText(context, "網(wǎng)絡(luò)訪問(wèn)失敗,請(qǐng)檢查您機(jī)器的聯(lián)網(wǎng)設(shè)備!", Toast.LENGTH_LONG).show();</p><p><b> }</b></p><p> }catch(Exception e) {</p><p> e.printStackTrace();</p><
41、p> } finally {</p><p> //釋放網(wǎng)絡(luò)連接資源</p><p> httpClient.getConnectionManager().shutdown();</p><p><b> }</b></p><p> return null;</p><p>&l
42、t;b> }</b></p><p> 由上面訪問(wèn)的可知,得到的編碼與名稱都是“編碼|名稱”的形式,因此在這也編寫一個(gè)解析得到城市碼的工具類 WeatherInfoParser,用于解析從服務(wù)器中得到的城市碼:</p><p><b> 9</b></p><p><b> /**</b><
43、/p><p> 通過(guò)解析content,得到一個(gè)一維為城市編號(hào),二維為城市名的二維數(shù)組</p><p> 解析的字符串的形式為: <code>編號(hào)|城市名,編號(hào)|城市名,.....</code></p><p> @param content 需要解析的字符串</p><p> @return 封裝有城市編碼與名稱
44、的二維數(shù)組</p><p><b> */</b></p><p> public static String[][] parseCity(String content) {</p><p> //判斷content不為空</p><p> if(content!=null&&content.tr
45、im().length()!=0) {</p><p> StringTokenizer st=new StringTokenizer(content, ","); int count = st.countTokens();</p><p> String[][] citys = new String[count][2];</p><p>
46、 int i=0, index=0;</p><p> while(st.hasMoreTokens()) {</p><p> String city = st.nextToken();</p><p> index = city.indexOf('|');</p><p> citys[i][0] = city.s
47、ubstring(0, index);</p><p> citys[i][1] = city.substring(index+1);</p><p><b> i = i+1;</b></p><p><b> }</b></p><p> return citys;</p>
48、<p><b> }</b></p><p> return null;</p><p><b> }</b></p><p> 編寫這兩個(gè)類后現(xiàn)在就是編寫從服務(wù)器端用程序遍歷得到全國(guó)各地的城市名與</p><p> 城市碼,并將它們分別的保存在 String[][] prov
49、inces 數(shù)組,String[][] childs 數(shù)組與</p><p> String[][] cityCode 中:</p><p> WebAccessTools webTools = new WebAccessTools(this); //得到訪問(wèn)網(wǎng)絡(luò)的內(nèi)容</p><p> String webContent=webTools.getWebCon
50、tent("http://m.weather.com.cn/data5/city.xml"); //第一次解析得到的為省份或一級(jí)直轄市</p><p> String[][] provinces = WeaterInfoParser.parseCity(webContent); String[] groups = new String[provinces.length];</p>
51、<p> 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];</p><p> //由省份碼
52、來(lái)得到城市碼</p><p> StringBuffer urlBuilder= new StringBuffer("http://m.weather.com.cn/data5/city");</p><p> urlBuilder.append(provinces[i][0]);</p><p> urlBuilder.append(&q
53、uot;.xml");</p><p> webContent = webTools.getWebContent(urlBuilder.toString());</p><p><b> 10</b></p><p> String[][] citys = WeaterInfoParser.parseCity(webConten
54、t); //用于保存所的有towns</p><p> String[][][] towns = new String[citys.length][][]; //計(jì)算總的城鎮(zhèn)數(shù)</p><p> int sum=0;</p><p> for( int j=0; j<citys.length; j++) {</p><p> /
55、/由城市碼來(lái)得到地方碼</p><p> urlBuilder= new StringBuffer("http://m.weather.com.cn/data5/city");</p><p> urlBuilder.append(citys[j][0]);</p><p> urlBuilder.append(".xml&quo
56、t;);</p><p> webContent = webTools.getWebContent(urlBuilder.toString()); towns[j] = WeaterInfoParser.parseCity(webContent);</p><p> sum = sum + towns[j].length;</p><p><b>
57、}</b></p><p> childs[i] = new String[sum];</p><p> cityCode[i] = new String[sum];</p><p><b> sum=0;</b></p><p> for( int j=0; j<citys.length; j
58、++) {</p><p> for(int n=0; n<towns[j].length; n++) {</p><p><b> if(n==0)</b></p><p> childs[i][sum] = towns[j][n][1];</p><p><b> else</b>
59、</p><p> childs[i][sum] = towns[j][0][1] + "." + towns[j][n][1];</p><p> urlBuilder= new StringBuffer("http://m.weather.com.cn/data5/city"); urlBuilder.append(towns[j][n][0
60、]); urlBuilder.append(".xml");</p><p> webContent = webTools.getWebContent(urlBuilder.toString()); String[][] code=WeaterInfoParser.parseCity(webContent); cityCode[i][sum] = code[0][1]; sum = sum
61、+ 1;</p><p><b> }</b></p><p><b> }</b></p><p> urlBuilder=null;</p><p><b> }</b></p><p> 接下來(lái)就是將得到的上面的三個(gè)數(shù)組建立數(shù)據(jù)庫(kù)文件 d
62、b_weather.db 保存起來(lái),用到 android.database.sqlite.SQLiteDatabase 類的靜態(tài)方法:</p><p> SQLiteDatabase openOrCreateDatabase(String path, CursorFactory factory)來(lái)創(chuàng)建一個(gè)數(shù)據(jù)庫(kù)文件,其中的 path 表示數(shù)據(jù)庫(kù)存放的路徑,而 factory 中游標(biāo)工廠,這里可將它設(shè)為空,從而得
63、到 SQLiteDatabase 對(duì)象,則再調(diào)用它的 execSQL(String sql)方法來(lái)執(zhí)行保存數(shù)據(jù)庫(kù)的操作,從而將上面的三個(gè)數(shù)組轉(zhuǎn)換為數(shù)據(jù)庫(kù)中的數(shù)</p><p> 據(jù),最后使用 ADT 插件中的 DDMS 工具將得到的數(shù)據(jù)庫(kù)文件從 Android 模擬器</p><p><b> 11</b></p><p> 中導(dǎo)出,最終
64、就得到了 db_weather.db 文件。以后上述的代碼就可以不使用,直接將 db_weather.db 文件放入資源文件夾 res 目錄中的 raw 目錄中,則在程序第一次運(yùn)行時(shí)導(dǎo)入到/data/data/com.weather.app/databases 目錄中就行了,其中關(guān)于數(shù)據(jù)庫(kù)的導(dǎo)入實(shí)際是 Java 中文件的復(fù)制。</p><p> 2.實(shí)現(xiàn)可伸縮性列表的的構(gòu)建與過(guò)濾</p><
65、p> 實(shí)現(xiàn)可伸縮性列表是通過(guò)繼承 android.widget.BaseExpandableListAdapter 適配器實(shí)現(xiàn)的,其中主要實(shí)現(xiàn)它的 public View getGroupView()得列表的一級(jí)列表和 public void getChildView()得到列表的二級(jí)子列表實(shí)現(xiàn)的,在這里由于只是實(shí)現(xiàn)文本顯示功能,故用 TextView 組件來(lái)填充就行了,如果要構(gòu)造這個(gè)自定義的適配器,則只需在提供存放省份直轄市的
66、一級(jí)列表的數(shù)組 String[] groups 和存放對(duì)應(yīng)的城鎮(zhèn)的二級(jí)列表的 String[][] childs 就行了。</p><p> 同時(shí)為了兼具過(guò)濾功能,還要需再實(shí)現(xiàn) android.widget.Filterable 接口,這個(gè)接口有一個(gè) getFilter()返回 Filter 過(guò)濾器的列表,故還要提供一個(gè) Filter 過(guò)濾類,在本系統(tǒng)中,實(shí)現(xiàn)的是一個(gè)內(nèi)部類 CityFilter,它繼承 and
67、roid.widget.Filter 類,覆蓋實(shí)現(xiàn)了兩個(gè)方法,一個(gè)是 performFiltering()得到 FilterResults 過(guò)濾結(jié)果對(duì)象方法,另一個(gè)是根據(jù)得到的 FilterResults 對(duì)象更新適配器的 publishResults()方法。</p><p> 其中的 performFiltering(CharSequence constraint)方法的實(shí)現(xiàn)是通過(guò) constraint 這
68、個(gè)關(guān)鍵字以省份直轄市為單位進(jìn)行匹配,如果匹配成功,則添加該省份以下的所有城市,如果匹配不成功,則再逐一與這個(gè)省份的下的城市配匹,則只添加匹配的城市,其中匹配的結(jié)果放在 Map<Integer, ArrayList<Integer>> values 這樣的向量中,再由新建的 FilterResults 封裝返回,(具體實(shí)現(xiàn)如下):</p><p> 首先是對(duì)關(guān)鍵字進(jìn)行判斷是否為空,如為空則
69、由 values 添加所有省份與城市,其中的 allGroups 和 allChilds 保存的是所有的省份與對(duì)應(yīng)的城市:</p><p> //當(dāng)過(guò)濾條件為空時(shí),返回所有的省份與城市</p><p> if(constraint == null || constraint.length() == 0) {</p><p> for(int i=0; i<
70、;allGroups.length; i++) { ArrayList<Integer> index = new ArrayList<Integer>(); //添加所有與之對(duì)應(yīng)的城市</p><p> for(int j=0; j<allChilds[i].length; j++) { index.add(j);</p><p><b> }&
71、lt;/b></p><p> values.put(i, index);</p><p><b> }</b></p><p><b> }</b></p><p> 如果關(guān)鍵字 constraint 不為空,則以省份為單位進(jìn)行匹配,省份匹配的添加下面的所在城鎮(zhèn),如果不匹配,則進(jìn)行步
72、深入匹配城鎮(zhèn),添加符合條件的城鎮(zhèn):</p><p><b> 12</b></p><p> String filterStr = constraint.toString(); for (int i=0; i<allGroups.length; i++) {</p><p> //查找省名是否包含用戶輸入的字符串</p>
73、<p> if(allGroups[i].contains(filterStr)) { ArrayList<Integer> index = new ArrayList<Integer>(); //添加所有與之對(duì)應(yīng)的城市</p><p> for(int j=0; j<allChilds[i].length; j++) { index.add(j);</p&g
74、t;<p><b> }</b></p><p> values.put(i, index);</p><p><b> } else {</b></p><p> ArrayList<Integer> index = new ArrayList<Integer>(); //如
75、果省份名沒有,則查找它下面的城市名是否包含</p><p> for(int j=0; j<allChilds[i].length; j++) { if(allChilds[i][j].contains(filterStr)) {</p><p> index.add(j);</p><p><b> }</b></p>
76、<p><b> }</b></p><p> //如果添加進(jìn)入了城市,說(shuō)明存在,則它的省份也添加進(jìn)去</p><p> if(index.size() > 0) {</p><p> values.put(i, index);</p><p><b> } else {</
77、b></p><p> index = null;</p><p><b> }</b></p><p><b> }</b></p><p><b> }</b></p><p> 得到過(guò)濾的結(jié)果后將其用 FilterResource
78、封裝后返回:</p><p> FilterResults results = new FilterResults(); results.values = values; results.count = values.size();</p><p> 另外的 publishResults(CharSequence constraint, FilterResults results)方法
79、就是根據(jù)上面得到的 results 對(duì)象來(lái)得到新的 String[] groups 與 String[][] Childs 數(shù)組,再調(diào)用 BaseExpandableListAdapter 父類的 notifyDataSetChanged()方法來(lái)更新列表,從而實(shí)現(xiàn)過(guò)濾后結(jié)果的顯示(具體實(shí)現(xiàn)如下):</p><p> 首先將參數(shù) FiltersResuls 對(duì)象轉(zhuǎn)換為 Map<Integer, Array
80、List<Integer>> filterResult,然后來(lái)判斷過(guò)濾后的結(jié)果長(zhǎng)度時(shí)否為 0,如果長(zhǎng)度為 0 則說(shuō)明過(guò)濾后的結(jié)果為空,則調(diào)用父類的 notifyDataSetInvalidated()方法來(lái)阻止列表的更新:</p><p> 如果長(zhǎng)度不為 0,則說(shuō)明存在過(guò)濾結(jié)果,則將它轉(zhuǎn)換為 groups 數(shù)組與 childs</p><p> 數(shù)組,并調(diào)用 noti
81、fyDataSetChanged()方法實(shí)再更新:</p><p><b> 13</b></p><p> String[] newGroups = new String[count];</p><p> String[][] newChilds = new String[count][];</p><p>
82、int index = 0;</p><p> int length = 0;</p><p> //得到新的groups和childs</p><p> for(int i=0; i<allGroups.length; i++) { if(filterResult.containsKey(i)) {</p><p> newG
83、roups[index] = allGroups[i];</p><p><b> //符合條件的城市</b></p><p> ArrayList<Integer> citys = filterResult.get(i); length = citys.size();</p><p> newChilds[index] =
84、new String[length]; for(int j = 0; j< length; j++) {</p><p> newChilds[index][j] = allChilds[i][citys.get(j)];</p><p><b> }</b></p><p> index = index + 1;</p>
85、;<p><b> }</b></p><p><b> }</b></p><p> //設(shè)置groups和childs</p><p> groups = newGroups;</p><p> childs = newChilds;</p><p&g
86、t;<b> //更新列表</b></p><p> notifyDataSetChanged();</p><p> //判斷是否展開列表</p><p> count = getGroupCount();</p><p> if(count < 34) {</p><p>&l
87、t;b> //展開伸縮性列表</b></p><p> for(int i=0; i<count; i++) {</p><p> provinceList.expandGroup(i);</p><p><b> }</b></p><p><b> } else {<
88、/b></p><p><b> //收縮伸縮性列表</b></p><p> for(int i=0; i<count; i++) {</p><p> provinceList.collapseGroup(i);</p><p><b> }</b></p>&
89、lt;p><b> }</b></p><p> 如上所述則就實(shí)現(xiàn)了帶有過(guò)濾性可伸展性列表適配性的實(shí)現(xiàn),則在使用時(shí)在</p><p> XML 組件配置文件中使用 ExpandableListView 列表,并調(diào)用它的 setAdapter()方</p><p> 法來(lái),加載自定義的適配器。而在使用它的過(guò)濾功能時(shí)則調(diào)用自定義適配器
90、的</p><p> getFilter()得到過(guò)濾 Filter 對(duì)象,再調(diào)用 Filter 對(duì)象的 filter(String)方法實(shí)現(xiàn)的,在</p><p> 本系統(tǒng)中才用的時(shí)觸發(fā)文本輸入框 EditText 的 TextChangedListener 事件時(shí)調(diào)用從而實(shí)現(xiàn)手動(dòng)選擇預(yù)報(bào)城市的過(guò)濾查詢。</p><p><b> 14</b&
91、gt;</p><p> 3.GPS 定位功能的實(shí)現(xiàn)</p><p> Android 中調(diào)用 GPS 功能,首先要獲取 GPS 定位管理器 LocationManager,獲取 LocationManager 后就是獲取 LocationProvider,可以通過(guò) Criteria 對(duì)象設(shè)置過(guò)濾條件來(lái)獲得最符合用戶需求的 LocationProvider,得到 LocationPro
92、vider 后就可通過(guò)調(diào)用 LocationMananger 對(duì)象的 getLastKnownLocation() 方法來(lái)獲取 Location 地址封裝對(duì)象,最后由實(shí)例化的 Geocoder 將 Location 中的經(jīng)度和緯度反編譯為地址信息集合 List 對(duì)象,從而由 List 對(duì)象來(lái)得到當(dāng)前用戶地址名。在開發(fā)過(guò)程中通過(guò) Eclipse 中的 ADT 插件的 DDMS 可以為 Android 模擬器指定任意地址,如下:</p
93、><p> 當(dāng)在模擬器控制面板中指定經(jīng)緯度后,則會(huì)在模擬器中出現(xiàn) GPS 的標(biāo)志:</p><p> 但在實(shí)際開發(fā)調(diào)用 GPS 功能過(guò)程時(shí),只能獲取經(jīng)度與緯度,而在使用 Geocoder 反編譯地址時(shí)報(bào)錯(cuò):</p><p> 使用的調(diào)用代碼如下:</p><p> 后來(lái)通過(guò)網(wǎng)上搜索得知在 Android2.2 模擬器中調(diào)用 Geocode
94、r 需要 backend 服務(wù): ”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.“</p
95、><p><b> 15</b></p><p> 但并有說(shuō)此服務(wù)要怎么得到,這看起來(lái)像是 Android2.2 模擬器的一個(gè) Bug,故而在本設(shè)計(jì)中采用訪問(wèn)[http://maps.google.cn/maps/geo?output=xml&q=經(jīng)度,緯度]的形式來(lái)得到詳備的地址信息(來(lái)源于:http://www.iteye.com/problems/695
96、17),如下訪問(wèn) http://maps.google.cn/maps/geo?output=xml&q=30.659269,104.065762:</p><p> 其中的 output 參數(shù)指定的是服務(wù)器響應(yīng)的格式,除了 XML 格式還可以為 JSON, CSV 等格式。</p><p> 由此可知,為了實(shí)現(xiàn) GPS 的定位功能還需要實(shí)現(xiàn)一個(gè)解析 XML 的工具類,在本&l
97、t;/p><p> 系統(tǒng)中由工具類 LocationXMParser 完成,它繼承至 org.xml.sax.helpers.DefaultHandler</p><p> 類,用于專門用于解析 XML 文件。</p><p> 上述的 GPS 功能具體實(shí)現(xiàn)過(guò)程如下:</p><p> 1.得到 LocationManager 系統(tǒng)定位
98、服務(wù)管理者:</p><p> LocationManager locationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);</p><p><b> 16</b></p><p> 設(shè)置 Geocoder 對(duì)象,過(guò)濾得到符合條件的 Locat
99、ionProvider ,再由 LocationProvider 得到封裝經(jīng)緯度信息的 Location 對(duì)象:</p><p> //設(shè)置一個(gè)Criteria標(biāo)準(zhǔn)用于過(guò)濾LocationProvider</p><p> Criteria criteria = new Criteria();</p><p> //設(shè)置不需要高度信息</p>&
100、lt;p> criteria.setAltitudeRequired(false);</p><p> //設(shè)置不需要方位信息</p><p> criteria.setBearingRequired(false);</p><p> //得到最好的可用的Provider</p><p> String provider =
101、locationManager.getBestProvider(criteria, true); //得到當(dāng)前的位置對(duì)象</p><p> Location location = locationManager.getLastKnownLocation(provider); double latitude = location.getLatitude(); //得到經(jīng)度</p><p>
102、 double longitude = location.getLongitude(); //得到緯度</p><p> 得到經(jīng)緯度后再訪問(wèn) http://maps.google.cn/maps/geo 來(lái)得到含地址信息的</p><p> XML 文本內(nèi)容,并用自定義的 LocationXMParser 工具類解析封裝得到此經(jīng)緯度對(duì)應(yīng)的城市名:</p><p&g
103、t; //根據(jù)經(jīng)緯度得到詳細(xì)的地址信息</p><p> //定義的一個(gè)網(wǎng)絡(luò)訪問(wèn)工具類</p><p> WebAccessTools webTools = new WebAccessTools(this); String addressContext = webTools.getWebContent</p><p> ("http://maps.
104、google.cn/maps/geo?output=xml&q="+ latitude+","+longitude);</p><p><b> //解析地址信息</b></p><p> SAXParserFactory spf = SAXParserFactory.newInstance(); try {</p>
105、;<p> SAXParser parser = spf.newSAXParser(); XMLReader reader = parser.getXMLReader(); LocationXMLParser handler = new LocationXMLParser(); reader.setContentHandler(handler);</p><p> StringReader re
106、ad = new StringReader(addressContext);</p><p> 創(chuàng)建新的輸入源SAX 解析器將使用 InputSource 對(duì)象來(lái)確定如何讀取 XML 輸入</p><p> InputSource source = new InputSource(read);</p><p><b> //開始解析</b>
107、;</p><p> reader.parse(source);</p><p> //判斷是否存在地址</p><p> if(handler.hasAddress())</p><p> return handler.getDetailAddress(); } catch (Exception e) {</p>&l
108、t;p> e.printStackTrace();</p><p><b> }</b></p><p><b> 17</b></p><p> 上面代碼中的 getDetailAdress()方法返回的是一個(gè) Map 對(duì)象,其中封裝了從 XML 中解析得到的國(guó)家、省份、縣區(qū)和城市四個(gè)信息,在得到這些信息后
109、,系統(tǒng)將與數(shù)據(jù)庫(kù)中預(yù)存的省份城市相比較,最終匹配得到該地區(qū)的城市碼完成 GPS 自動(dòng)定位功能的實(shí)現(xiàn)。</p><p> 4.Widget 窗體小部件的更新</p><p> 由于 widget 中的時(shí)鐘關(guān)系,需要對(duì) widget 顯示進(jìn)行時(shí)刻的更新用來(lái)保持與系統(tǒng)中時(shí)間的一致。實(shí)現(xiàn)這個(gè)功能需要用到 AlarmManager 類,這個(gè)類專門用來(lái)設(shè)定在某個(gè)指定的時(shí)間去完成指定的事件。設(shè)計(jì)思路
110、是在 Widget 的 onUpdate 方法中啟動(dòng)一個(gè)自定義更新后臺(tái)服務(wù),更新 widget,并設(shè)定下一分鐘再次調(diào)用此服務(wù)。具體實(shí)現(xiàn)過(guò)步驟如下:</p><p> 首先自定義一個(gè)后臺(tái)運(yùn)行服務(wù)類繼承至 Service 類,實(shí)現(xiàn)它的服務(wù)開始運(yùn)行調(diào)用的 onStart()方法:</p><p> super.onStart(intent, startId);</p><
111、p> //得到widget的布局對(duì)象</p><p> RemoteViews views = WeatherWidget.getWeatherView(this); //得到AppWidgetManager widget管理器</p><p> AppWidgetManager appWidgetManager=AppWidgetManager.getInstance(thi
112、s); int[] appids=appWidgetManager.getAppWidgetIds(new ComponentName(this,</p><p> WeatherWidget.class));</p><p> //得到城市碼,并更新天氣</p><p> SharedPreferences sp=getSharedPreferences(&
113、lt;/p><p> SetCityActivity.CITY_CODE_FILE,</p><p> SetCityActivity.MODE_PRIVATE);</p><p> String cityCode= sp.getString("code", "");</p><p> if(cit
114、yCode!=null&&cityCode.trim().length() > 0) { WeatherWidget.updateAppWidget(views, this,</p><p> appWidgetManager, cityCode);</p><p><b> }</b></p><p> appWi
115、dgetManager.updateAppWidget(appids, views); //獲取當(dāng)前時(shí)間設(shè)置警報(bào)服務(wù)</p><p> Date date = new Date();</p><p> long now =date.getTime();</p><p> long unit=60000;//間隔一分鐘</p><p>
116、 int s=date.getSeconds();//得到秒數(shù)</p><p> unit=60000-s*1000;//將時(shí)間精確到秒</p><p> pintent=PendingIntent.getService(this, 0, intent, 0);</p><p><b> //計(jì)時(shí)器</b></p>&l
117、t;p> alarm=(AlarmManager)getSystemService(Context.ALARM_SERVICE);</p><p> //AlarmManager.RTC_WAKEUP設(shè)置服務(wù)在系統(tǒng)休眠時(shí)同樣會(huì)運(yùn)行</p><p> //第二個(gè)參數(shù)是下一次啟動(dòng)service時(shí)間</p><p> alarm.set(AlarmManag
118、er.RTC_WAKEUP, now+unit, pintent);</p><p><b> 18</b></p><p> 然后在實(shí)現(xiàn) AppWidgetProvider 的 widget 類的 onUpdate 方法中啟動(dòng)這個(gè)自定義的服務(wù):</p><p> //啟動(dòng)一個(gè)自定義更新widget的后臺(tái)服務(wù)</p><
119、;p> context.startService(new Intent(context,UpdateWidgetService.class));</p><p> 除了啟動(dòng)這個(gè)服務(wù)是不夠的,當(dāng)用戶刪除 widget 部件時(shí),后臺(tái)服務(wù)也必須停止,這樣就必須實(shí)現(xiàn) Service 類中的另一個(gè)方法 onDestroy()方法,該方法在 Service 停止時(shí)調(diào)用,在這里用于取消 AlarmManager 設(shè)置
120、的警報(bào)服務(wù):</p><p> //當(dāng)widget中通過(guò)調(diào)用context.stopService方法來(lái)指定銷毀service時(shí),被調(diào)用 public void onDestroy() {</p><p><b> //取消定時(shí)管理</b></p><p> if( alarm!=null) {</p><p>
121、 alarm.cancel(pintent);</p><p><b> }</b></p><p> super.onDestroy();</p><p><b> }</b></p><p> 則在 widget 類的 onDisabled()方法中調(diào)用 stopService 方法來(lái)停
122、止后臺(tái)服務(wù),</p><p> 其中的 onDisabled 方法在 widget 被用戶刪除時(shí)由系統(tǒng)自動(dòng)調(diào)用:</p><p> public void onDisabled(Context context) { super.onDisabled(context);</p><p><b> //關(guān)閉后臺(tái)服務(wù)</b></p>
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 眾賞文庫(kù)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 手機(jī)天氣預(yù)報(bào)系統(tǒng)畢業(yè)論文
- 畢業(yè)論文——手機(jī)天氣預(yù)報(bào)系統(tǒng)畢業(yè)設(shè)計(jì)
- 畢業(yè)論文——手機(jī)天氣預(yù)報(bào)系統(tǒng)畢業(yè)設(shè)計(jì)
- android3g手機(jī)天氣預(yù)報(bào)系統(tǒng)-畢業(yè)論文
- 手機(jī)天氣預(yù)報(bào)系統(tǒng)
- 手機(jī)天氣預(yù)報(bào)系統(tǒng)畢業(yè)設(shè)計(jì).pdf
- 手機(jī)天氣預(yù)報(bào)系統(tǒng)畢業(yè)設(shè)計(jì).pdf
- 基于android手機(jī)天氣預(yù)報(bào)系統(tǒng)
- 基于android手機(jī)移動(dòng)天氣預(yù)報(bào)系統(tǒng)
- 基于android系統(tǒng)天氣預(yù)報(bào)應(yīng)用程序畢業(yè)論文
- 基于Android手機(jī)的天氣預(yù)報(bào)查詢系統(tǒng).pdf
- 基于遠(yuǎn)程調(diào)用數(shù)據(jù)的天氣預(yù)報(bào)系---畢業(yè)論文
- 基于android平臺(tái)的天氣預(yù)報(bào)系統(tǒng)的設(shè)計(jì)與開發(fā)畢業(yè)論文
- android平臺(tái)天氣預(yù)報(bào)軟件設(shè)計(jì)與實(shí)現(xiàn) 畢業(yè)論文
- android平臺(tái)天氣預(yù)報(bào)widget的設(shè)計(jì)與實(shí)現(xiàn)畢業(yè)論文
- android平臺(tái)天氣預(yù)報(bào)widget的設(shè)計(jì)與實(shí)現(xiàn)畢業(yè)論文
- 短期天氣預(yù)報(bào)試題庫(kù)天氣預(yù)報(bào)概要
- 專題天氣預(yù)報(bào)
- 農(nóng)用天氣預(yù)報(bào)
- 《天氣預(yù)報(bào)》教案
評(píng)論
0/150
提交評(píng)論