基于Android平臺的天氣預(yù)報短信服務(wù)系統(tǒng)課程設(shè)計_第1頁
基于Android平臺的天氣預(yù)報短信服務(wù)系統(tǒng)課程設(shè)計_第2頁
基于Android平臺的天氣預(yù)報短信服務(wù)系統(tǒng)課程設(shè)計_第3頁
基于Android平臺的天氣預(yù)報短信服務(wù)系統(tǒng)課程設(shè)計_第4頁
基于Android平臺的天氣預(yù)報短信服務(wù)系統(tǒng)課程設(shè)計_第5頁
已閱讀5頁,還剩76頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

79/81目錄1. 需求分析 11.1功能需求 11.2界面需求 11.3內(nèi)部功能 12. 程序設(shè)計 22.1用戶界面設(shè)計 22.2數(shù)據(jù)庫設(shè)計 22.2.1配置信息 22.2.2SMS短信服務(wù)信息 32.3程序模塊設(shè)計 33. 程序開發(fā) 43.1文件結(jié)構(gòu)與用途 43.2數(shù)據(jù)庫適配器 53.3短信監(jiān)聽器 83.4后臺服務(wù) 103.4.1短信發(fā)送模塊 113.4.2數(shù)據(jù)庫獵取模塊 133.5用戶界面 173.5.1WeatherActivity 183.5.2HistoryActivity 193.5.3SetupActivity 243.5.4GoogleMapActivity 254.總結(jié) 345.參考文獻 35天氣預(yù)報短信服務(wù)系統(tǒng)需求分析1.1功能需求天氣預(yù)報短信服務(wù)系統(tǒng)中,有一個顯示天氣情況的用戶界面,能夠通過圖片和文字顯示當前和以后幾天的天氣狀況,包括溫度、濕度、風向和雨雪情況等。這些天氣數(shù)據(jù)是通過后臺服務(wù)獵取的,那個后臺服務(wù)能夠按照一定時刻間隔,從Yahoo上獵取天氣預(yù)報信息,并將天氣信息保存在后臺服務(wù)中。系統(tǒng)還需要提供基于SMS短信的天氣數(shù)據(jù)服務(wù),其他手機用戶能夠向本示例所在的手機上發(fā)送SMS短信,并在短信中包含用戶指定的關(guān)鍵字,則能夠?qū)⒈4嬖诤笈_服務(wù)中的天氣情況,再通過SMS短信回復(fù)給用戶。最后,每個被發(fā)送的SMS短信都要被記錄下來,用戶能夠掃瞄或刪除這些回復(fù)信息。本系統(tǒng)還要顯示地圖,在地圖上顯示某地點的天氣信息。1.2界面需求本示例包含三個要緊的用戶界面:(1)顯示天氣預(yù)報的用戶界面;(2)顯示已發(fā)送SMS短信的用戶界面;(3)掃瞄和設(shè)置配置信息的用戶界面;(4)Google地圖,在地圖上覆蓋天氣信息。1.3內(nèi)部功能隱藏在用戶界面后面的內(nèi)部功能,是用戶界面能夠正確實現(xiàn)的基礎(chǔ),如下所述:(1)顯示天氣預(yù)報的用戶界面;(2)獵取Yahoo的天氣數(shù)據(jù);(3)顯示SMS短信的用戶界面;(4)依照關(guān)鍵字監(jiān)視SMS短信;(5)發(fā)送包含天氣信息的SMS短信;(6)將發(fā)送的SMS短信寫入數(shù)據(jù)庫;(7)掃瞄和設(shè)置配置信息的用戶界面;(8)將用戶設(shè)置的配置信息保存到數(shù)據(jù)庫;(9)啟動時讀取數(shù)據(jù)庫中的配置信息;(10)恢復(fù)缺省設(shè)置;(11)顯示Google地圖且覆蓋天氣信息的用戶界面,寫入獵取的谷歌密鑰。

