版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
1、第11章 綜合示例(shl)設(shè)計與開發(fā)共九十二頁本章學習(xux)目標:了解(lioji)Android應用程序的設(shè)計和開發(fā)過程掌握使用多種組件進行Android程序開發(fā)的方法共九十二頁11.1 需求(xqi)分析設(shè)計本章的初衷希望讀者能夠(nnggu)根據(jù)實際項目的需求,準確的分析出Android應用程序開發(fā)所可能涉及到的知識點,并學會如何通過分析軟件的需求,快速的設(shè)計出應用程序的用戶界面和模塊結(jié)構(gòu),并最終完成應用程序的開發(fā)和調(diào)試共九十二頁11.1 需求(xqi)分析功能需求本章提供的“天氣預報短信服務軟件”是一個略微復雜的示例。在這個綜合示例中,有一個顯示天氣情況的用戶界面,可以通過圖片和
2、文字顯示當前和未來幾天的天氣狀況,包括溫度、濕度(shd)、風向和雨雪情況等。這些天氣數(shù)據(jù)是通過后臺服務獲取的,這個后臺服務可以按照一定時間間隔,從Google上獲取天氣預報信息,并將天氣信息保存在后臺服務中。示例還需要提供基于SMS短信的天氣數(shù)據(jù)服務,其他手機用戶可以向本示例所在的手機上發(fā)送SMS短信,并在短信中包含用戶指定的關(guān)鍵字,則可以將保存在后臺服務中的天氣情況,再通過SMS短信回復給用戶。最后,每個被發(fā)送的SMS短信都要被記錄下來,用戶可以瀏覽或刪除這些回復信息共九十二頁11.1 需求(xqi)分析界面(jimin)需求本示例包含三個主要的用戶界面顯示天氣預報的用戶界面顯示已發(fā)送SM
3、S短信的用戶界面瀏覽和設(shè)置配置信息的用戶界面共九十二頁11.1 需求(xqi)分析內(nèi)部功能隱藏在用戶界面后面的內(nèi)部功能,是用戶界面能夠正確實現(xiàn)的基礎(chǔ)顯示天氣預報(tinqybo)的用戶界面獲取Google的天氣數(shù)據(jù)顯示SMS短信的用戶界面根據(jù)關(guān)鍵字監(jiān)視SMS短信發(fā)送包含天氣信息的SMS短信將發(fā)送的SMS短信寫入數(shù)據(jù)庫瀏覽和設(shè)置配置信息的用戶界面將用戶設(shè)置的配置信息保存到數(shù)據(jù)庫啟動時讀取數(shù)據(jù)庫中的配置信息恢復缺省設(shè)置共九十二頁11.2 程序設(shè)計(chn x sh j)11.2.1 用戶界面設(shè)計詳細分析應用程序中三個主要用戶界面包含的顯示內(nèi)容在“顯示天氣預報(tinqybo)的用戶界面”中,根據(jù)G
4、oogle可以提供的數(shù)據(jù),在界面上可以顯示當前的天氣狀況,包括城市名稱、溫度、濕度、風向、雨雪情況和獲取數(shù)據(jù)時間等信息;還可以顯示未來四天的天氣狀況,但僅包括溫度和雨雪情況在“顯示已發(fā)送SMS短信的用戶界面”中,應顯示每個回復短信的時間、目標手機號碼、城市名稱、當天的天氣狀況和未來一天的天氣狀況在“瀏覽和設(shè)置配置信息的用戶界面”中,應顯示獲取天氣預報的目標城市名稱、獲取數(shù)據(jù)的頻率和短信的關(guān)鍵字,并允許用戶設(shè)置是否提供短信服務以及是否記錄回復的短信信息共九十二頁11.2 程序設(shè)計(chn x sh j)11.2.1 用戶界面(yn h ji min)設(shè)計用戶界面的草圖共九十二頁11.2 程序設(shè)計
5、(chn x sh j)11.2.2 數(shù)據(jù)庫設(shè)計本示例主要存儲兩種數(shù)據(jù)配置信息:因為配置信息的數(shù)據(jù)量很小,從Android支持的存儲方式上分析,可以保存在SharePreference、文件或SQLite數(shù)據(jù)庫中SMS短信服務信息: SMS短信服務信息是一個隨著時間推移而不斷增加的數(shù)據(jù),屬于文本信息,而且有固定的格式,因此適合使用SQLite數(shù)據(jù)庫進行存儲綜合分析這兩種需要(xyo)存儲的數(shù)據(jù),選擇SQLite數(shù)據(jù)庫作為存儲數(shù)據(jù)的方法共九十二頁11.2 程序設(shè)計(chn x sh j)11.2.2 數(shù)據(jù)庫設(shè)計配置(pizh)信息配置信息中主要保存天氣信息查詢的城市名稱,訪問Google更新天氣
6、信息的頻率,請求天氣信息SMS短信的關(guān)鍵字,以及是否提供短信服務和是否記錄短信服務內(nèi)容配置信息的數(shù)據(jù)庫表結(jié)構(gòu)屬性數(shù)據(jù)類型說明_idinteger自動增加的主鍵city_nametext進行天氣信息查詢的城市名refresh_speedtext進行天氣信息查詢的頻率,單位為秒/次sms_servicetext是否提供短信服務,即接收到請求短信后是否回復包含天氣信息的短信sms_infotext是否記錄發(fā)出的SMS短信的信息key_wordtext短信服務的關(guān)鍵字,用以確定哪條短信是請求天氣服務的短信共九十二頁11.2 程序設(shè)計(chn x sh j)11.2.2 數(shù)據(jù)庫設(shè)計SMS短信服務信息(x
7、nx)SMS短信服務信息主要保存請求服務短信的發(fā)送者、短信內(nèi)容、接收時間和回復信息的內(nèi)容SMS短信服務信息的數(shù)據(jù)庫表結(jié)構(gòu)屬性數(shù)據(jù)類型說明_idinteger自動增加的主鍵sms_sendertext請求服務短信的發(fā)送者sms_bodytext請求服務短信的內(nèi)容信息sms_receive_timetext接收到請求服務短信的時間return_resulttext回復短信的內(nèi)容共九十二頁11.2 程序設(shè)計(chn x sh j)11.2.3 程序模塊設(shè)計從功能需求上分析(fnx),可以將整個應用程序劃分為4個模塊,分別是用戶界面、后臺服務、數(shù)據(jù)庫適配器和短信監(jiān)聽器。下圖是模塊結(jié)構(gòu)圖共九十二頁11.
8、2 程序設(shè)計(chn x sh j)11.2.3 程序模塊設(shè)計由模塊結(jié)構(gòu)圖中可知,后臺服務是整個應用程序的核心,主要包含兩個子模塊,一個是“數(shù)據(jù)獲取模塊”,負責周期性的從Google獲取天氣信息;另一個是“短信服務模塊”,負責處理接收到的服務請求短信,并發(fā)送包含天氣信息的短信后臺服務由用戶界面通過Intent啟動,啟動后的后臺服務可以在用戶界面關(guān)閉后仍然保持運行狀態(tài),直到用戶通過用戶界面發(fā)送Intent停止服務,或系統(tǒng)(xtng)因資源不足而強行關(guān)閉服務共九十二頁11.2 程序設(shè)計(chn x sh j)11.2.3 程序模塊設(shè)計用戶界面從后臺服務獲取天氣信息,而沒有直接通過網(wǎng)絡訪問Googl
9、e的天氣數(shù)據(jù)一方面是因為后臺服務使用了工作線程,通過后臺服務獲取天氣數(shù)據(jù)可以避免因網(wǎng)絡通信不暢造成界面失去響應另一方面,在用戶關(guān)閉界面后,后臺服務仍然需要更新天氣信息,以保證短信服務數(shù)據(jù)的準確性。用戶界面還會調(diào)用數(shù)據(jù)庫適配器,向SQLite數(shù)據(jù)庫中寫入、讀取配置信息,或?qū)MS短信服務信息進行(jnxng)操作共九十二頁11.2 程序設(shè)計(chn x sh j)11.2.3 程序模塊設(shè)計短信監(jiān)聽器是一個BroadcastReceiver,監(jiān)視(jinsh)所有接收到的短信如果短信中包含用戶自定義的關(guān)鍵字,短信監(jiān)聽器則會認為這條短信是天氣服務請求短信,將短信的相關(guān)信息寫入后臺服務的短信服務隊列如
10、果用戶在配置信息中選擇無需提供短信服務,短信監(jiān)聽器仍然繼續(xù)監(jiān)聽所有短信,只是后臺服務不再允許將服務請求短信寫入服務隊列數(shù)據(jù)庫適配器封裝了所有對SQLite數(shù)據(jù)庫操作的方法,用戶界面和后臺服務會調(diào)用它實現(xiàn)數(shù)據(jù)庫操作共九十二頁11.3 程序開發(fā)11.3.1 文件結(jié)構(gòu)與用途在程序開發(fā)階段,首先確定(qudng)“天氣預報短信服務軟件”的工程名稱為WeatherDemo,包名稱為edu.hrbeu.WeatherDemo,據(jù)程序模塊設(shè)計的內(nèi)容,建立WeatherDemo示例共九十二頁11.3 程序開發(fā)11.3.1 文件結(jié)構(gòu)與用途(yngt)WeatherDemo示例源代碼的文件結(jié)構(gòu)共九十二頁11.3
11、程序開發(fā)11.3.1 文件結(jié)構(gòu)與用途W(wǎng)eatherDemo示例設(shè)置(shzh)了多個命名空間,分別用來保存用戶界面、數(shù)據(jù)庫、后臺服務、SMS短信和天氣數(shù)據(jù)的源代碼文件WeatherDemo示例的命名空間命名空間說明edu.hrbeu.WeatherDemo存放與用戶界面相關(guān)的源代碼文件edu.hrbeu.WeatherDemo.DB存放與SQLite數(shù)據(jù)庫相關(guān)的源代碼文件edu.hrbeu.WeatherDemo.Service存放與后臺服務相關(guān)的源代碼文件edu.hrbeu.WeatherDemo.SMS 存放與SMS短信相關(guān)的源代碼文件edu.hrbeu.WeatherDemo.Weath
12、er 存放與天氣數(shù)據(jù)有關(guān)的源代碼文件共九十二頁11.3 程序開發(fā)11.3.1 文件結(jié)構(gòu)與用途W(wǎng)eatherDemo示例將不同用途的源代碼文件放置(fngzh)在不同的命名空間中包名稱文件名說明.WeatherDemoHistoryActivity.java“歷史數(shù)據(jù)”頁的ActivitySetupActivity.java“系統(tǒng)設(shè)置”頁的ActivityWeatherActivity.java“天氣預報”頁的ActivityWeatherDemo.java程序啟動缺省的Activity.WeatherDemo.DBConfig.java保存配置信息的類DBAdapter.java數(shù)據(jù)庫適配器.
13、WeatherDemo.ServiceSmsReceiver.java短信監(jiān)聽器WeatherAdapter.java數(shù)據(jù)獲取模塊WeatherService.java后臺服務.WeatherDemo.SMS SimpleSms.java簡化的SMS短信類SmsAdapter.java短信發(fā)送模塊.WeatherDemo.WeatherForecast.java未來天氣信息的類Weather.java當前天氣信息的類共九十二頁11.3 程序開發(fā)11.3.1 文件結(jié)構(gòu)與用途Android的資源(zyun)文件保存在/res的子目錄中/res/drawable目錄中保存的是圖像文件/res/lay
14、out目錄中保存的是布局文件/res/values目錄中保存的是用來定義字符串和顏色的文件/res/xml目錄保存的是XML格式的數(shù)據(jù)文件所有在程序開發(fā)階段可以被調(diào)用的資源都保存在這些目錄中共九十二頁11.3 程序開發(fā)11.3.1 文件(wnjin)結(jié)構(gòu)與用途資源文件名稱與用途資源目錄文件說明drawableicon.png圖標文件sunny.png調(diào)試用的天氣圖片tab_history.pngTabHost中“歷史數(shù)據(jù)”頁的圖片tab_setup.pngTabHost中“系統(tǒng)設(shè)置”頁的圖片tab_weather.pngTabHost中“天氣預報”頁的圖片layoutdata_row.xml“
15、歷史數(shù)據(jù)”頁ListActivity的每行數(shù)據(jù)的布局tab_history.xmlTabHost中“歷史數(shù)據(jù)”頁的布局tab_setup.xmlTabHost中“系統(tǒng)設(shè)置”頁的布局tab_weather.xmlTabHost中“天氣預報”頁的布局valuescolor.xml保存顏色的XML文件string.xml保存字符串的XML文件xmlapi.xml從Google下載的天氣數(shù)據(jù)文件。在程序運行時沒有實際作用,但在開發(fā)過程中可以讓讀者了解數(shù)據(jù)格式共九十二頁11.3 程序開發(fā)11.3.2 數(shù)據(jù)庫適配器數(shù)據(jù)庫適配器是最底層的模塊,主要用于封裝用戶界面和后臺服務對SQLite數(shù)據(jù)庫的操作,數(shù)據(jù)庫
16、適配器的核心代碼(di m)主要在DBAdapter.java文件中用戶保存配置信息的類文件Config.javaConfig.java文件的全部代碼如下package edu.hrbeu.WeatherDemo.DB; public class Config public static String CityName;public static String RefreshSpeed;public static String ProvideSmsService;public static String SaveSmsInfo;public static String KeyWord; 共九十
17、二頁11.3 程序開發(fā)11.3.2 數(shù)據(jù)庫適配器從代碼中不難看出,公有靜態(tài)屬性CityName、RefreshSpeed、ProvideSmsService、SaveSmsInfo和KeyWord,完全對應數(shù)據(jù)庫中保存配置信息表的屬性。在程序啟動后,保存在數(shù)據(jù)庫中的城市名稱、更新頻率、是否(sh fu)提供短信服務、是否(sh fu)保存短信信息和關(guān)鍵字等內(nèi)容,將被寫入這個Config類中,供其他模塊在做邏輯判斷時使用public static void LoadDefaultConfig()CityName = ;RefreshSpeed = 60;ProvideSmsService = t
18、rue;SaveSmsInfo = true;KeyWord = NY;共九十二頁11.3 程序開發(fā)11.3.2 數(shù)據(jù)庫適配器代碼第10行的LoadDefaultConfig()函數(shù),保存了程序內(nèi)置的配置參數(shù)此函數(shù)會在兩個情況下被調(diào)用用戶主動選擇“恢復缺省設(shè)置”首次啟動程序時,用來初始化保存配置參數(shù)的數(shù)據(jù)庫DBAdapter類與以往介紹過的數(shù)據(jù)庫適配器類相似,都具有繼承SQLiteOpenHelper的幫助類DBOpenHelperDBOpenHelper在建立數(shù)據(jù)庫時,同時(tngsh)建立兩個數(shù)據(jù)庫表,并對保存配置信息的表進行了初始化,初始化的相關(guān)代碼在第4249行共九十二頁11.3 程序
19、開發(fā)11.3.2 數(shù)據(jù)庫適配器private static final String DB_NAME = weather_app.db;private static final String DB_TABLE_CONFIG = setup_config;private static final String DB_CONFIG_ID = 1;private static final int DB_VERSION = 1; public static final String KEY_ID = _id;public static final String KEY_CITY_NAME = city
20、_name;public static final String KEY_REFRESH_SPEED = refresh_speed;public static final String KEY_SMS_SERVICE = sms_service;public static final String KEY_SMS_INFO = sms_info;public static final String KEY_KEY_WORD = key_word; private static final String DB_TABLE_SMS = sms_data;public static final S
21、tring KEY_SENDER = sms_sender;public static final String KEY_BODY = sms_body;public static final String KEY_RECEIVE_TIME = sms_receive_time;public static final String KEY_RETURN_RESULT = return_result; 共九十二頁11.3 程序開發(fā)11.3.2 數(shù)據(jù)庫適配器/*靜態(tài)Helper類,用于建立、更新和打開數(shù)據(jù)庫*/private static class DBOpenHelper extends SQ
22、LiteOpenHelper public DBOpenHelper(Context context, String name, CursorFactory factory, int version) super(context, name, factory, version); private static final String DB_CREATE_CONFIG = create table + DB_TABLE_CONFIG + ( + KEY_ID + integer primary key autoincrement, + KEY_CITY_NAME+ text not null,
23、 + KEY_REFRESH_SPEED+ text, + KEY_SMS_SERVICE + text, + KEY_SMS_INFO + text, + KEY_KEY_WORD + text); private static final String DB_CREATE_SMS = create table + DB_TABLE_SMS + ( + KEY_ID + integer primary key autoincrement, + KEY_SENDER+ text not null, + KEY_BODY+ text, + KEY_RECEIVE_TIME + text, + K
24、EY_RETURN_RESULT + text);共九十二頁11.3 程序開發(fā)11.3.2 數(shù)據(jù)庫適配器 Overridepublic void onCreate(SQLiteDatabase _db) _db.execSQL(DB_CREATE_CONFIG);_db.execSQL(DB_CREATE_SMS); /初始化系統(tǒng)配置的數(shù)據(jù)表Config.LoadDefaultConfig();ContentValues newValues = new ContentValues();newValues.put(KEY_CITY_NAME, Config.CityName);newValues
25、.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); 共九十二頁11.3 程序開發(fā)11.3.2 數(shù)據(jù)庫適配器 Overridepublic void onUpgrade(SQ
26、LiteDatabase _db, int _oldVersion, int _newVersion) _db.execSQL(DROP TABLE IF EXISTS + DB_TABLE_CONFIG); _db.execSQL(DROP TABLE IF EXISTS + DB_CREATE_SMS); onCreate(_db);共九十二頁11.3 程序開發(fā)11.3.2 數(shù)據(jù)庫適配器在DBAdapter類中,用戶界面會調(diào)用SaveConfig()和LoadConfig(),從SQLite數(shù)據(jù)庫中保存和讀取配置信息。保存配置信息時,SaveConfig()函數(shù)會將Config類中的公有靜
27、態(tài)(jngti)屬性寫入數(shù)據(jù)庫;反之,LoadConfig()會將數(shù)據(jù)庫中的配置信息寫入Config類中的公有靜態(tài)屬性SaveConfig()和LoadConfig()的代碼如下public void SaveConfig()ContentValues updateValues = new ContentValues(); updateValues.put(KEY_CITY_NAME, Config.CityName);updateValues.put(KEY_REFRESH_SPEED, Config.RefreshSpeed);updateValues.put(KEY_SMS_SERVIC
28、E, Config.ProvideSmsService);updateValues.put(KEY_SMS_INFO, Config.SaveSmsInfo);updateValues.put(KEY_KEY_WORD, Config.KeyWord);共九十二頁11.3 程序開發(fā)11.3.2 數(shù)據(jù)庫適配器 db.update(DB_TABLE_CONFIG, updateValues, KEY_ID + = + DB_CONFIG_ID, null);Toast.makeText(context, 系統(tǒng)設(shè)置保存成功, Toast.LENGTH_SHORT).show();public voi
29、d LoadConfig() Cursor result = db.query(DB_TABLE_CONFIG, new String 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;共九十二頁11.3 程序開發(fā)11.3.2 數(shù)據(jù)庫適配器 Config.CityN
30、ame = 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);Confi
31、g.KeyWord = result.getString(result.getColumnIndex(KEY_KEY_WORD);Toast.makeText(context, 系統(tǒng)設(shè)置讀取成功, Toast.LENGTH_SHORT).show();共九十二頁11.3 程序開發(fā)11.3.2 數(shù)據(jù)庫適配器另一個會調(diào)用DBAdapter類的是后臺服務,即WeatherService類后臺服務主要調(diào)用SaveOneSms(SimpleSms sms)、DeleteAllSms()和GetAllSms()函數(shù),分別用來保存SMS短信記錄、刪除所有(suyu)SMS數(shù)據(jù)記錄和獲取所有SMS數(shù)據(jù)記錄在G
32、etAllSms()函數(shù)中,調(diào)用了一個私有函數(shù)ToSimpleSms(Cursor cursor),用來將從數(shù)據(jù)庫獲取的數(shù)據(jù)轉(zhuǎn)換為SimpleSms對象數(shù)組SimpleSms類將在下一小節(jié)進行介紹下面是SaveOneSms(SimpleSms sms)、DeleteAllSms()和GetAllSms()函數(shù)的代碼共九十二頁11.3 程序開發(fā)11.3.2 數(shù)據(jù)庫適配器public void SaveOneSms(SimpleSms sms)ContentValues newValues = new ContentValues(); newValues.put(KEY_SENDER, sms.S
33、ender);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);public long DeleteAllSms() return db.delete(DB_TABLE_SMS, null, null);public SimpleSms GetAllSms() Cursor results = db
34、.query(DB_TABLE_SMS, new String KEY_ID, KEY_SENDER, KEY_BODY, KEY_RECEIVE_TIME, KEY_RETURN_RESULT, null, null, null, null, null); return ToSimpleSms(results); private SimpleSms ToSimpleSms(Cursor cursor)共九十二頁11.3 程序開發(fā)11.3.2 數(shù)據(jù)庫適配器int resultCounts = cursor.getCount();if (resultCounts = 0 | !cursor.mo
35、veToFirst()return null; SimpleSms sms = new SimpleSmsresultCounts;for (int i = 0 ; iresultCounts; i+)smsi = new SimpleSms();smsi.Sender = cursor.getString(cursor.getColumnIndex(KEY_SENDER);smsi.Body = cursor.getString(cursor.getColumnIndex(KEY_BODY);smsi.ReceiveTime = cursor.getString(cursor.getColu
36、mnIndex(KEY_RECEIVE_TIME);smsi.ReturnResult=cursor.getString(cursor.getColumnIndex(KEY_RETURN_RESULT);cursor.moveToNext();return sms; 共九十二頁11.3 程序開發(fā)11.3.3 短信監(jiān)聽器短信監(jiān)聽器本質(zhì)上是BroadcastReceiver,用于監(jiān)聽Android系統(tǒng)所接收到的所有(suyu)SMS短消息,可以在應用程序關(guān)閉后仍然繼續(xù)運行,核心代碼在SmsReceiver.java文件中在介紹SmsReceiver類前,先說明用來保存SMS短信內(nèi)容和相關(guān)信息的Si
37、mpleSms類。android.telephony.gsm.SmsMessage是Android提供的短信類,但這里需要一個更精簡、小巧的類,保存少量的信息,因此構(gòu)造了SimpleSms類,僅用來保存短信的發(fā)送者、內(nèi)容、接收時間和返回結(jié)果。這里的“返回結(jié)果”指的是返回包含天氣信息的短信內(nèi)容共九十二頁11.3 程序開發(fā)11.3.3 短信監(jiān)聽器SimpleSms.java文件完整(wnzhng)代碼:package edu.hrbeu.WeatherDemo.SMS;import java.text.SimpleDateFormat; public class SimpleSms public
38、String Sender;public String Body;public String ReceiveTime;public String ReturnResult; public SimpleSms()共九十二頁11.3 程序開發(fā)11.3.3 短信監(jiān)聽器第5行到第8行代碼的屬性Sender、Body、ReceiveTime和ReturnResult,分別表示SMS短信的發(fā)送者、內(nèi)容、接收時間和返回結(jié)果第15行和第16行的代碼在SimpleSms類的構(gòu)造函數(shù)中,直接將系統(tǒng)時間以“年-月-日 小時(xiosh):分:秒”的格式保存在ReceiveTime屬性中 public SimpleS
39、ms(String sender, String body)this.Sender = sender;this.Body = body;SimpleDateFormat tempDate = new SimpleDateFormat(yyyy-MM-dd + + hh:mm:ss);this.ReceiveTime = tempDate.format(new java.util.Date();this.ReturnResult = ;共九十二頁11.3 程序開發(fā)11.3.3 短信監(jiān)聽器SmsReceiver類繼承BroadcastReceiver,重載了onReceive()函數(shù)系統(tǒng)消息的識別
40、和關(guān)鍵字的識別并不復雜,只要(zhyo)接收vider.Telephony.SMS_RECEIVED類型的系統(tǒng)消息,則表明是Android系統(tǒng)接收到了短信;將短信的內(nèi)容拆分后,判斷消息內(nèi)容是否是配置信息中定義的關(guān)鍵字,即可判斷該短信是否為天氣服務請求短信共九十二頁11.3 程序開發(fā)11.3.3 短信監(jiān)聽器SmsReceiver.java文件的核心(hxn)代碼public class SmsReceiver extends BroadcastReceiverprivate static final String SMS_ACTION = vider.Telephony.SMS_RECEIVED
41、; Overridepublic void onReceive(Context context, Intent intent) if (intent.getAction().equals(SMS_ACTION)Bundle bundle = intent.getExtras();if (bundle != null) Object objs = (Object) bundle.get(pdus); SmsMessage messages = new SmsMessageobjs.length; for (int i = 0; iobjs.length; i+) messagesi = SmsM
42、essage.createFromPdu(byte) objsi); 共九十二頁11.3 程序開發(fā)11.3.3 短信監(jiān)聽器 String smsBody = messages0.getDisplayMessageBody(); String smsSender = messages0.getDisplayOriginatingAddress();if (smsBody.trim().equals(Config.KeyWord) & Config.ProvideSmsService.equals(true) SimpleSms simpleSms = new SimpleSms(smsSende
43、r, smsBody); WeatherService.RequerSMSService(simpleSms); Toast.makeText(context, 接收到服務請求短信, Toast.LENGTH_SHORT).show(); 共九十二頁11.3 程序開發(fā)11.3.3 短信監(jiān)聽器第10行代碼將帶有pdus字符串特征的對象,通過Bundle.get()函數(shù)提取出來在第12行代碼使用SmsMessage.CreateFromPdu()函數(shù)構(gòu)造SmsMessage對象在第11行代碼使用循環(huán)語句是因為接收到的短信可能不止一條從第14行和第15行代碼上看,這里只處理第1條短信第17行代碼構(gòu)造
44、SimpleSms對象在代碼第18行調(diào)用WeatherService類的RequerSMSService()函數(shù),將SimpleSms對象添加(tin ji)到短信隊列中共九十二頁11.3 程序開發(fā)11.3.3 短信監(jiān)聽器在AndroidManifest.xml文件中注冊短信監(jiān)聽器SmsReceiver,并聲明可以接收短信的用戶許可android.permission.RECEIVE_SMS如果(rgu)注冊的組件不在根命名空間中,則需要將子命名空間寫在類的前面共九十二頁11.3 程序開發(fā)11.3.3 短信監(jiān)聽器例如下面在代碼第1行中,因為SmsReceiver.java文件(wnjin)在e
45、du.hrbeu.WeatherDemo.Service命名空間下,而不在根命名空間edu.hrbeu.WeatherDemo下,因此注冊組件時需要在類名SmsReceiver前添加.Service 共九十二頁11.3 程序開發(fā)11.3.4 后臺服務后臺服務是WeatherDemo示例的核心模塊,在用戶啟動后持續(xù)在后臺運行,直到用戶手動停止服務后臺服務功能一是發(fā)送包含天氣(tinq)信息的SMS短信(短信發(fā)送模塊)二是周期性的獲取Google的天氣數(shù)據(jù)(數(shù)據(jù)獲取模塊)共九十二頁11.3 程序開發(fā)11.3.4 后臺服務短信發(fā)送模塊:后臺服務在單獨的線程上運行首先調(diào)用ProcessSmsList(
46、)函數(shù),檢查短信隊列中是否有需要(xyo)回復的短信然后調(diào)用GetGoogleWeatherData()函數(shù)獲取天氣數(shù)據(jù)最后線程暫停1秒,以釋放CPU資源WeatherDemo示例后臺服務的核心代碼在WeatherService.java文件中共九十二頁11.3 程序開發(fā)11.3.4 后臺服務下面是線程調(diào)用函數(shù)的部分(b fen)代碼private static ArrayList smsList = new ArrayList(); private Runnable backgroudWork = new Runnable()Overridepublic void run() trywhil
47、e(!Terrupted()ProcessSmsList();GetGoogleWeatherData();Thread.sleep(1000); catch (InterruptedException e) e.printStackTrace();共九十二頁11.3 程序開發(fā)11.3.4 后臺服務ProcessSmsList()函數(shù)用來檢查(jinch)短信列表smsList,并根據(jù)Weather類中保存的天氣數(shù)據(jù),向請求者的發(fā)送回復短信WeatherService.java文件的ProcessSmsList()函數(shù)代碼如下共九十二頁11.3 程序開發(fā)11.3.4 后臺(huti)服務pri
48、vate void ProcessSmsList()if (smsList.size()=0)return;SmsManager smsManager = SmsManager.getDefault();PendingIntent mPi = PendingIntent.getBroadcast(this, 0, new Intent(), 0);while(smsList.size()0)SimpleSms sms = smsList.get(0);smsList.remove(0);smsManager.sendTextMessage(sms.Sender, null, Weather.G
49、etSmsMsg(), mPi, null);sms.ReturnResult = Weather.GetSmsMsg();SaveSmsData(sms);共九十二頁11.3 程序開發(fā)11.3.4 后臺服務發(fā)送短信是使用(shyng)SmsManager對象的sendTextMessage()方法,該方法一共需要5個參數(shù)第1個參數(shù)是收件人地址第2個參數(shù)是發(fā)件人地址第3個參數(shù)是短信正文第4個參數(shù)是發(fā)送服務第5個參數(shù)是送達服務sendTextMessage()方法的收件人地址和短信正文是不可為空的參數(shù),而且一般GSM規(guī)范要求短信內(nèi)容要控制在70個漢字以內(nèi)代碼第8行的Weather.GetSmsM
50、sg(),用來獲得供回復短信使用的天氣信息,因為考慮到短信的字數(shù)限制,僅返回當天和未來一天的天氣狀況共九十二頁11.3 程序開發(fā)11.3.4 后臺服務(fw)Weather.java文件的代碼如下package edu.hrbeu.WeatherDemo.Weather;import android.graphics.Bitmap; public class Weather public static String city;public static String forecase_date;public static String current_date_time;public stat
51、ic String current_condition;public static String current_temp;public static String current_humidity;public static String current_image_url;public static Bitmap current_image;public static String current_wind;共九十二頁11.3 程序開發(fā)11.3.4 后臺(huti)服務public static Forecast day = new Forecast4;static for (int i
52、= 0; i day.length; i+)dayi = new Forecast();public static String GetSmsMsg()String msg = ;msg += city + ,;msg += current_condition + , + current_temp+. ;msg += day0.day_of_week+“, ” + day0.condition + “, ” + 、day0.high + / + day0.low; return msg;共九十二頁11.3 程序開發(fā)11.3.4 后臺服務Forecast.java文件(wnjin)的代碼如下pa
53、ckage edu.hrbeu.WeatherDemo.Weather;import android.graphics.Bitmap; public class Forecast public String day_of_week;public String low;public String high;public String image_url;public Bitmap image;public String condition;共九十二頁11.3 程序開發(fā)11.3.4 后臺服務數(shù)據(jù)獲取模塊:天氣數(shù)據(jù)是從Google提供的Web Service中獲取的,數(shù)據(jù)的獲取地址是/ig/api?
54、hl=en&weather=New%20YorkNew%20York表示獲取紐約(New York)的天氣數(shù)據(jù),%20表示一個空格讀者可以替換New%20York,并將新的地址輸入Web瀏覽器,在瀏覽器中可以直接看到XML格式的天氣數(shù)據(jù)在資源目錄中的/res/xml/api.xml文件(wnjin),就是2009年9月22日獲取的紐約天氣數(shù)據(jù)在程序資源中保留api.xml文件,主要是用來幫助讀者分析XML數(shù)據(jù)格式,在程序運行期間并不訪問該文件共九十二頁11.3 程序開發(fā)11.3.4 后臺(huti)服務api.xml文件的內(nèi)容如下共九十二頁11.3 程序開發(fā)11.3.4 后臺(huti)服務
55、共九十二頁11.3 程序開發(fā)11.3.4 后臺(huti)服務 共九十二頁11.3 程序開發(fā)11.3.4 后臺服務標簽內(nèi)的數(shù)據(jù)是天氣預報的城市和時間等基本信息(xnx),標簽內(nèi)的是當時的天氣狀況,4個標簽是未來四天的天氣情況在api.xml文件中,還提供了能夠反映天氣情況的圖標地址,例如第19行、第27行和第35行等 共九十二頁11.3 程序開發(fā)11.3.4 后臺服務WeatherAdapter類實現(xiàn)了利用URL獲取位圖的私有函數(shù)GetURLBitmap(),以及用來下載和解析XML數(shù)據(jù)的公有函數(shù)GetWeatherData()后臺服務在調(diào)用GetWeatherData()函數(shù)解析Google
56、提供的天氣數(shù)據(jù)時,會不斷調(diào)用GetURLBitmap()函數(shù),將XML數(shù)據(jù)中的天氣圖標根據(jù)圖標地址(dzh)下載到本地保存共九十二頁11.3 程序開發(fā)11.3.4 后臺服務GetURLBitmap()函數(shù)(hnsh)的代碼如下private static Bitmap GetURLBitmap(String urlString)URL url = null;Bitmap bitmap = null;try url = new URL( + urlString);catch (MalformedURLException e)e.printStackTrace();tryHttpURLConnec
57、tion conn = (HttpURLConnection) url.openConnection();conn.connect();InputStream is = conn.getInputStream();bitmap = BitmapFactory.decodeStream(is);is.close();共九十二頁11.3 程序開發(fā)11.3.4 后臺服務第12行代碼(di m)構(gòu)造了支持HTTP功能的URLConnection第14行代碼返回字節(jié)流第15行代碼使用字節(jié)流產(chǎn)生位圖第16行代碼關(guān)閉字節(jié)流 catch (IOException e)e.printStackTrace();r
58、eturn bitmap;共九十二頁11.3 程序開發(fā)11.3.4 后臺服務(fw)GetWeatherData()函數(shù)首先根據(jù)指定的URL地址,從網(wǎng)絡獲取字節(jié)流數(shù)據(jù),然后調(diào)用輕量級XML解析器XmlPullParser對天氣數(shù)據(jù)進行解析,并將解析結(jié)果保存在Weather類的公有靜態(tài)屬性中GetWeatherData()函數(shù)的代碼如下public static void GetWeatherData() throws IOException, Throwable String queryString = /ig/api?weather= + Config.CityName;URL aURL =
59、 new URL(queryString.replace( , %20);URLConnection conn = aURL.openConnection();conn.connect();InputStream is = conn.getInputStream(); XmlPullParserFactory factory = XmlPullParserFactory.newInstance()factory.setNamespaceAware(true);XmlPullParser parser = factory.newPullParser();parser.setInput(is,UT
60、F-8);共九十二頁11.3 程序開發(fā)11.3.4 后臺(huti)服務12. int dayCounter = 0;while(parser.next()!= XmlPullParser.END_DOCUMENT) String element = parser.getName(); if (element != null & element.equals(forecast_information) while(true) int eventCode = parser.next(); element = parser.getName(); if (eventCode = XmlPullPar
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 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. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2026年一級造價師考試題庫300道帶答案(突破訓練)
- 2026年心理咨詢師之心理咨詢師二級技能考試題庫附參考答案ab卷
- 2026年企業(yè)人力資源管理師考試備考題庫附完整答案【易錯題】
- 2026年心理咨詢師之心理咨詢師基礎(chǔ)知識考試題庫及完整答案
- 2026年高校教師資格證之高等教育法規(guī)考試題庫【有一套】
- 2026年一級造價師考試題庫300道及答案1套
- 2026年高校教師資格證之高等教育法規(guī)考試題庫(考點梳理)
- 2026年法律法規(guī)考試題庫及答案【名師系列】
- 在協(xié)議書上莊嚴簽字
- 2025 年高職動物防疫與檢疫(動物防疫技術(shù))試題及答案
- YC/T 273-2014卷煙包裝設(shè)計要求
- 小學英語五年級上冊人教版(PEP)知識競賽題
- XX縣尸體解剖檢驗中心可行性研究報告項目建議書
- 微型往復活塞空壓機使用維護專項說明書
- 高效節(jié)能日光溫室設(shè)計方案
- 幼兒園園本課程開發(fā)的困境與對策研究-以S幼兒園為例
- 曼昆《經(jīng)濟學原理》(微觀經(jīng)濟學分冊)第8版 全部答案
- 西安菲爾特金屬材料過濾有限公司金屬纖維及過濾器生產(chǎn)建設(shè)項目安全專篇
- 軍事地形學知識總結(jié)
- 酒店安全生產(chǎn)責任制清單(全套模板)
- FAS電路板功能及接口特性
評論
0/150
提交評論