版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
《Android手機(jī)開(kāi)發(fā)》第20-22課
Android天氣預(yù)報(bào)短信服務(wù)軟件
——項(xiàng)目設(shè)計(jì)與開(kāi)發(fā)
講授:劉發(fā)久《Android手機(jī)開(kāi)發(fā)》第20-22課
Android本章學(xué)習(xí)目標(biāo):掌握Android應(yīng)用項(xiàng)目的開(kāi)發(fā)過(guò)程掌握Android應(yīng)用項(xiàng)目的需求分析掌握Android應(yīng)用項(xiàng)目的系統(tǒng)設(shè)計(jì)掌握Android應(yīng)用項(xiàng)目的實(shí)現(xiàn)方法掌握Android應(yīng)用項(xiàng)目的測(cè)試方法本章學(xué)習(xí)目標(biāo):20.1
需求分析
設(shè)計(jì)本章的初衷希望能夠根據(jù)實(shí)際項(xiàng)目的需求,準(zhǔn)確的分析出Android應(yīng)用程序開(kāi)發(fā)所可能涉及到的知識(shí)點(diǎn),并學(xué)會(huì)如何通過(guò)分析軟件的需求,快速的設(shè)計(jì)出應(yīng)用程序的用戶界面和模塊結(jié)構(gòu),并最終完成應(yīng)用程序的開(kāi)發(fā)和調(diào)試20.1需求分析
設(shè)計(jì)本章的初衷20.1
需求分析功能需求本章提供的“天氣預(yù)報(bào)短信服務(wù)軟件”綜合示例中,有一個(gè)顯示天氣情況的用戶界面,可以通過(guò)圖片和文字顯示當(dāng)前和未來(lái)幾天的天氣狀況,包括溫度、濕度、風(fēng)向和雨雪情況等。這些天氣數(shù)據(jù)是通過(guò)后臺(tái)服務(wù)獲取的,這個(gè)后臺(tái)服務(wù)可以按照一定時(shí)間間隔,從Google上獲取天氣預(yù)報(bào)信息,并將天氣信息保存在后臺(tái)服務(wù)中。示例還需要提供基于SMS短信的天氣數(shù)據(jù)服務(wù),其他手機(jī)用戶可以向本示例所在的手機(jī)上發(fā)送SMS短信,并在短信中包含用戶指定的關(guān)鍵字,則可以將保存在后臺(tái)服務(wù)中的天氣情況,再通過(guò)SMS短信回復(fù)給用戶。最后,每個(gè)被發(fā)送的SMS短信都要被記錄下來(lái),用戶可以瀏覽或刪除這些回復(fù)信息20.1需求分析功能需求20.1
需求分析界面需求本示例包含三個(gè)主要的用戶界面顯示天氣預(yù)報(bào)的用戶界面顯示已發(fā)送SMS短信的用戶界面瀏覽和設(shè)置配置信息的用戶界面20.1需求分析界面需求20.1
需求分析內(nèi)部功能隱藏在用戶界面后面的內(nèi)部功能,是用戶界面能夠正確實(shí)現(xiàn)的基礎(chǔ)顯示天氣預(yù)報(bào)的用戶界面獲取Google的天氣數(shù)據(jù)顯示SMS短信的用戶界面根據(jù)關(guān)鍵字監(jiān)視SMS短信發(fā)送包含天氣信息的SMS短信將發(fā)送的SMS短信寫入數(shù)據(jù)庫(kù)瀏覽和設(shè)置配置信息的用戶界面將用戶設(shè)置的配置信息保存到數(shù)據(jù)庫(kù)啟動(dòng)時(shí)讀取數(shù)據(jù)庫(kù)中的配置信息恢復(fù)缺省設(shè)置20.1需求分析內(nèi)部功能20.2
項(xiàng)目設(shè)計(jì)20.2.1用戶界面設(shè)計(jì)詳細(xì)分析應(yīng)用程序中三個(gè)主要用戶界面包含的顯示內(nèi)容在“顯示天氣預(yù)報(bào)的用戶界面”中,根據(jù)Google可以提供的數(shù)據(jù),在界面上可以顯示當(dāng)前的天氣狀況,包括城市名稱、溫度、濕度、風(fēng)向、雨雪情況和獲取數(shù)據(jù)時(shí)間等信息;還可以顯示未來(lái)四天的天氣狀況,但僅包括溫度和雨雪情況在“顯示已發(fā)送SMS短信的用戶界面”中,應(yīng)顯示每個(gè)回復(fù)短信的時(shí)間、目標(biāo)手機(jī)號(hào)碼、城市名稱、當(dāng)天的天氣狀況和未來(lái)一天的天氣狀況在“瀏覽和設(shè)置配置信息的用戶界面”中,應(yīng)顯示獲取天氣預(yù)報(bào)的目標(biāo)城市名稱、獲取數(shù)據(jù)的頻率和短信的關(guān)鍵字,并允許用戶設(shè)置是否提供短信服務(wù)以及是否記錄回復(fù)的短信信息20.2項(xiàng)目設(shè)計(jì)20.2.1用戶界面設(shè)計(jì)20.2項(xiàng)目設(shè)計(jì)20.2.1用戶界面設(shè)計(jì)用戶界面的草圖20.2項(xiàng)目設(shè)計(jì)20.2.1用戶界面設(shè)計(jì)20.2項(xiàng)目設(shè)計(jì)20.2.2數(shù)據(jù)庫(kù)設(shè)計(jì)本示例主要存儲(chǔ)兩種數(shù)據(jù)配置信息:因?yàn)榕渲眯畔⒌臄?shù)據(jù)量很小,從Android支持的存儲(chǔ)方式上分析,可以保存在SharePreference、文件或SQLite數(shù)據(jù)庫(kù)中SMS短信服務(wù)信息:
SMS短信服務(wù)信息是一個(gè)隨著時(shí)間推移而不斷增加的數(shù)據(jù),屬于文本信息,而且有固定的格式,因此適合使用SQLite數(shù)據(jù)庫(kù)進(jìn)行存儲(chǔ)綜合分析這兩種需要存儲(chǔ)的數(shù)據(jù),選擇SQLite數(shù)據(jù)庫(kù)作為存儲(chǔ)數(shù)據(jù)的方法20.2項(xiàng)目設(shè)計(jì)20.2.2數(shù)據(jù)庫(kù)設(shè)計(jì)20.2項(xiàng)目設(shè)計(jì)20.2.2數(shù)據(jù)庫(kù)設(shè)計(jì)配置信息配置信息中主要保存天氣信息查詢的城市名稱,訪問(wèn)Google更新天氣信息的頻率,請(qǐng)求天氣信息SMS短信的關(guān)鍵字,以及是否提供短信服務(wù)和是否記錄短信服務(wù)內(nèi)容配置信息的數(shù)據(jù)庫(kù)表結(jié)構(gòu)屬性數(shù)據(jù)類型說(shuō)明_idinteger自動(dòng)增加的主鍵city_nametext進(jìn)行天氣信息查詢的城市名refresh_speedtext進(jìn)行天氣信息查詢的頻率,單位為秒/次sms_servicetext是否提供短信服務(wù),即接收到請(qǐng)求短信后是否回復(fù)包含天氣信息的短信sms_infotext是否記錄發(fā)出的SMS短信的信息key_wordtext短信服務(wù)的關(guān)鍵字,用以確定哪條短信是請(qǐng)求天氣服務(wù)的短信20.2項(xiàng)目設(shè)計(jì)20.2.2數(shù)據(jù)庫(kù)設(shè)計(jì)屬性數(shù)據(jù)類型說(shuō)明_20.2項(xiàng)目設(shè)計(jì)20.2.2數(shù)據(jù)庫(kù)設(shè)計(jì)SMS短信服務(wù)信息SMS短信服務(wù)信息主要保存請(qǐng)求服務(wù)短信的發(fā)送者、短信內(nèi)容、接收時(shí)間和回復(fù)信息的內(nèi)容SMS短信服務(wù)信息的數(shù)據(jù)庫(kù)表結(jié)構(gòu)屬性數(shù)據(jù)類型說(shuō)明_idinteger自動(dòng)增加的主鍵sms_sendertext請(qǐng)求服務(wù)短信的發(fā)送者sms_bodytext請(qǐng)求服務(wù)短信的內(nèi)容信息sms_receive_timetext接收到請(qǐng)求服務(wù)短信的時(shí)間return_resulttext回復(fù)短信的內(nèi)容20.2項(xiàng)目設(shè)計(jì)20.2.2數(shù)據(jù)庫(kù)設(shè)計(jì)屬性數(shù)據(jù)類型說(shuō)明_20.2項(xiàng)目設(shè)計(jì)20.2.3程序模塊設(shè)計(jì)從功能需求上分析,可以將整個(gè)應(yīng)用程序劃分為4個(gè)模塊,分別是用戶界面、后臺(tái)服務(wù)、數(shù)據(jù)庫(kù)適配器和短信監(jiān)聽(tīng)器。下圖是模塊結(jié)構(gòu)圖20.2項(xiàng)目設(shè)計(jì)20.2.3程序模塊設(shè)計(jì)20.2項(xiàng)目設(shè)計(jì)20.2.3程序模塊設(shè)計(jì)由模塊結(jié)構(gòu)圖中可知,后臺(tái)服務(wù)是整個(gè)應(yīng)用程序的核心,主要包含兩個(gè)子模塊,一個(gè)是“數(shù)據(jù)獲取模塊”,負(fù)責(zé)周期性的從Google獲取天氣信息;另一個(gè)是“短信服務(wù)模塊”,負(fù)責(zé)處理接收到的服務(wù)請(qǐng)求短信,并發(fā)送包含天氣信息的短信后臺(tái)服務(wù)由用戶界面通過(guò)Intent啟動(dòng),啟動(dòng)后的后臺(tái)服務(wù)可以在用戶界面關(guān)閉后仍然保持運(yùn)行狀態(tài),直到用戶通過(guò)用戶界面發(fā)送Intent停止服務(wù),或系統(tǒng)因資源不足而強(qiáng)行關(guān)閉服務(wù)20.2項(xiàng)目設(shè)計(jì)20.2.3程序模塊設(shè)計(jì)20.2項(xiàng)目設(shè)計(jì)20.2.3程序模塊設(shè)計(jì)用戶界面從后臺(tái)服務(wù)獲取天氣信息,而沒(méi)有直接通過(guò)網(wǎng)絡(luò)訪問(wèn)Google的天氣數(shù)據(jù)一方面是因?yàn)楹笈_(tái)服務(wù)使用了工作線程,通過(guò)后臺(tái)服務(wù)獲取天氣數(shù)據(jù)可以避免因網(wǎng)絡(luò)通信不暢造成界面失去響應(yīng)另一方面,在用戶關(guān)閉界面后,后臺(tái)服務(wù)仍然需要更新天氣信息,以保證短信服務(wù)數(shù)據(jù)的準(zhǔn)確性。用戶界面還會(huì)調(diào)用數(shù)據(jù)庫(kù)適配器,向SQLite數(shù)據(jù)庫(kù)中寫入、讀取配置信息,或?qū)MS短信服務(wù)信息進(jìn)行操作20.2項(xiàng)目設(shè)計(jì)20.2.3程序模塊設(shè)計(jì)20.2項(xiàng)目設(shè)計(jì)20.2.3程序模塊設(shè)計(jì)短信監(jiān)聽(tīng)器是一個(gè)BroadcastReceiver,監(jiān)視所有接收到的短信如果短信中包含用戶自定義的關(guān)鍵字,短信監(jiān)聽(tīng)器則會(huì)認(rèn)為這條短信是天氣服務(wù)請(qǐng)求短信,將短信的相關(guān)信息寫入后臺(tái)服務(wù)的短信服務(wù)隊(duì)列如果用戶在配置信息中選擇無(wú)需提供短信服務(wù),短信監(jiān)聽(tīng)器仍然繼續(xù)監(jiān)聽(tīng)所有短信,只是后臺(tái)服務(wù)不再允許將服務(wù)請(qǐng)求短信寫入服務(wù)隊(duì)列數(shù)據(jù)庫(kù)適配器封裝了所有對(duì)SQLite數(shù)據(jù)庫(kù)操作的方法,用戶界面和后臺(tái)服務(wù)會(huì)調(diào)用它實(shí)現(xiàn)數(shù)據(jù)庫(kù)操作20.2項(xiàng)目設(shè)計(jì)20.2.3程序模塊設(shè)計(jì)20.3
程序開(kāi)發(fā)
20.3.1文件結(jié)構(gòu)與用途在程序開(kāi)發(fā)階段,首先確定“天氣預(yù)報(bào)短信服務(wù)軟件”的工程名稱為WeatherDemo,包名稱為edu.hrbeu.WeatherDemo,據(jù)程序模塊設(shè)計(jì)的內(nèi)容,建立WeatherDemo示例20.3程序開(kāi)發(fā)
20.3.1文件結(jié)構(gòu)與用途20.3
程序開(kāi)發(fā)20.3.1文件結(jié)構(gòu)與用途W(wǎng)eatherDemo示例源代碼的文件結(jié)構(gòu)20.3程序開(kāi)發(fā)20.3.1文件結(jié)構(gòu)與用途20.3
程序開(kāi)發(fā)20.3.1文件結(jié)構(gòu)與用途W(wǎng)eatherDemo示例設(shè)置了多個(gè)命名空間,分別用來(lái)保存用戶界面、數(shù)據(jù)庫(kù)、后臺(tái)服務(wù)、SMS短信和天氣數(shù)據(jù)的源代碼文件WeatherDemo示例的命名空間命名空間說(shuō)明edu.hrbeu.WeatherDemo存放與用戶界面相關(guān)的源代碼文件edu.hrbeu.WeatherDemo.DB存放與SQLite數(shù)據(jù)庫(kù)相關(guān)的源代碼文件edu.hrbeu.WeatherDemo.Service存放與后臺(tái)服務(wù)相關(guān)的源代碼文件edu.hrbeu.WeatherDemo.SMS存放與SMS短信相關(guān)的源代碼文件edu.hrbeu.WeatherDemo.Weather存放與天氣數(shù)據(jù)有關(guān)的源代碼文件20.3程序開(kāi)發(fā)20.3.1文件結(jié)構(gòu)與用途命名空間說(shuō)明e20.3
程序開(kāi)發(fā)20.3.1文件結(jié)構(gòu)與用途W(wǎng)eatherDemo示例將不同用途的源代碼文件放置在不同的命名空間中包名稱文件名說(shuō)明.WeatherDemoHistoryActivity.java“歷史數(shù)據(jù)”頁(yè)的ActivitySetupActivity.java“系統(tǒng)設(shè)置”頁(yè)的ActivityWeatherActivity.java“天氣預(yù)報(bào)”頁(yè)的ActivityWeatherDemo.java程序啟動(dòng)缺省的Activity.WeatherDemo.DBConfig.java保存配置信息的類DBAdapter.java數(shù)據(jù)庫(kù)適配器.WeatherDemo.ServiceSmsReceiver.java短信監(jiān)聽(tīng)器WeatherAdapter.java數(shù)據(jù)獲取模塊WeatherService.java后臺(tái)服務(wù).WeatherDemo.SMSSimpleSms.java簡(jiǎn)化的SMS短信類SmsAdapter.java短信發(fā)送模塊.WeatherDemo.WeatherForecast.java未來(lái)天氣信息的類Weather.java當(dāng)前天氣信息的類20.3程序開(kāi)發(fā)20.3.1文件結(jié)構(gòu)與用途包名稱文件名說(shuō)20.3
程序開(kāi)發(fā)20.3.1文件結(jié)構(gòu)與用途Android的資源文件保存在/res的子目錄中/res/drawable目錄中保存的是圖像文件/res/layout目錄中保存的是布局文件/res/values目錄中保存的是用來(lái)定義字符串和顏色的文件/res/xml目錄保存的是XML格式的數(shù)據(jù)文件所有在程序開(kāi)發(fā)階段可以被調(diào)用的資源都保存在這些目錄中20.3程序開(kāi)發(fā)20.3.1文件結(jié)構(gòu)與用途20.3
程序開(kāi)發(fā)20.3.1文件結(jié)構(gòu)與用途資源文件名稱與用途資源目錄文件說(shuō)明drawableicon.png圖標(biāo)文件sunny.png調(diào)試用的天氣圖片tab_history.pngTabHost中“歷史數(shù)據(jù)”頁(yè)的圖片tab_setup.pngTabHost中“系統(tǒng)設(shè)置”頁(yè)的圖片tab_weather.pngTabHost中“天氣預(yù)報(bào)”頁(yè)的圖片layoutdata_row.xml“歷史數(shù)據(jù)”頁(yè)ListActivity的每行數(shù)據(jù)的布局tab_history.xmlTabHost中“歷史數(shù)據(jù)”頁(yè)的布局tab_setup.xmlTabHost中“系統(tǒng)設(shè)置”頁(yè)的布局tab_weather.xmlTabHost中“天氣預(yù)報(bào)”頁(yè)的布局valuescolor.xml保存顏色的XML文件string.xml保存字符串的XML文件xmlapi.xml從Google下載的天氣數(shù)據(jù)文件。在程序運(yùn)行時(shí)沒(méi)有實(shí)際作用,但在開(kāi)發(fā)過(guò)程中可以讓讀者了解數(shù)據(jù)格式20.3程序開(kāi)發(fā)20.3.1文件結(jié)構(gòu)與用途資源目錄文件說(shuō)20.3
程序開(kāi)發(fā)20.3.2數(shù)據(jù)庫(kù)適配器數(shù)據(jù)庫(kù)適配器是最底層的模塊,主要用于封裝用戶界面和后臺(tái)服務(wù)對(duì)SQLite數(shù)據(jù)庫(kù)的操作,數(shù)據(jù)庫(kù)適配器的核心代碼主要在DBAdapter.java文件中用戶保存配置信息的類文件Config.javaConfig.java文件的全部代碼如下packageedu.hrbeu.WeatherDemo.DB;
publicclassConfig{ publicstaticStringCityName; publicstaticStringRefreshSpeed; publicstaticStringProvideSmsService; publicstaticStringSaveSmsInfo; publicstaticStringKeyWord;
20.3程序開(kāi)發(fā)20.3.2數(shù)據(jù)庫(kù)適配器package20.3
程序開(kāi)發(fā)20.3.2數(shù)據(jù)庫(kù)適配器從代碼中不難看出,公有靜態(tài)屬性CityName、RefreshSpeed、ProvideSmsService、SaveSmsInfo和KeyWord,完全對(duì)應(yīng)數(shù)據(jù)庫(kù)中保存配置信息表的屬性。在程序啟動(dòng)后,保存在數(shù)據(jù)庫(kù)中的城市名稱、更新頻率、是否提供短信服務(wù)、是否保存短信信息和關(guān)鍵字等內(nèi)容,將被寫入這個(gè)Config類中,供其他模塊在做邏輯判斷時(shí)使用publicstaticvoidLoadDefaultConfig(){ CityName=""; RefreshSpeed="60"; ProvideSmsService="true"; SaveSmsInfo="true"; KeyWord="NY"; }}20.3程序開(kāi)發(fā)20.3.2數(shù)據(jù)庫(kù)適配器publics20.3
程序開(kāi)發(fā)20.3.2數(shù)據(jù)庫(kù)適配器代碼第10行的LoadDefaultConfig()函數(shù),保存了程序內(nèi)置的配置參數(shù)此函數(shù)會(huì)在兩個(gè)情況下被調(diào)用用戶主動(dòng)選擇“恢復(fù)缺省設(shè)置”首次啟動(dòng)程序時(shí),用來(lái)初始化保存配置參數(shù)的數(shù)據(jù)庫(kù)DBAdapter類與以往介紹過(guò)的數(shù)據(jù)庫(kù)適配器類相似,都具有繼承SQLiteOpenHelper的幫助類DBOpenHelperDBOpenHelper在建立數(shù)據(jù)庫(kù)時(shí),同時(shí)建立兩個(gè)數(shù)據(jù)庫(kù)表,并對(duì)保存配置信息的表進(jìn)行了初始化,初始化的相關(guān)代碼在第42~49行20.3程序開(kāi)發(fā)20.3.2數(shù)據(jù)庫(kù)適配器20.3
程序開(kāi)發(fā)20.3.2數(shù)據(jù)庫(kù)適配器privatestaticfinalStringDB_NAME="weather_app.db";privatestaticfinalStringDB_TABLE_CONFIG="setup_config";privatestaticfinalStringDB_CONFIG_ID="1";privatestaticfinalintDB_VERSION=1;
publicstaticfinalStringKEY_ID="_id";publicstaticfinalStringKEY_CITY_NAME="city_name";publicstaticfinalStringKEY_REFRESH_SPEED="refresh_speed";publicstaticfinalStringKEY_SMS_SERVICE="sms_service";publicstaticfinalStringKEY_SMS_INFO="sms_info";publicstaticfinalStringKEY_KEY_WORD="key_word";
privatestaticfinalStringDB_TABLE_SMS="sms_data";publicstaticfinalStringKEY_SENDER="sms_sender";publicstaticfinalStringKEY_BODY="sms_body";publicstaticfinalStringKEY_RECEIVE_TIME="sms_receive_time";publicstaticfinalStringKEY_RETURN_RESULT="return_result";
20.3程序開(kāi)發(fā)20.3.2數(shù)據(jù)庫(kù)適配器private20.3
程序開(kāi)發(fā)20.3.2數(shù)據(jù)庫(kù)適配器/**靜態(tài)Helper類,用于建立、更新和打開(kāi)數(shù)據(jù)庫(kù)*/privatestaticclassDBOpenHelperextendsSQLiteOpenHelper{publicDBOpenHelper(Contextcontext,Stringname,CursorFactoryfactory,intversion){super(context,name,factory,version);}
privatestaticfinalStringDB_CREATE_CONFIG="createtable"+DB_TABLE_CONFIG+"("+KEY_ID+"integerprimarykeyautoincrement,"+KEY_CITY_NAME+"textnotnull,"+KEY_REFRESH_SPEED+"text,"+KEY_SMS_SERVICE+"text,"+KEY_SMS_INFO+"text,"+KEY_KEY_WORD+"text);";
privatestaticfinalStringDB_CREATE_SMS="createtable"+DB_TABLE_SMS+"("+KEY_ID+"integerprimarykeyautoincrement,"+KEY_SENDER+"textnotnull,"+KEY_BODY+"text,"+KEY_RECEIVE_TIME+"text,"+KEY_RETURN_RESULT+"text);";
20.3程序開(kāi)發(fā)20.3.2數(shù)據(jù)庫(kù)適配器/**靜態(tài)Hel20.3
程序開(kāi)發(fā)20.3.2數(shù)據(jù)庫(kù)適配器@Override publicvoidonCreate(SQLiteDatabase_db){ _db.execSQL(DB_CREATE_CONFIG); _db.execSQL(DB_CREATE_SMS);
//初始化系統(tǒng)配置的數(shù)據(jù)表
Config.LoadDefaultConfig(); ContentValuesnewValues=newContentValues(); newValues.put(KEY_CITY_NAME,Config.CityName); newValues.put(KEY_REFRESH_SPEED,Config.RefreshSpeed); newValues.put(KEY_SMS_SERVICE,Config.ProvideSmsService); newValues.put(KEY_SMS_INFO,Config.SaveSmsInfo); newValues.put(KEY_KEY_WORD,Config.KeyWord); _db.insert(DB_TABLE_CONFIG,null,newValues); }
20.3程序開(kāi)發(fā)20.3.2數(shù)據(jù)庫(kù)適配器20.3
程序開(kāi)發(fā)20.3.2數(shù)據(jù)庫(kù)適配器@Override publicvoidonUpgrade(SQLiteDatabase_db,int_oldVersion,int_newVersion){ _db.execSQL("DROPTABLEIFEXISTS"+DB_TABLE_CONFIG); _db.execSQL("DROPTABLEIFEXISTS"+DB_CREATE_SMS); onCreate(_db); }}20.3程序開(kāi)發(fā)20.3.2數(shù)據(jù)庫(kù)適配器20.3
程序開(kāi)發(fā)20.3.2數(shù)據(jù)庫(kù)適配器在DBAdapter類中,用戶界面會(huì)調(diào)用SaveConfig()和LoadConfig(),從SQLite數(shù)據(jù)庫(kù)中保存和讀取配置信息。保存配置信息時(shí),SaveConfig()函數(shù)會(huì)將Config類中的公有靜態(tài)屬性寫入數(shù)據(jù)庫(kù);反之,LoadConfig()會(huì)將數(shù)據(jù)庫(kù)中的配置信息寫入Config類中的公有靜態(tài)屬性SaveConfig()和LoadConfig()的代碼如下publicvoidSaveConfig(){ ContentValuesupdateValues=newContentValues(); updateValues.put(KEY_CITY_NAME,Config.CityName); updateValues.put(KEY_REFRESH_SPEED,Config.RefreshSpeed); updateValues.put(KEY_SMS_SERVICE,Config.ProvideSmsService); updateValues.put(KEY_SMS_INFO,Config.SaveSmsInfo); updateValues.put(KEY_KEY_WORD,Config.KeyWord); 20.3程序開(kāi)發(fā)20.3.2數(shù)據(jù)庫(kù)適配器publicv20.3
程序開(kāi)發(fā)20.3.2數(shù)據(jù)庫(kù)適配器db.update(DB_TABLE_CONFIG,updateValues,KEY_ID+"="+DB_CONFIG_ID,null); Toast.makeText(context,"系統(tǒng)設(shè)置保存成功",Toast.LENGTH_SHORT).show();}
publicvoidLoadConfig(){ Cursorresult=db.query(DB_TABLE_CONFIG,newString[]{KEY_ID,KEY_CITY_NAME, KEY_REFRESH_SPEED,KEY_SMS_SERVICE,KEY_SMS_INFO,KEY_KEY_WORD}, KEY_ID+"="+DB_CONFIG_ID,null,null,null,null); if(result.getCount()==0||!result.moveToFirst()){ return; }20.3程序開(kāi)發(fā)20.3.2數(shù)據(jù)庫(kù)適配器20.3
程序開(kāi)發(fā)20.3.2數(shù)據(jù)庫(kù)適配器Config.CityName=result.getString(result.getColumnIndex(KEY_CITY_NAME)); Config.RefreshSpeed=result.getString(result.getColumnIndex(KEY_REFRESH_SPEED)); Config.ProvideSmsService=result.getString(result.getColumnIndex(KEY_SMS_SERVICE)); Config.SaveSmsInfo=result.getString(result.getColumnIndex(KEY_SMS_INFO)); Config.KeyWord=result.getString(result.getColumnIndex(KEY_KEY_WORD)); Toast.makeText(context,"系統(tǒng)設(shè)置讀取成功",Toast.LENGTH_SHORT).show();}20.3程序開(kāi)發(fā)20.3.2數(shù)據(jù)庫(kù)適配器20.3
程序開(kāi)發(fā)20.3.2數(shù)據(jù)庫(kù)適配器另一個(gè)會(huì)調(diào)用DBAdapter類的是后臺(tái)服務(wù),即WeatherService類后臺(tái)服務(wù)主要調(diào)用SaveOneSms(SimpleSmssms)、DeleteAllSms()和GetAllSms()函數(shù),分別用來(lái)保存SMS短信記錄、刪除所有SMS數(shù)據(jù)記錄和獲取所有SMS數(shù)據(jù)記錄在GetAllSms()函數(shù)中,調(diào)用了一個(gè)私有函數(shù)ToSimpleSms(Cursorcursor),用來(lái)將從數(shù)據(jù)庫(kù)獲取的數(shù)據(jù)轉(zhuǎn)換為SimpleSms對(duì)象數(shù)組SimpleSms類將在下一小節(jié)進(jìn)行介紹下面是SaveOneSms(SimpleSmssms)、DeleteAllSms()和GetAllSms()函數(shù)的代碼20.3程序開(kāi)發(fā)20.3.2數(shù)據(jù)庫(kù)適配器20.3
程序開(kāi)發(fā)20.3.2數(shù)據(jù)庫(kù)適配器publicvoidSaveOneSms(SimpleSmssms){ ContentValuesnewValues=newContentValues(); newValues.put(KEY_SENDER,sms.Sender); newValues.put(KEY_BODY,sms.Body); newValues.put(KEY_RECEIVE_TIME,sms.ReceiveTime); newValues.put(KEY_RETURN_RESULT,sms.ReturnResult); db.insert(DB_TABLE_SMS,null,newValues);}publiclongDeleteAllSms(){ returndb.delete(DB_TABLE_SMS,null,null);}publicSimpleSms[]GetAllSms(){ Cursorresults=db.query(DB_TABLE_SMS,newString[]{KEY_ID,KEY_SENDER, KEY_BODY,KEY_RECEIVE_TIME,KEY_RETURN_RESULT}, null,null,null,null,null); returnToSimpleSms(results);}privateSimpleSms[]ToSimpleSms(Cursorcursor){20.3程序開(kāi)發(fā)20.3.2數(shù)據(jù)庫(kù)適配器publicv20.3
程序開(kāi)發(fā)20.3.2數(shù)據(jù)庫(kù)適配器intresultCounts=cursor.getCount(); if(resultCounts==0||!cursor.moveToFirst()){ returnnull; }
SimpleSms[]sms=newSimpleSms[resultCounts]; for(inti=0;i<resultCounts;i++){ sms[i]=newSimpleSms(); sms[i].Sender=cursor.getString(cursor.getColumnIndex(KEY_SENDER)); sms[i].Body=cursor.getString(cursor.getColumnIndex(KEY_BODY)); sms[i].ReceiveTime=cursor.getString(cursor.getColumnIndex(KEY_RECEIVE_TIME)); sms[i].ReturnResult=cursor.getString(cursor.getColumnIndex(KEY_RETURN_RESULT)); cursor.moveToNext(); } returnsms;}20.3程序開(kāi)發(fā)20.3.2數(shù)據(jù)庫(kù)適配器intresu20.3
程序開(kāi)發(fā)20.3.3短信監(jiān)聽(tīng)器短信監(jiān)聽(tīng)器本質(zhì)上是BroadcastReceiver,用于監(jiān)聽(tīng)Android系統(tǒng)所接收到的所有SMS短消息,可以在應(yīng)用程序關(guān)閉后仍然繼續(xù)運(yùn)行,核心代碼在SmsReceiver.java文件中在介紹SmsReceiver類前,先說(shuō)明用來(lái)保存SMS短信內(nèi)容和相關(guān)信息的SimpleSms類。android.telephony.gsm.SmsMessage是Android提供的短信類,但這里需要一個(gè)更精簡(jiǎn)、小巧的類,保存少量的信息,因此構(gòu)造了SimpleSms類,僅用來(lái)保存短信的發(fā)送者、內(nèi)容、接收時(shí)間和返回結(jié)果。這里的“返回結(jié)果”指的是返回包含天氣信息的短信內(nèi)容20.3程序開(kāi)發(fā)20.3.3短信監(jiān)聽(tīng)器20.3
程序開(kāi)發(fā)20.3.3短信監(jiān)聽(tīng)器SimpleSms.java文件完整代碼:packageedu.hrbeu.WeatherDemo.SMS;importjava.text.SimpleDateFormat;
publicclassSimpleSms{ publicStringSender; publicStringBody; publicStringReceiveTime; publicStringReturnResult;
publicSimpleSms(){ }20.3程序開(kāi)發(fā)20.3.3短信監(jiān)聽(tīng)器packagee20.3
程序開(kāi)發(fā)20.3.3短信監(jiān)聽(tīng)器第5行到第8行代碼的屬性Sender、Body、ReceiveTime和ReturnResult,分別表示SMS短信的發(fā)送者、內(nèi)容、接收時(shí)間和返回結(jié)果第15行和第16行的代碼在SimpleSms類的構(gòu)造函數(shù)中,直接將系統(tǒng)時(shí)間以“年-月-日小時(shí):分:秒”的格式保存在ReceiveTime屬性中publicSimpleSms(Stringsender,Stringbody){ this.Sender=sender; this.Body=body; SimpleDateFormattempDate=newSimpleDateFormat("yyyy-MM-dd"+""+"hh:mm:ss"); this.ReceiveTime=tempDate.format(newjava.util.Date()); this.ReturnResult=""; }}20.3程序開(kāi)發(fā)20.3.3短信監(jiān)聽(tīng)器20.3
程序開(kāi)發(fā)20.3.3短信監(jiān)聽(tīng)器SmsReceiver類繼承BroadcastReceiver,重載了onReceive()函數(shù)系統(tǒng)消息的識(shí)別和關(guān)鍵字的識(shí)別并不復(fù)雜,只要接收vider.Telephony.SMS_RECEIVED類型的系統(tǒng)消息,則表明是Android系統(tǒng)接收到了短信;將短信的內(nèi)容拆分后,判斷消息內(nèi)容是否是配置信息中定義的關(guān)鍵字,即可判斷該短信是否為天氣服務(wù)請(qǐng)求短信20.3程序開(kāi)發(fā)20.3.3短信監(jiān)聽(tīng)器20.3
程序開(kāi)發(fā)20.3.3短信監(jiān)聽(tīng)器SmsReceiver.java文件的核心代碼publicclassSmsReceiverextendsBroadcastReceiver{ privatestaticfinalStringSMS_ACTION="vider.Telephony.SMS_RECEIVED";
@Override publicvoidonReceive(Contextcontext,Intentintent){ if(intent.getAction().equals(SMS_ACTION)){ Bundlebundle=intent.getExtras(); if(bundle!=null){ Object[]objs=(Object[])bundle.get("pdus"); SmsMessage[]messages=newSmsMessage[objs.length]; for(inti=0;i<objs.length;i++){ messages[i]=SmsMessage.createFromPdu((byte[])objs[i]); }20.3程序開(kāi)發(fā)20.3.3短信監(jiān)聽(tīng)器publiccl20.3
程序開(kāi)發(fā)20.3.3短信監(jiān)聽(tīng)器StringsmsBody=messages[0].getDisplayMessageBody(); StringsmsSender=messages[0].getDisplayOriginatingAddress(); if(smsBody.trim().equals(Config.KeyWord)&&Config.ProvideSmsService.equals("true")){ SimpleSmssimpleSms=newSimpleSms(smsSender,smsBody); WeatherService.RequerSMSService(simpleSms);Toast.makeText(context,"接收到服務(wù)請(qǐng)求短信",Toast.LENGTH_SHORT).show(); }
} }}20.3程序開(kāi)發(fā)20.3.3短信監(jiān)聽(tīng)器20.3
程序開(kāi)發(fā)20.3.3短信監(jiān)聽(tīng)器第10行代碼將帶有pdus字符串特征的對(duì)象,通過(guò)Bundle.get()函數(shù)提取出來(lái)在第12行代碼使用SmsMessage.CreateFromPdu()函數(shù)構(gòu)造SmsMessage對(duì)象在第20行代碼使用循環(huán)語(yǔ)句是因?yàn)榻邮盏降亩绦趴赡懿恢挂粭l從第14行和第15行代碼上看,這里只處理第1條短信第17行代碼構(gòu)造SimpleSms對(duì)象在代碼第18行調(diào)用WeatherService類的RequerSMSService()函數(shù),將SimpleSms對(duì)象添加到短信隊(duì)列中20.3程序開(kāi)發(fā)20.3.3短信監(jiān)聽(tīng)器20.3
程序開(kāi)發(fā)20.3.3短信監(jiān)聽(tīng)器在AndroidManifest.xml文件中注冊(cè)短信監(jiān)聽(tīng)器SmsReceiver,并聲明可以接收短信的用戶許可android.permission.RECEIVE_SMS如果注冊(cè)的組件不在根命名空間中,則需要將子命名空間寫在類的前面20.3程序開(kāi)發(fā)20.3.3短信監(jiān)聽(tīng)器20.3
程序開(kāi)發(fā)20.3.3短信監(jiān)聽(tīng)器例如下面在代碼第1行中,因?yàn)镾msReceiver.java文件在edu.hrbeu.WeatherDemo.Service命名空間下,而不在根命名空間edu.hrbeu.WeatherDemo下,因此注冊(cè)組件時(shí)需要在類名SmsReceiver前添加.Service<receiverandroid:name=".Service.SmsReceiver"> <intent-filter> <actionandroid:name="vider.Telephony.SMS_RECEIVED"/> </intent-filter></receiver><uses-permissionandroid:name="android.permission.RECEIVE_SMS"/>20.3程序開(kāi)發(fā)20.3.3短信監(jiān)聽(tīng)器<receiver20.3
程序開(kāi)發(fā)20.3.4后臺(tái)服務(wù)后臺(tái)服務(wù)是WeatherDemo示例的核心模塊,在用戶啟動(dòng)后持續(xù)在后臺(tái)運(yùn)行,直到用戶手動(dòng)停止服務(wù)后臺(tái)服務(wù)功能一是發(fā)送包含天氣信息的SMS短信(短信發(fā)送模塊)二是周期性的獲取Google的天氣數(shù)據(jù)(數(shù)據(jù)獲取模塊)
20.3程序開(kāi)發(fā)20.3.4后臺(tái)服務(wù)20.3
程序開(kāi)發(fā)20.3.4后臺(tái)服務(wù)短信發(fā)送模塊:后臺(tái)服務(wù)在單獨(dú)的線程上運(yùn)行首先調(diào)用ProcessSmsList()函數(shù),檢查短信隊(duì)列中是否有需要回復(fù)的短信然后調(diào)用GetGoogleWeatherData()函數(shù)獲取天氣數(shù)據(jù)最后線程暫停1秒,以釋放CPU資源WeatherDemo示例后臺(tái)服務(wù)的核心代碼在WeatherService.java文件中20.3程序開(kāi)發(fā)20.3.4后臺(tái)服務(wù)20.3
程序開(kāi)發(fā)20.3.4后臺(tái)服務(wù)下面是線程調(diào)用函數(shù)的部分代碼privatestaticArrayList<SimpleSms>smsList=newArrayList<SimpleSms>();
privateRunnablebackgroudWork=newRunnable(){ @Override publicvoidrun(){ try{ while(!Terrupted()){ ProcessSmsList(); GetGoogleWeatherData(); Thread.sleep(1000); } }catch(InterruptedExceptione){ e.printStackTrace(); } }};20.3程序開(kāi)發(fā)20.3.4后臺(tái)服務(wù)privatest20.3
程序開(kāi)發(fā)20.3.4后臺(tái)服務(wù)ProcessSmsList()函數(shù)用來(lái)檢查短信列表smsList,并根據(jù)Weather類中保存的天氣數(shù)據(jù),向請(qǐng)求者的發(fā)送回復(fù)短信WeatherService.java文件的ProcessSmsList()函數(shù)代碼如下20.3程序開(kāi)發(fā)20.3.4后臺(tái)服務(wù)20.3
程序開(kāi)發(fā)20.3.4后臺(tái)服務(wù)privatevoidProcessSmsList(){ if(smsList.size()==0){ return; } SmsManagersmsManager=SmsManager.getDefault(); PendingIntentmPi=PendingIntent.getBroadcast(this,0,newIntent(),0); while(smsList.size()>0){ SimpleSmssms=smsList.get(0); smsList.remove(0); smsManager.sendTextMessage(sms.Sender,null,Weather.GetSmsMsg(),mPi,null); sms.ReturnResult=Weather.GetSmsMsg(); SaveSmsData(sms); }}20.3程序開(kāi)發(fā)20.3.4后臺(tái)服務(wù)privatevo20.3
程序開(kāi)發(fā)20.3.4后臺(tái)服務(wù)發(fā)送短信是使用SmsManager對(duì)象的sendTextMessage()方法,該方法一共需要5個(gè)參數(shù)第1個(gè)參數(shù)是收件人地址第2個(gè)參數(shù)是發(fā)件人地址第3個(gè)參數(shù)是短信正文第4個(gè)參數(shù)是發(fā)送服務(wù)第5個(gè)參數(shù)是送達(dá)服務(wù)sendTextMessage()方法的收件人地址和短信正文是不可為空的參數(shù),而且一般GSM規(guī)范要求短信內(nèi)容要控制在70個(gè)漢字以內(nèi)代碼第8行的Weather.GetSmsMsg(),用來(lái)獲得供回復(fù)短信使用的天氣信息,因?yàn)榭紤]到短信的字?jǐn)?shù)限制,僅返回當(dāng)天和未來(lái)一天的天氣狀況20.3程序開(kāi)發(fā)20.3.4后臺(tái)服務(wù)20.3
程序開(kāi)發(fā)20.3.4后臺(tái)服務(wù)Weather.java文件的代碼如下packageedu.hrbeu.WeatherDemo.Weather;importandroid.graphics.Bitmap;
publicclassWeather{ publicstaticStringcity; publicstaticStringforecase_date; publicstaticStringcurrent_date_time; publicstaticStringcurrent_condition; publicstaticStringcurrent_temp; publicstaticStringcurrent_humidity; publicstaticStringcurrent_image_url; publicstaticBitmapcurrent_image; publicstaticStringcurrent_wind;
20.3程序開(kāi)發(fā)20.3.4后臺(tái)服務(wù)packageed20.3
程序開(kāi)發(fā)20.3.4后臺(tái)服務(wù)publicstaticForecast[]day=newForecast[4];
static{ for(inti=0;i<day.length;i++){ day[i]=newForecast(); } }
publicstaticStringGetSmsMsg(){ Stringmsg=""; msg+=city+","; msg+=current_condition+","+current_temp+"."; msg+=day[0].day_of_week+“,”+day[0].condition+“,”+、
day[0].high+"/"+day[0].low; returnmsg; }}20.3程序開(kāi)發(fā)20.3.4后臺(tái)服務(wù)publicsta20.3
程序開(kāi)發(fā)20.3.4后臺(tái)服務(wù)Forecast.java文件的代碼如下packageedu.hrbeu.WeatherDemo.Weather;importandroid.graphics.Bitmap;
publicclassForecast{ publicStringday_of_week; publicStringlow; publicStringhigh; publicStringimage_url; publicBitmapimage; publicStringcondition;}20.3程序開(kāi)發(fā)20.3.4后臺(tái)服務(wù)packageed20.3
程序開(kāi)發(fā)20.3.4后臺(tái)服務(wù)數(shù)據(jù)獲取模塊:天氣數(shù)據(jù)是從Google提供的WebService中獲取的,數(shù)據(jù)的獲取地址是/ig/api?hl=en&weather=New%20YorkNew%20York表示獲取紐約(NewYork)的天氣數(shù)據(jù),%20表示一個(gè)空格讀者可以替換New%20York,并將新的地址輸入Web瀏覽器,在瀏覽器中可以直接看到XML格式的天氣數(shù)據(jù)在資源目錄中的/res/xml/api.xml文件,就是2009年9月22日獲取的紐約天氣數(shù)據(jù)在程序資源中保留api.xml文件,主要是用來(lái)幫助讀者分析XML數(shù)據(jù)格式,在程序運(yùn)行期間并不訪問(wèn)該文件20.3程序開(kāi)發(fā)20.3.4后臺(tái)服務(wù)20.3
程序開(kāi)發(fā)20.3.4后臺(tái)服務(wù)api.xml文件的內(nèi)容如下<?xmlversion="1.0"encoding="UTF-8"?><xml_api_replyversion="1"> <weathermodule_id="0"tab_id="0"mobile_row="0"mobile_zipped="1"row="0"section="0"> <forecast_information> <citydata=""/> <postal_codedata=""/> <latitude_e6data=""/> <longitude_e6data=""/> <forecast_datedata=""/> <current_date_timedata="2009-09-2216:51:00+0000"/> <unit_systemdata="US"/> </forecast_information>
20.3程序開(kāi)發(fā)20.3.4后臺(tái)服務(wù)<?xmlvers20.3
程序開(kāi)發(fā)20.3.4后臺(tái)服務(wù)<current_conditions> <conditiondata="MostlyCloudy"/> <temp_fdata="72"/> <temp_cdata="22"/> <humiditydata="Humidity:71%"/> <icondata="/ig/images/weather/mostly_cloudy.gif"/> <wind_conditiondata="Wind:Nat"/> </current_conditions>
<forecast_conditions> <day_of_weekdata="Tue"/> <lowdata="65"/> <highdata="76"/> <icondata="/ig/images/weather/mostly_sunny.gif"/> <conditiondata="PartlySunny"/> </forecast_conditions>
20.3程序開(kāi)發(fā)20.3.4后臺(tái)服務(wù)20.3
程序開(kāi)發(fā)20.3.4后臺(tái)服務(wù)<forecast_conditions> <day_of_weekdata="Wed"/> <lowdata="68"/> <highdata="79"/> <icondata="/ig/images/weather/chance_of_storm.gif"/> <conditiondata="ChanceofStorm"/> </forecast_conditions>
<forecast_conditions> <day_of_weekdata="Thu"/> <lowdata="61"/> <highdata="83"/> <icondata="/ig/images/weather/chance_of_storm.gif"/> <conditiondata="ChanceofStorm"/> </forecast_conditions>\
20.3程序開(kāi)發(fā)20.3.4后臺(tái)服務(wù)20.3
程序開(kāi)發(fā)20.3.4后臺(tái)服務(wù)<forecast_information>標(biāo)簽內(nèi)的數(shù)據(jù)是天氣預(yù)報(bào)的城市和時(shí)間等基本信息,<current_conditions>標(biāo)簽內(nèi)的是當(dāng)時(shí)的天氣狀況,4個(gè)<forecast_conditions>標(biāo)簽是未來(lái)四天的天氣情況在api.xml文件中,還提供了能夠反映天氣情況的圖標(biāo)地址,例如第19行、第27行和第35行等<forecast_conditions> <day_of_weekdata="Fri"/> <lowdata="54"/> <highdata="72"/> <icondata="/ig/images/weather/sunny.gif"/> <conditiondata="Clear"/> </forecast_conditions> </weather></xml_api_reply>20.3程序開(kāi)發(fā)20.3.4后臺(tái)服務(wù)20.3
程序開(kāi)發(fā)20.3.4后臺(tái)服務(wù)WeatherAdapter類實(shí)現(xiàn)了利用URL獲取位圖的私有函數(shù)GetURLBitmap(),以及用來(lái)下載和解析XML數(shù)據(jù)的公有函數(shù)GetWeatherData()后臺(tái)服務(wù)在調(diào)用GetWeatherData()函數(shù)解析Google提供的天氣數(shù)據(jù)時(shí),會(huì)不斷調(diào)用GetURLBitmap()函數(shù),將XML數(shù)據(jù)中的天氣圖標(biāo)根據(jù)圖標(biāo)地址下載到本地保存20.3程序開(kāi)發(fā)20.3.4后臺(tái)服務(wù)20.3
程序開(kāi)發(fā)20.3.4后臺(tái)服務(wù)GetURLBitmap()函數(shù)的代碼如下privatestaticBitmapGetURLBitmap(StringurlString){ URLurl=null; Bitmapbitmap=null; try{ url=newURL(""+urlString); } catch(MalformedURLExceptione){ e.printStackTrace(); }
try{ HttpURLConnectionconn=(HttpURLConnection)url.openConnection(); conn.connect(); InputStreamis=conn.getInputStream(); bitmap=BitmapFactory.decodeStream(is); is.close();20.3程序開(kāi)發(fā)20.3.4后臺(tái)服務(wù)privatest20.3
程序開(kāi)發(fā)20.3.4后臺(tái)服務(wù)第12行代碼構(gòu)造了支持HTTP功能的URLConnection第14行代碼返回字節(jié)流第15行代碼使用字節(jié)流產(chǎn)生位圖第16行代碼關(guān)閉字節(jié)流}catch(IOExceptione){ e.printStackTrace(); } returnbitmap;}20.3程序開(kāi)發(fā)20.3.4后臺(tái)服務(wù)20.3
程序開(kāi)發(fā)20.3.4后臺(tái)服務(wù)GetWeatherData()函數(shù)首先根據(jù)指定的URL地址,從網(wǎng)絡(luò)獲取字節(jié)流數(shù)據(jù),然后調(diào)用輕量級(jí)XML解析器XmlPullParser對(duì)天氣數(shù)據(jù)進(jìn)行解析,并將解析結(jié)果保存在Weather類的公有靜態(tài)屬性中GetWeatherData()函數(shù)的代碼如下publicstaticvoidGetWeatherData()throwsIOException,Throwable{StringqueryString="/ig/api?weather="+Config.CityName; URLaURL=newURL(queryString.replace("","%20")); URLConnectionconn=aURL.openConnection(); conn.connect(); InputStreamis=conn.getInputStream();
XmlPullParserFactoryfactory=XmlPullParserFactory.newInstance() factory.setNamespaceAware(true); XmlPullParserparser=factory.newPullParser(); parser.setInput(is,"UTF-8");20.3程序開(kāi)發(fā)20.3.4后臺(tái)服務(wù)publicsta20.3
程序開(kāi)發(fā)20.3.4后臺(tái)服務(wù)12.intdayCounter=0; while(parser.next()!=XmlPullParser.END_DOCUMENT){ Stringelement=parser.getName(); if(element!=null&&element.equals("forecast_information")){ while(true){ inteventCode=parser.next(); element=parser.getName(); if(eventCode==XmlPullParser.START_TAG){ if(element.equals("city")){ Weather.city=parser.getAttributeValue(0);23.}elseif(element.equals("current_date_time")){Weather.current_date_time=parser.getAttributeValue(0);25.}}
20.3程序開(kāi)發(fā)20.3.4后臺(tái)服務(wù)12.20.3
程序開(kāi)發(fā)20.3.4后臺(tái)服務(wù)28. if(element.equals("forecast_information")&& eventCode==XmlPullParser.END_TAG){ break; }} }20.3程序開(kāi)發(fā)20.3.4后臺(tái)服務(wù)28. 20.3
程序開(kāi)發(fā)20.3.4后臺(tái)服務(wù)if(element!=null&&element.equals("current_conditions")){ while(true){ inteventCode=parser.next(); element=parser.getName(); if(eventCode==XmlPullParser.START_TAG){ if(element.equals("condition")){ Weather.current_condition=parser.getAttributeValue(0);\ }elseif(element.equals("temp_f")){ Weather.current_temp=parser.getAttributeValue(0); }elseif(element.equals("humidity")){ Weather.current_humidity=parser.getAttributeValue(0); }elseif(element.equals("wind_condition")){ Weather.current_wind=parser.getAttributeValue(0); }elseif(element.equals("icon")){ Weather.current_image_url=parser.getAttributeValue(0); Weather.current_image=GetURLBitmap(Weather.current_image_url);}}
20.3程序開(kāi)發(fā)20.3.4后臺(tái)服務(wù)20.3
程序開(kāi)發(fā)20.3.4后臺(tái)服務(wù)if(element.equals("current_conditions")&& eventCode==XmlPullParser.END_TAG){ break; } } }20.3程序開(kāi)發(fā)20.3.4后臺(tái)服務(wù)20.3
程序開(kāi)發(fā)20.3.4后臺(tái)服務(wù)if(element!=null&&element.equals("forecast_conditions")){ while(true){ inteventCode=parser.next(); element=parser.getName(); if(eventCode==XmlPullParser.START_TAG){ if(element.equals("day_of_week")){ Weather.day[dayCounter].day_of_week=parser.getAttributeValue(0); }elseif(element.equals("low")){ Weather.day[dayCounter].low=parser.getAttributeValue(0); }elseif(element.equals("high")){ Weather.day[dayCounter].high=parser.getAttributeValue(0); }elseif(element.equals("icon")){ Weather.day[dayCounter].image_url=parser.getAttributeValue(0); Weather.day[dayCounter].image=GetURLBitmap(Weather.day[dayCounter].image_url); }elseif(element.equals("condition")){Weather.day[dayCounter].condition=parser.getAttributeValue(0); }20.3程序開(kāi)發(fā)20.3.4后臺(tái)服務(wù)20.3
程序開(kāi)發(fā)20.3.4后臺(tái)服務(wù)}
if(element.equals("forecast_conditions")&& eventCode==XmlPullParser.END_TAG){ dayCounter++; break; } } } } is.close();}20.3程序開(kāi)發(fā)20.3.4后臺(tái)服務(wù)20.3
程序開(kāi)發(fā)20.3.4后臺(tái)服務(wù)最后,在AndroidManifest.xml文件中注冊(cè)WeatherService,并聲明連接互聯(lián)網(wǎng)和發(fā)送SMS短信的兩個(gè)用戶許可<serviceandroid:name=".Service.WeatherService"/><uses-permissionandroid:name="android.permission.INTERNET"/><uses-permissionandroid:name="android.permission.SEND_SMS"/>20.3程序開(kāi)發(fā)20.3.4后臺(tái)服務(wù)<servicea20.3
程序開(kāi)發(fā)20.3.5用戶界面在用戶界面設(shè)計(jì)上,采用可以在多個(gè)分頁(yè)上快速切換的Tab標(biāo)簽頁(yè)WeatherDemo示例的Tab標(biāo)簽頁(yè)將每個(gè)標(biāo)簽頁(yè)與一個(gè)Activity關(guān)聯(lián)在一起,這樣做的好處就是可以將不同標(biāo)簽頁(yè)的代碼放在不同的文件中,而且每個(gè)標(biāo)簽頁(yè)都可以有獨(dú)立的
溫馨提示
- 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ù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2026天津市濱海新區(qū)事業(yè)單位招聘25人備考題庫(kù)及參考答案詳解
- 2026江蘇南京大學(xué)招聘XZ2026-005商學(xué)院保潔員備考題庫(kù)含答案詳解
- 2026云南昆明市尋甸回族彝族自治縣檔案館城鎮(zhèn)公益性崗位招聘2人備考題庫(kù)及答案詳解參考
- 2026廣東清遠(yuǎn)市佛岡縣石角鎮(zhèn)招聘新城社區(qū)專職網(wǎng)格員1人備考題庫(kù)及參考答案詳解一套
- 2026年河北滄州市人民醫(yī)院選聘高層次人才49名備考題庫(kù)附答案詳解
- 2025云南臨滄雙江自治縣地方產(chǎn)業(yè)發(fā)展服務(wù)中心招聘公益性崗位人員1人備考題庫(kù)有完整答案詳解
- 2026年河北邯鄲凌云中學(xué)招聘儲(chǔ)備教師61名備考題庫(kù)及答案詳解1套
- 2026江蘇徐州美華盛泰電梯有限公司招聘?jìng)淇碱}庫(kù)及1套完整答案詳解
- 2026國(guó)家電投集團(tuán)陜西公司招聘2人備考題庫(kù)及答案詳解(考點(diǎn)梳理)
- 2026河南師范大學(xué)科研助理崗位招聘1人備考題庫(kù)及參考答案詳解
- 護(hù)工培訓(xùn)課件內(nèi)容
- 職業(yè)中介活動(dòng)管理制度
- 瘦西湖景區(qū)槐泗河片區(qū)水系整治項(xiàng)目(二期)李莊澗環(huán)境影響報(bào)告表
- 學(xué)校維修監(jiān)控合同協(xié)議書
- 生產(chǎn)與運(yùn)作管理試題及答案
- 貴州省貴陽(yáng)市云巖區(qū)2024-2025學(xué)年上學(xué)期八年級(jí)數(shù)學(xué)期末試題卷(原卷版+解析版)
- 湖南省2023年普通高等學(xué)校對(duì)口招生考試英語(yǔ)試卷
- 《疼痛的評(píng)估與護(hù)理》課件
- 應(yīng)急通信裝備
- 高思導(dǎo)引3-6年級(jí)分類題目-數(shù)字謎02-三下02-簡(jiǎn)單乘除法豎式
- 建筑工地消防安全工作總結(jié)
評(píng)論
0/150
提交評(píng)論