程序設(shè)計2.1用戶界面設(shè)計詳細分析應(yīng)用程序中四個要緊用戶界面包含的顯示內(nèi)容,如下所述:(1)在“顯示天氣預(yù)報的用戶界面”中,依照Yahoo能夠提供的數(shù)據(jù),在界面上能夠顯示當前的天氣狀況,包括都市名稱、溫度、雨雪情況和獵取數(shù)據(jù)時刻等信息;還能夠顯示以后一天的天氣狀況,僅包括溫度和雨雪情況;(2)在“顯示已發(fā)送SMS短信的用戶界面”中,應(yīng)顯示每個回復(fù)短信的時刻、目標手機號碼、都市名稱、當天的天氣狀況和以后一天的天氣狀況;(3)在“掃瞄和設(shè)置配置信息的用戶界面”中,應(yīng)顯示獵取天氣預(yù)報的目標都市名稱、獵取數(shù)據(jù)的頻率和短信的關(guān)鍵字,并同意用戶設(shè)置是否提供短信服務(wù)以及是否記錄回復(fù)的短信信息;(4)在“顯示谷歌地圖及在地圖上覆蓋天氣信息界面”中,應(yīng)顯示Google地圖,當用戶點擊地圖上某都市時,會顯示某都市信息及天氣情況。2.2數(shù)據(jù)庫設(shè)計本系統(tǒng)要緊存儲兩種數(shù)據(jù),詳述如下:(1)配置信息:因為配置信息的數(shù)據(jù)量專門小,從Android支持的存儲方式上分析,能夠保存在SharePreference、文件或SQLite數(shù)據(jù)庫中;(2)SMS短信服務(wù)信息:SMS短信服務(wù)信息是一個隨著時刻推移而不斷增加的數(shù)據(jù),屬于文本信息,且有固定的格式,因此適合使用SQLite數(shù)據(jù)庫進行存儲。綜合分析這兩種需要存儲的數(shù)據(jù),選擇SQLite數(shù)據(jù)庫作為存儲數(shù)據(jù)的方法2.2.1配置信息配置信息中要緊保存天氣信息查詢的都市名稱,訪問Yahoo更新天氣信息的頻率,請求天氣信息SMS短信的關(guān)鍵字,且是否提供短信服務(wù)和是否記錄短信服務(wù)內(nèi)容,其數(shù)據(jù)庫表如下:表2_1配置信息的數(shù)據(jù)庫屬性數(shù)據(jù)類型講明_idinteger自動增加的主鍵city_nametext進行天氣信息查詢的都市名refresh_speedtext進行天氣信息查詢的頻率,單位為秒/次sms_servicetext是否提供短信服務(wù),即接收到請求短信后是否回復(fù)包含天氣信息的短信sms_infotext是否記錄發(fā)出的SMS短信的信息key_wordtext短信服務(wù)的關(guān)鍵字,用以確定哪條是請求天氣服務(wù)的短信2.2.2SMS短信服務(wù)信息SMS短信服務(wù)信息要緊保存請求服務(wù)短信的發(fā)送者、短信內(nèi)容、接收時刻和回復(fù)信息的內(nèi)容,其數(shù)據(jù)庫表如下:表2_2SMS短信服務(wù)信息的數(shù)據(jù)庫屬性數(shù)據(jù)類型講明_idinteger自動增加的主鍵sms_sendertext請求服務(wù)短信的發(fā)送者sms_bodytext請求服務(wù)短信的內(nèi)容信息sms_receive_timetext接收到請求服務(wù)短信的時刻return_resulttext回復(fù)短信的內(nèi)容2.3程序模塊設(shè)計從功能需求上分析,能夠?qū)⒄麄€應(yīng)用程序劃分為4個模塊,分不是用戶界面、后臺服務(wù)、數(shù)據(jù)庫適配器和短信監(jiān)聽器。1.由模塊結(jié)構(gòu)圖中可知,后臺服務(wù)是整個應(yīng)用程序的核心,要緊包含兩個子模塊,一個是“數(shù)據(jù)獵取模塊”,負責周期性的從Yahoo獵取天氣信息;另一個是“短信服務(wù)模塊”,負責處理接收到的服務(wù)請求短信,并發(fā)送包含天氣信息的短信2.后臺服務(wù)由用戶界面通過Intent啟動,啟動后的后臺服務(wù)能夠在用戶界面關(guān)閉后仍然保持運行狀態(tài),直到用戶通過用戶界面發(fā)送Intent停止服務(wù),或系統(tǒng)因資源不足而強行關(guān)閉服務(wù)3.用戶界面從后臺服務(wù)獵取天氣信息,而沒有直接通過網(wǎng)絡(luò)訪問Google的天氣數(shù)據(jù)(1)一方面是因為后臺服務(wù)使用了工作線程,通過后臺服務(wù)獵取天氣數(shù)據(jù)能夠幸免因網(wǎng)絡(luò)通信不暢造成界面失去響應(yīng)(2)另一方面,在用戶關(guān)閉界面后,后臺服務(wù)仍然需要更新天氣信息,以保證短信服務(wù)數(shù)據(jù)的準確性。用戶界面還會調(diào)用數(shù)據(jù)庫適配器,向SQLite數(shù)據(jù)庫中寫入、讀取配置信息,或?qū)MS短信服務(wù)信息進行操作4.短信監(jiān)聽器是一個BroadcastReceiver,監(jiān)視所有接收到的短信(1)假如短信中包含用戶自定義的關(guān)鍵字,短信監(jiān)聽器則會認為這條短信是天氣服務(wù)請求短信,將短信的相關(guān)信息寫入后臺服務(wù)的短信服務(wù)隊列(2)假如用戶在配置信息中選擇無需提供短信服務(wù),短信監(jiān)聽器仍然接著監(jiān)聽所有短信,只是后臺服務(wù)不再同意將服務(wù)請求短信寫入服務(wù)隊列5.數(shù)據(jù)庫適配器封裝了所有對SQLite數(shù)據(jù)庫操作的方法,用戶界面和后臺服務(wù)會調(diào)用它實現(xiàn)數(shù)據(jù)庫操作。程序開發(fā)3.1文件結(jié)構(gòu)與用途在程序開發(fā)時期,首先確定“天氣預(yù)報短信服務(wù)系統(tǒng)”的工程名稱為MyWeather,包名稱為edu.hrbeu.WeatherDemo,據(jù)程序模塊設(shè)計的內(nèi)容,建立WeatherDemo。為了使源代碼文件的結(jié)構(gòu)更加清晰,WeatherDemo設(shè)置了多個命名空間,分不用來保存用戶界面、數(shù)據(jù)庫、后臺服務(wù)、SMS短信和天氣數(shù)據(jù)的源代碼文件,命名空間的名稱以及講明參考表3_1。表3_1WeatherDemo的命名空間命名空間講明edu.hrbeu.WeatherDemo存放與用戶界面相關(guān)的源代碼文件edu.hrbeu.WeatherDemo.DB存放與SQLite數(shù)據(jù)庫相關(guān)的源代碼文件edu.hrbeu.WeatherDemo.Service存放與后臺服務(wù)相關(guān)的源代碼文件edu.hrbeu.WeatherDemo.SMS存放與SMS短信相關(guān)的源代碼文件WeatherDemo示例將不同用途的源代碼文件放置在不同的命名空間中,源代碼文件的名稱和用途能夠參考表3_2。表3_2WeatherDemo的文件用途講明包名稱文件名講明.WeatherDemoHistoryActivity.java“歷史數(shù)據(jù)”頁的ActivitySetupActivity.java“系統(tǒng)設(shè)置”頁的ActivityWeatherActivity.java“天氣預(yù)報”頁的ActivityGoogleMapActivity.java“谷歌地圖”頁的ActivityTextOverlay.java地圖覆蓋天氣信息的類WeatherDemo.java程序啟動缺省的Activity.WeatherDemo.DBConfig.java保存配置信息的類DBAdapter.java數(shù)據(jù)庫適配器City.java覆蓋天氣的都市信息的類.WeatherDemo.ServiceSmsReceiver.java短信監(jiān)聽器WeatherAdapter.java數(shù)據(jù)獵取模塊WeatherService.java后臺服務(wù).WeatherDemo.SMSSimpleSms.java簡化的SMS短信類SmsAdapter.java短信發(fā)送模塊.WeatherDemo.WeatherForecast.java以后信息的類Weather.java當前天氣信息的類Android的資源文件保存在/res的子目錄中:(1)/res/drawable目錄中保存的是圖像文件(2)/res/layout目錄中保存的是布局文件(3)/res/values目錄中保存的是用來定義字符串和顏色的文件(4)/res/xml目錄保存的是XML格式的數(shù)據(jù)文件所有在程序開發(fā)時期能夠被調(diào)用的資源都保存在這些目錄中,具體每個資源文件的用途能夠參考表3_3。表3_3資源文件名稱與用途資源目錄文件講明drawableicon.png圖標文件sunny.png調(diào)試用的天氣圖片tab_history.pngTabHost中“歷史數(shù)據(jù)”頁的圖片tab_map.pngTabHost中“谷歌地圖”頁的圖片tab_setup.pngTabHost中“系統(tǒng)設(shè)置”頁的圖片tab_weather.pngTabHost中“天氣預(yù)報”頁的圖片layoutdata_row.xml“歷史數(shù)據(jù)”頁ListActivity的每行數(shù)據(jù)的布局tab_history.xmlTabHost中“歷史數(shù)據(jù)”頁的布局tab_map.xmlTabHost中“谷歌地圖”頁的布局tab_setup.xmlTabHost中“系統(tǒng)設(shè)置”頁的布局tab_weather.xmlTabHost中“天氣預(yù)報”頁的布局valuescolor.xml保存顏色的XML文件string.xml保存字符串的XML文件xmlapi.xml從Google下載的天氣數(shù)據(jù)文件。在程序運行時沒有實際作用,但在開發(fā)過程中能夠讓讀者了解數(shù)據(jù)格式3.2數(shù)據(jù)庫適配器數(shù)據(jù)庫適配器是最底層的模塊,要緊用于封裝用戶界面和后臺服務(wù)對SQLite數(shù)據(jù)庫的操作,數(shù)據(jù)庫適配器的核心代碼要緊在DBAdapter.java文件中,用戶保存配置信息的類文件Config.java。Config.java文件的全部代碼如下packageedu.hrbeu.WeatherDemo.DB;publicclassConfig{ publicstaticStringCityName; publicstaticStringRefreshSpeed; publicstaticStringProvideSmsService; publicstaticStringSaveSmsInfo; publicstaticStringKeyWord; publicstaticvoidLoadDefaultConfig(){ CityName="chaohu"; RefreshSpeed="20"; ProvideSmsService="true"; SaveSmsInfo="true"; KeyWord="HF";}從代碼中不難看出,公有靜態(tài)屬性CityName、RefreshSpeed、ProvideSmsService、SaveSmsInfo和KeyWord,完全對應(yīng)數(shù)據(jù)庫中保存配置信息表的屬性。在程序啟動后,保存在數(shù)據(jù)庫中的都市名稱、更新頻率、是否提供短信服務(wù)、是否保存短信信息和關(guān)鍵字等內(nèi)容,將被寫入那個Config類中,供其他模塊在做邏輯推斷LoadDefaultConfig()函數(shù)保存了程序內(nèi)置的配置參數(shù),此函數(shù)會在兩個情況下被調(diào)用(1)用戶主動選擇“恢復(fù)缺省設(shè)置”(2)首次啟動程序時,用來初始化保存配置參數(shù)的數(shù)據(jù)庫DBAdapter類與以往介紹過的數(shù)據(jù)庫適配器類相似,都具有繼承SQLiteOpenHelper的關(guān)心類DBOpenHelper。DBOpenHelper在建立數(shù)據(jù)庫時,同時建立兩個數(shù)據(jù)庫表,并對保存配置信息的表進行了初始化,初始化的相關(guān)代碼在如下: 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";/**靜態(tài)Helper類,用于建立、更新和打開數(shù)據(jù)庫*/ 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);"; @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); } @Override publicvoidonUpgrade(SQLiteDatabase_db,int_oldVersion,int_newVersion){ _db.execSQL("DROPTABLEIFEXISTS"+DB_TABLE_CONFIG); _db.execSQL("DROPTABLEIFEXISTS"+DB_CREATE_SMS); onCreate(_db); } }在DBAdapter類中,用戶界面會調(diào)用SaveConfig()和LoadConfig(),從SQLite數(shù)據(jù)庫中保存和讀取配置信息。保存配置信息時,SaveConfig()函數(shù)會將Config類中的公有靜態(tài)屬性寫入數(shù)據(jù)庫;反之,LoadConfig()會將數(shù)據(jù)庫中的配置信息寫入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); db.update(DB_TABLE_CONFIG,updateValues,KEY_ID+"="+DB_CONFIG_ID,null); Toast.makeText(context,"系統(tǒng)設(shè)置保存成功",Toast.LENGTH_SHORT).show(); }另一個會調(diào)用DBAdapter類的是后臺服務(wù),即WeatherService類。后臺服務(wù)要緊調(diào)用SaveOneSms(SimpleSmssms)、DeleteAllSms()和GetAllSms()函數(shù),分不用來保存SMS短信記錄、刪除所有SMS數(shù)據(jù)記錄和獵取所有SMS數(shù)據(jù)記錄。在GetAllSms()函數(shù)中,調(diào)用了一個私有函數(shù)ToSimpleSms(Cursorcursor),用來將從數(shù)據(jù)庫獵取的數(shù)據(jù)轉(zhuǎn)換為SimpleSms對象數(shù)組。SimpleSms類將在下面內(nèi)容中進行介紹下面是SaveOneSms(SimpleSmssms)、DeleteAllSms()和GetAllSms()函數(shù)的代碼: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){ 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;}3.3短信監(jiān)聽器短信監(jiān)聽器本質(zhì)上是BroadcastReceiver,用于監(jiān)聽Android系統(tǒng)所接收到的所有SMS短消息,能夠在應(yīng)用程序關(guān)閉后仍然接著運行,核心代碼在SmsReceiver.java文件中。在介紹SmsReceiver類前,先講明用來保存SMS短信內(nèi)容和相關(guān)信息的SimpleSms類。android.telephony.gsm.SmsMessage是Android提供的短信類,但那個地點需要一個更精簡、小巧的類,保存少量的信息,因此構(gòu)造了SimpleSms類,僅用來保存短信的發(fā)送者、內(nèi)容、接收時刻和返回結(jié)果。那個地點的“返回結(jié)果”指的是返回包含天氣信息的短信內(nèi)容SimpleSms.java文件完整代碼如下:packageedu.hrbeu.WeatherDemo.SMS;importjava.text.SimpleDateFormat;publicclassSimpleSms{ publicStringSender; publicStringBody; publicStringReceiveTime; publicStringReturnResult; publicSimpleSms(){ } 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=""; }}上述代碼的屬性Sender、Body、ReceiveTime和ReturnResult,分不表示SMS短信的發(fā)送者、內(nèi)容、接收時刻和返回結(jié)果。上述代碼在SimpleSms類的構(gòu)造函數(shù)中,直接將系統(tǒng)時刻以“年-月-日小時:分:秒”的格式保存在ReceiveTime屬性中。SmsReceiver類繼承BroadcastReceiver,重載了onReceive()函數(shù)。事實上系統(tǒng)消息的識不和系統(tǒng)關(guān)鍵字的識不并不復(fù)雜,我們只要能夠接收到vider.Telephony.SMS_RECIVED類型的系統(tǒng)消息,則表明是Android系統(tǒng)接收到了短信;將短信的內(nèi)容拆分后,推斷消息內(nèi)容是否是配置信息中定義的關(guān)鍵字,即可推斷該短信是否為天氣服務(wù)請求短信。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]); } 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ù)請求短信",Toast.LENGTH_SHORT) .show(); } } } }}第10行代碼將帶有pdus字符串特征的對象,通過Bundle.get()函數(shù)提取出來,在第12行代碼使用SmsMessage.CreateFromPdu()函數(shù)構(gòu)造SmsMessage對象,在第11行代碼使用循環(huán)語句是因為接收到的短信可能不止一條,從第14行和第15行代碼上看,那個地點只處理第1條短信,第17行代碼構(gòu)造SimpleSms對象,在代碼第18行調(diào)用WeatherService類的RequerSMSService()函數(shù),將SimpleSms對象添加到短信隊列中在AndroidManifest.xml文件中注冊短信監(jiān)聽器SmsReceiver,并聲明能夠接收短信的用戶許可android.permission.RECEIVE_SMS假如注冊的組件不在根命名空間中,則需要將子命名空間寫在類的前面。例如下面在代碼第1行中,因為SmsReceiver.java文件在edu.hrbeu.WeatherDemo.Service命名空間下,而不在根命名空間edu.hrbeu.WeatherDemo下,因此注冊組件時需要在類名SmsReceiver前添加.Service<receiverandroid:name=".Service.SmsReceiver"> <intent-filter><actionandroid:name="vider.Telephony.SMS_RECEIVED"/> </intent-filter></receiver><uses-permissionandroid:name=”android.permission.RECEIVE_SMS”/>3.4后臺服務(wù)后臺服務(wù)是WeatherDemo示例的核心模塊,在用戶啟動后持續(xù)在后臺運行,直到用戶手動停止服務(wù)。后臺服務(wù)功能:一是發(fā)送包含天氣信息的SMS短信(短信發(fā)送模塊)二是周期性的獵取Yahoo的天氣數(shù)據(jù)(數(shù)據(jù)獵取模塊)3.4.1短信發(fā)送模塊后臺服務(wù)在單獨的線程上運行,首先調(diào)用ProcessSmsList()函數(shù),檢查短信隊列中是否有需要回復(fù)的短信,然后調(diào)用GetGoogleWeatherData()函數(shù)獵取天氣數(shù)據(jù),最后線程暫停1秒,以釋放CPU資源,WeatherDemo示例后臺服務(wù)的核心代碼在WeatherService.java文件中下面是線程調(diào)用函數(shù)的部分代碼如下所述:privatestaticArrayList<SimpleSms>smslist=newArrayList<SimpleSms>();privateRunnablebackgroudWork=newRunnable(){ @Override publicvoidrun(){ try{ while(!Terrupted()){ ProcessSmsList(); GetGoogleWeatherData(); Thread.sleep(1000); } } catch(InterruptedExceptione){ e.printStackTrace(); } } };ProcessSmsList()函數(shù)用來檢查短信列表smsList,并依照Weather類中保存的天氣數(shù)據(jù),向請求者的發(fā)送回復(fù)短信,WeatherService.java文件的ProcessSmsList()函數(shù)代碼如下: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); } }發(fā)送短信是使用SmsManager對象的sendTextMessage()方法,該方法一共需要5個參數(shù):第1個參數(shù)是收件人地址,第2個參數(shù)是發(fā)件人地址,第3個參數(shù)是短信正文,第4個參數(shù)是發(fā)送服務(wù),第5個參數(shù)是送達服務(wù)。sendTextMessage()方法的收件人地址和短信正文是不可為空的參數(shù),而且一般GSM規(guī)范要求短信內(nèi)容要操縱在70個漢字以內(nèi)。代碼第8行的Weather.GetSmsMsg(),用來獲得供回復(fù)短信使用的天氣信息,因為考慮到短信的字數(shù)限制,僅返回當天和以后一天的天氣狀況。Weather.java文件的代碼如下:packageedu.hrbeu.WeatherDemo.Weather;importandroid.graphics.Bitmap;publicclassWeather{ publicstaticStringcity; publicstaticStringcode; publicstaticStringcountry; publicstaticStringtLowT; publicstaticStringtHighT; publicstaticStringtemp; publicstaticStringtDescription; publicstaticStringlatitude; publicstaticStringlongitude; publicstaticStringtime; publicstaticStringday_of_week; publicstaticStringcurrent_image_url; publicstaticBitmapcurrent_image; publicstaticForecast[]forecast=newForecast[2]; static{ for(inti=0;i<forecast.length;i++){ forecast[i]=newForecast(); } } publicstaticStringGetSmsMsg(){ Stringmsg=""; msg+=city+","; msg+=country+","+latitude+"."+longitude; msg+=","+day_of_week+","+tDescription+","+temp+"℃"; returnmsg; }}Forecast.java文件的代碼如下:packageedu.hrbeu.WeatherDemo.Weather;importandroid.graphics.Bitmap;publicclassForecast{ publicStringday_of_week; publicStringlow; publicStringhigh; publicStringimage_url; publicBitmapimage; publicStringcondition;}3.4.2數(shù)據(jù)庫獵取模塊數(shù)據(jù)獵取模塊:天氣數(shù)據(jù)是從Yahoo提供的WebService中獵取的,數(shù)據(jù)的獵取地址是/forecastrss?p=CHXX0037&u=c,CHXX0037表示獵取廣州的天氣數(shù)據(jù),讀者能夠替換CHXX0037,并將新的地址輸入Web掃瞄器,在掃瞄器中能夠直接看到XML格式的天氣數(shù)據(jù)。在資源目錄中的/res/xml/api.xml文件,確實是2012年12月16日api.xml文件的內(nèi)容如下:<?xmlversion="1.0"encoding="UTF-8"standalone="yes"?> <rssversion="2.0"xmlns:yweather="/ns/rss/1.0"xmlns:geo="/2003/01/geo/wgs84_pos#"> <channel> <title>Yahoo!Weather-Guangzhou,CH</title><link>/dailynews/rss/weather/Guangzhou__CH/*/forecast/CHXX0037_c.html</link><description>Yahoo!WeatherforGuangzhou,CH</description><language>en-us</language><lastBuildDate>Sun,16Dec201210:00amCST</lastBuildDate><ttl>60</ttl><yweather:locationcity="Guangzhou"region=""country="CH"/><yweather:unitstemperature="C"distance="km"pressure="mb"speed="km/h"/><yweather:windchill="24"direction="0"speed="0"/><yweather:atmospherehumidity="83"visibility="2.49"pressure="1015.92"rising="0"/><yweather:astronomysunrise="7:01am"sunset="5:43pm"/><image><title>Yahoo!Weather</title><width>142</width><height>18</height><link></link><url>/a/i/brand/purplelogo//uh/us/news-wea.gif</url></image><item><title>ConditionsforGuangzhou,CHat10:00amCST</title><geo:lat>23.12</geo:lat><geo:long>113.3</geo:long><link>/dailynews/rss/weather/Guangzhou__CH/*/forecast/CHXX0037_c.html</link><pubDate>Sun,16Dec201210:00amCST</pubDate><yweather:conditiontext="Fog"code="20"temp="24"date="Sun,16Dec201210:00amCST"/><description><![CDATA[<imgsrc="/a/i/us/we/52/20.gif"/><br/><b>CurrentConditions:</b><br/>Fog,24C<BR/><BR/><b>Forecast:</b><BR/>Sun-PartlyCloudy.High:26Low:16<br/>Mon-PartlyCloudy.High:24Low:16<br/><br/><ahref="/dailynews/rss/weather/Guangzhou__CH/*/forecast/CHXX0037_c.html">FullForecastatYahoo!Weather</a><BR/><BR/>(providedby<ahref="">TheWeatherChannel</a>)<br/>]]></description><yweather:forecastday="Sun"date="16Dec2012"low="16"high="26"text="PartlyCloudy"code="30"/><yweather:forecastday="Mon"date="17Dec2012"low="16"high="24"text="PartlyCloudy"code="30"/><guidisPermaLink="false">CHXX0037_2012_12_17_7_00_CST</guid></item></channel></rss><!--SunDec1603:10:19PST2012-->WeatherAdapter類實現(xiàn)了利用URL獵取位圖的私有函數(shù)GetURLBitmap(),以及用來下載和解析XML數(shù)據(jù)的公有函數(shù)GetWeatherData()。后臺服務(wù)在調(diào)用GetWeatherData()函數(shù)解析Yahoo提供的天氣數(shù)據(jù)時,會不斷調(diào)用GetURLBitmap()函數(shù),將XML數(shù)據(jù)中的天氣圖標依照圖標地址下載到本地保存。GetURLBitmap()函數(shù)的代碼如下:privatestaticBitmapGetURLBitmap(StringurlString){ URLurl=null; Bitmapbitmap=null; try{ url=newURL("/a/i/us/we/52/"+urlString +".gif"); } catch(MalformedURLExceptione){ e.printStackTrace(); } try{ HttpURLConnectionconn=(HttpURLConnection)url.openConnection(); conn.connect(); InputStreamis=conn.getInputStream(); bitmap=BitmapFactory.decodeStream(is); is.close(); } catch(IOExceptione){ e.printStackTrace(); } returnbitmap; }}getweather()函數(shù)首先依照指定的URL地址,從網(wǎng)絡(luò)獵取字節(jié)流數(shù)據(jù),然后調(diào)用輕量級XML解析器XmlPullParser對天氣數(shù)據(jù)進行解析,并將解析結(jié)果保存在Weather類的公有靜態(tài)屬性中g(shù)etweather()函數(shù)的代碼如下:publicstaticvoidgetWeather()throwsMalformedURLException, XmlPullParserException,IOException{ Stringvalue=City.getCode(Config.CityName); StringqueryString="/forecastrss?w=" +value+"&u=c"; System.out.println(queryString); System.out.println(Config.CityName) XmlPullParserparser=Xml.newPullParser(); parser.setInput(newURL(queryString).openConnection().getInputStream(), "UTF-8"); intcode=parser.getEventType(); StringpreString=null; intposition=0; while(code!=XmlPullParser.END_DOCUMENT){ switch(code){ caseXmlPullParser.START_TAG: preString=parser.getName(); if(preString.equals("location")){ Weather.city=parser.getAttributeValue(0); Weather.country=parser.getAttributeValue(2); } elseif(preString.equals("condition")){ Weather.tDescription=parser.getAttributeValue(0); Weather.current_image_url=parser.getAttributeValue(1); Weather.temp=parser.getAttributeValue(2); Weather.day_of_week=parser.getAttributeValue(3); Weather.current_image=GetURLBitmap(Weather.current_image_url); } elseif(preString.equals("forecast")){ Weather.forecast[position].low=parser .getAttributeValue(2); Weather.forecast[position].high=parser .getAttributeValue(3); Weather.forecast[position].day_of_week=parser .getAttributeValue(0); Weather.forecast[position].condition=parser .getAttributeValue(4); Weather.forecast[position].image_url=parser .getAttributeValue(5); Weather.forecast[position].image=GetURLBitmap(Weather.forecast[position].image_url); position++; } break; caseXmlPullParser.END_TAG: preString=null; break; caseXmlPullParser.TEXT: if(preString==null) break; if(preString.equals("lat")){ Weather.latitude=parser.getText(); } elseif(preString.equals("long")){ Weather.longitude=parser.getText(); } elseif(preString.equals("pubDate")) Weather.time=parser.getText(); break; caseXmlPullParser.START_DOCUMENT: break; default: break; } code=parser.next(); } }最后,在AndroidManifest.xml文件中注冊WeatherService,并聲明連接互聯(lián)網(wǎng)和發(fā)送SMS短信的兩個用戶許可。<serviceandroid:name=”.Service.WeatherService”/><uses-permissionandroid:name="android.permission.INTERNET"/> <uses-permissionandroid:name="android.permission.RECEIVE_SMS"/>3.5用戶界面在用戶界面設(shè)計上,采納能夠在多個分頁上快速切換的Tab標簽頁,WeatherDemo示例的Tab標簽頁將每個標簽頁與一個Activity關(guān)聯(lián)在一起,如此做的好處確實是能夠?qū)⒉煌瑯撕烅摰拇a放在不同的文件中,而且每個標簽頁都能夠有獨立的選項菜單。WeatherDemo類是繼承TabActivity的Tab標簽頁,共設(shè)置3個標簽頁(1)TAB1標簽頁的標題為“天氣預(yù)報”,關(guān)聯(lián)的Activity為WeatherActivity(2)TAB2標簽頁的標題為“歷史數(shù)據(jù)”,關(guān)聯(lián)Activity為HistoryActivity(3)TAB3標簽頁的標題為“系統(tǒng)設(shè)置”,關(guān)聯(lián)Activity為SetupActivity(4)TAB4標簽頁的標題為“地圖信息”,關(guān)聯(lián)Activity為GoogleMapActivityWeatherDemo.java文件的完整代碼如下:packageedu.hrbeu.WeatherDemo;importandroid.app.TabActivity;importandroid.content.Intent;importandroid.os.Bundle;importandroid.widget.TabHost;publicclassWeatherDemoextendsTabActivity{ /**Calledwhentheactivityisfirstcreated.*/ @Override publicvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); TabHosttabHost=getTabHost(); tabHost.addTab(tabHost .newTabSpec("TAB1") .setIndicator("天氣預(yù)報", getResources().getDrawable(R.drawable.tab_weather)) .setContent(newIntent(this,WeatherActivity.class))); tabHost.addTab(tabHost .newTabSpec("TAB2") .setIndicator("歷史數(shù)據(jù)", getResources().getDrawable(R.drawable.tab_history)) .setContent(newIntent(this,HistoryActivity.class))); tabHost.addTab(tabHost .newTabSpec("TAB3") .setIndicator("系統(tǒng)設(shè)置", getResources().getDrawable(R.drawable.tab_setup)) .setContent(newIntent(this,SetupActivity.class))); tabHost.addTab(tabHost .newTabSpec("TAB4") .setIndicator("地圖信息", getResources().getDrawable(R.drawable.tab_map)) .setContent(newIntent(this,GoogleMapActivity.class))); }}WeatherDemo.java中的代碼只是用戶界面的框架,設(shè)置了Tab標簽頁的圖標、標題和所關(guān)聯(lián)的Activity,標簽頁中的具體顯示內(nèi)容還要依靠于每個Activity所設(shè)置的界面布局。3.5.1WeatherActivityWeatherActivity在啟動時并不能夠顯示最新的天氣信息,用戶需要通過選項菜單的“啟動服務(wù)”開啟后臺服務(wù),然后點擊“刷新”獵取最新的天氣狀況,選項菜單還提供“停止服務(wù)”和“退出”選項。WeatherActivity使用的布局文件是tab_weather.xml,這是個較為繁瑣的界面布局,多次的使用了垂直和水平的線性布局。WeatherActivity的界面布局和代碼并不難以理解,因此那個地點不再給出WeatherActivity.java和tab_weather.xml具體代碼。WeatherActivity用戶界面圖(啟動服務(wù)后)如圖3.5.1所示:圖3.5.1WeatherActivity用戶界面3.5.2HistoryActivityHistoryActivity:要緊用來顯示SQLite數(shù)據(jù)庫中的短信服務(wù)信息,顯示的內(nèi)容包括發(fā)送者的手機號碼、時刻和回復(fù)短信內(nèi)容。為了能夠以列表的形式顯示多行數(shù)據(jù),并定制每行數(shù)據(jù)的布局。HistoryActivity用戶界面圖如圖3.5.2所示:圖3.5.2HistoryActivity用戶界面那個地點使用了ListActivity,ListActivity能夠不通過setContentView()設(shè)置布局,也不必重載onCreate()函數(shù),而直接將顯示列表加載到ListActivity,增加了使用的便利性。在WeatherDemo示例中,仍然使用setContentView()設(shè)置布局,如此做的好處是能夠在界面中設(shè)置更為復(fù)雜的顯示元素,例如在列表上方增加了提示信息“SQLite數(shù)據(jù)庫中的短信服務(wù)信息”。下方的代碼是HistoryActivity.java文件的onCreate()函數(shù)中的設(shè)置布局和加載適配器的關(guān)鍵代碼:setContentView(R.layout.tab_history);setListAdapter(dataAdapter);tab_history.xml是HistoryActivity的布局文件,下面先分析一下tab_history.xml的內(nèi)容tab_history.xml文件的完整代碼如下:<?xmlversion="1.0"encoding="utf-8"?><LinearLayoutxmlns:android="/apk/res/android" android:orientation="vertical"android:layout_width="fill_parent" android:layout_height="fill_parent"android:background="@drawable/black"> <TextViewandroid:layout_width="wrap_content" android:layout_height="wrap_content"android:text="SQLite數(shù)據(jù)庫中的短信服務(wù)信息:"> </TextView> <ListViewandroid:id="@android:id/list"android:layout_width="fill_parent" android:layout_height="wrap_content"android:layout_marginTop="2dip"> </ListView></LinearLayout>tab_history.xml中ListView控件,并使用系統(tǒng)的ID值“@android:id/list”,ListView的數(shù)據(jù)列配器是通過setListAdapter(dataAdapter)設(shè)置的。ListView使用的是自定義布局,布局保存在data_row.xml文件中,data_row.xml的完整代碼如下:<LinearLayoutxmlns:android="/apk/res/android" android:orientation="horizontal"android:layout_width="fill_parent" android:layout_height="fill_parent"android:background="@drawable/white" android:layout_marginTop="2dip"> <LinearLayoutandroid:orientation="vertical" android:layout_width="fill_parent"android:layout_height="fill_parent"> <TextViewandroid:id="@+id/data_row_01" android:layout_gravity="center_vertical"android:layout_width="fill_parent" android:layout_height="wrap_content"android:textSize="12dip" android:textColor="@drawable/black"/> <TextViewandroid:id="@+id/data_row_02" android:layout_gravity="center_vertical"android:layout_width="fill_parent" android:layout_height="wrap_content"android:textSize="12dip" android:textColor="@drawable/black"android:layout_marginTop="3dip"/> </LinearLayout></LinearLayout>Android提供的數(shù)據(jù)適配器僅同意保存字符串數(shù)組或列表對象,假如希望使用自定義布局,則需要實現(xiàn)自定義的數(shù)據(jù)適配器,并繼承Android提供的BaseAdapter(Android.widget.BaseAdapter)對象。自定義的數(shù)據(jù)適配器在SmsAdapter.java文件中,其完整代碼如下:packageedu.hrbeu.WeatherDemo.SMS;importandroid.content.Context;importandroid.view.LayoutInflater;importandroid.view.View;importandroid.view.ViewGroup;importandroid.widget.BaseAdapter;importandroid.widget.TextView;importedu.hrbeu.WeatherDemo.DB.DBAdapter;importedu.hrbeu.WeatherDemo.R;publicclassSmsAdapterextendsBaseAdapter{ privateLayoutInflatermInflater; privatestaticDBAdapterdbAdapter; privatestaticSimpleSms[]smsList; publicSmsAdapter(Contextcontext) {

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論