本章將創(chuàng)建一款“開車不發(fā)短信”的應用,讓你在開車時能夠自動回復收到的短信。一名計算機入門課上的新生首創(chuàng)了這款應用,與美國國家農(nóng)場保險公司開發(fā)的一款裝機量巨大的應用相類似。App Inventor可以利用Android手機中的某些強大功能,包括SMS短信處理、數(shù)據(jù)庫管理、文本轉(zhuǎn)成語音以及位置傳感器等,本應用就是一個典型的例子。
美國國家安全委員會(NSC)于2010年1月發(fā)布的研究結(jié)果表明,每年有至少28%的交通事故——將近160萬次車禍源于司機在開車時使用手機,其中至少20萬次交通事故與發(fā)短信有關(guān)(http://www.nsc.org/pages/nscestimates16millioncrashescausedbydriversusingcellphonesandtexting.aspx)。因此,許多國家已經(jīng)全面禁止司機開車時使用手機。
Daniel Finnegan,一個舊金山大學的學生,在2010年秋季學期的App Inventor編程課上,提出了一個了不起的想法,用一個應用來解決開車發(fā)短信泛濫的問題。如圖4-1所示,他創(chuàng)建的應用可以對收到的任何短信進行自動回復,如回復“我正在開車,稍后與您聯(lián)系”之類的內(nèi)容。
圖 4-1 “開車不發(fā)短信”
課堂上的頭腦風暴增加了應用的功能,也豐富了本教程,這些內(nèi)容發(fā)布在App Inventor網(wǎng)站上:
用戶可以根據(jù)情況改變回復內(nèi)容:例如,如果你正在開會或看電影,而不是開車,回復內(nèi)容可以做相應的修改;
應用可以大聲朗讀來信內(nèi)容:盡管有自動回復,但對來信的好奇心也會置你于死地;
就在本應用發(fā)布到App Inventor網(wǎng)站后的幾周,State Farm Insurance創(chuàng)建了名為“On the Move”的Android應用,http://www.statefarm.com/aboutus/newsroom/20100819.asp【譯者沒找到On the Move,不過該公司的確有幾個好的應用值得嘗試】,其功能與“開車不發(fā)短信”類似。該公司將這項服務作為“掌上代理”應用的升級內(nèi)容,免費向所有人開放,并在YouTube網(wǎng)站發(fā)布視頻:http://www.youtube.com/watch?v=3xtjzO0-Hfw【譯者訪問該網(wǎng)址,提示“此視頻未公開”】。
我們無法確認Daniel的應用或App Inventor網(wǎng)站的教程是否對“On the Move”產(chǎn)生了影響,但有趣的是,這讓我們思考一種可能性:在一門編程基礎課上創(chuàng)建的應用(竟然由一個創(chuàng)意寫作的學生創(chuàng)建?。┮苍S會促成軟件的批量生產(chǎn),或至少是對軟件生產(chǎn)的生態(tài)系統(tǒng)有所貢獻。當然,這也說明了App Inventor降低了軟件開發(fā)的門檻,以至于無論是誰,只要有一個好主意,都可以快速、低成本地把想法變成一個實實在在的、可交互的應用。
相比前幾章來說,這是一個更加復雜的應用,因此我們每次只完成一項功能,從自動回復開始。以下是將要學習的內(nèi)容:
Texting組件:具有收發(fā)短信功能;
TextBox組件:用于提交自定義回復信息(需要與Button組件配合使用);
TinyDB數(shù)據(jù)庫組件:用于保存自定義信息,即使應用已經(jīng)關(guān)閉,信息也不會丟失;
Screen.Initialize事件:在應用啟動時加載自定義回復內(nèi)容;
Text-to-Speech組件:用于大聲朗讀文字;
本應用的運行,需要手機上Text-To-Speech(TTS)模塊的支持。該模塊包含在Android 2或更高的版本中,如果你的操作系統(tǒng)是Android 1.x,需要從Google Play下載。在手機上:
1. 打開Google Play應用;
2. 搜索TTS;
3. 選擇應用Text-To-Speech Extended并安裝。
TTS模塊安裝后,可以測試其功能。對于Android2以上版本,在"設置->輔助功能"中打開“文字轉(zhuǎn)換語音輸出”功能,根據(jù)需要設置默認語言及語速,然后選擇“收聽示例”。如果沒聽到任何聲音,請確認手機音量已調(diào)高;還可以更改TTS引擎默認屬性設置,來改變聲音效果。
TTS模塊設置完成后,登陸App Inventor網(wǎng)站開始新項目“NoTextingWhileDriving”(項目名中不能有空格),然后設置屏幕的標題為“開車不發(fā)短信”,最后通過WiFi與測試手機(AI伴侶)連接。
應用的用戶界面很簡單:一個顯示自動回復內(nèi)容的Label,一個編輯自動回復信息的文本輸入框和一個提交輸入結(jié)果的按鈕。還需要拖入一個Texting組件、一個TinyDB組件、一個TextToSpeech組件以及一個LocationSensor組件,這些組件都將出現(xiàn)在“不可視組件”區(qū)。你可以在圖4-2中看到上述組件在設計器中的截圖。
圖 4-2 組件設計器中的“開車不發(fā)短信”應用
將表4-1中列出的組件拖到預覽窗口中,創(chuàng)建出圖4-2中所示的用戶界面。
表4-1 “開車不發(fā)短信”應用中的全部組件
組件類型 | 面板中分組 | 命名 | 作用 |
---|---|---|---|
Label | User Interface | PromptLabel | 讓用戶了解應用的功能 |
Label | User Interface | ResponseLabel | 顯示即將發(fā)送的自動回復信息 |
TextBox | User Interface | NewResponseTextbox | 用戶在此處輸入定制的回復信息 |
Button | User Interface | SubmitResponseButton | 用戶點擊來提交、保存回復信息 |
Texting | Social | Texting1 | 處理短信事務 |
TinyDB | Storage | TinyDB1 | 將自動回復信息保存在數(shù)據(jù)庫中 |
TextToSpeech | Media | TextToSpeech1 | 大聲朗讀來信 |
LocationSensor | Sensors | LocationSensor1 | 感知電話所在位置 |
按照以下方式設置組件屬性:
設置PromptLabel的Text屬性為“當本應用正在運行時,將用下面的文字來回復所有收到的短信。”
設置ResponseLabel的Text屬性為“我正在開車,稍后與您聯(lián)系。”并勾選FontBold(粗體字)屬性;
設置NewResponseTextbox的Text屬性為“”(讓文本框為空,等待用戶輸入);
設置NewResponseTextbox的Hint(提示)屬性為“輸入新的回復內(nèi)容”,Width設為“Fill Parent”;
從基本的自動回復行開始,再逐步添加更多功能。
自動回復功能需要用到App Inventor的Texting組件,可以把它想象成一個藏在手機里的小矮人,它知曉如何收發(fā)短信。該組件用Texting.MessageReceived事件塊來響應“收到短信”,拖出該事件塊,并在塊內(nèi)放入一些命令塊,看看當你收到短信時,會發(fā)生什么事情。這里我們希望能夠自動回復預先編輯好的內(nèi)容。
發(fā)送短信的操作需要調(diào)用Texting1.SendMessage塊,將其放在Texting1.MessageReceived塊內(nèi)。Texting1.SendMessage塊只能發(fā)送短信,至于要發(fā)什么內(nèi)容,以及發(fā)給誰,需要在調(diào)用之前,由你來告訴它:表4-2列出了自動回復行為所需要的塊,而圖4-3顯示了它們在塊編輯器中的樣子。
**表4-2 自動回復短信所需要的塊
塊的類型 | 所在抽屜 | 功能 |
---|---|---|
Texting1.MessageReceived | Texting | 手機收到短信時會啟動該事件的處理程序 |
set Texting1.PhoneNumber to | Texting | 在發(fā)送短信前設置接收者電話號碼 |
get number | Variables | 獲取短信發(fā)送者的電話號碼 |
set Texting.Message to | Texting | 設置要發(fā)送的短信內(nèi)容 |
ResponseLabel.Text | ResponseLabel | 用戶預輸入的短信內(nèi)容 |
call Texting1.SendMessage | Texting | 發(fā)送短信 |
圖 4-3 對收到的短信進行自動回復
手機收到短信將觸發(fā)Texting1.MessageReceived事件。如圖4-3所示,發(fā)送者的手機號保存在參數(shù)number中,短信內(nèi)容保存在參數(shù)messageText中。自動回復就是要向發(fā)送者發(fā)送一條短信,為此要先設置Texting組件的兩個關(guān)鍵屬性:PhoneNumber及Message。PhoneNumber設置為發(fā)送者的手機號,Message設置為ResponseLabel中顯示的內(nèi)容:“我正在開車,稍后與您聯(lián)系?!痹O置完成之后,調(diào)用Texting. SendMessage實現(xiàn)自動回復。
注釋是編程工作的重要組成部分,它可以告訴其他程序員那些與代碼有關(guān)的重要信息。在塊上單擊右鍵,在快捷菜單中選擇“Add Comment”(添加注釋),此時塊的左上方會出現(xiàn)藍色問號,點擊藍色問號,會彈出文本輸入框,可供輸入注釋信息;點擊藍色問號還可以隱藏注釋信息。注釋在應用中不是必須的,這里添加注釋是為了介紹每個塊的功能。
很多人用注釋來記錄創(chuàng)建應用的過程;注釋可以解釋程序的功能,但不會改變程序的行為。無論是你自己今后要修改程序,還是其他人要對程序做個性化設置,注釋都是非常重要的?!皼]有不變的軟件”已經(jīng)成為共識,因此,代碼的注釋是軟件工程中非常重要的環(huán)節(jié),尤其像App Inventor這樣的開源軟件。
測試: 需要用第二部手機來測試程序。如果沒有,可以注冊申請Google Voice或其他類似的服務,并從注冊的服務中給你的手機發(fā)送短信。用第二部手機給正在運行本應用的手機發(fā)短信,第二部手機是否收到了回信?
下面來添加更多的程序塊,允許用戶輸入自定義的回復內(nèi)容。在組件設計器中,已經(jīng)添加了名為NewResponseTextbox的TextBox組件,用于輸入自定義回復信息,當用戶點擊SubmitResponseButton時,NewResponseTextbox中的內(nèi)容被復制到ResponseLabel中,這就是自動回復短信的內(nèi)容。表4-3列出了在ResponseLabel中顯示新的回復內(nèi)容所需的塊。
表4-3 顯示自定義回復所需的塊
塊的類型 | 所在抽屜 | 功能 |
---|---|---|
SubmitResponseButton.Click | SubmitResponseButton | 點擊按鈕提交新的回復信息 |
set ResponseLabel.Text to | ResponseLabel | 為該Label設置新的文本內(nèi)容 |
NewResponseTextbox.Text | NewResponseTextbox | 用戶在這里輸入新的回復內(nèi)容 |
一個典型的輸入表單 的作用是:首先在文本框中輸入文字,然后單擊提交按鈕來通知系統(tǒng)做處理。圖4-4顯示了用戶點擊“修改回復內(nèi)容”按鈕時, SubmitResponseButton.Click事件被觸發(fā)。
圖 4-4 將用戶輸入的信息設置為自動回復內(nèi)容
事件處理程序?qū)⒂脩粼贜ewResponseTextbox中輸入的文字復制到ResponseLabel中,而ResponseLabel保存的是自動回復信息,因此要確保新輸入的信息顯示在ResponseLabel中。
測試:輸入一段自定義信息并提交,然后用第二部手機發(fā)送短信到測試手機上,看看這次自動回復的是新定制的內(nèi)容嗎?
你創(chuàng)建了一個偉大的應用,卻留下了一個陷阱:用戶輸入了定制回復,然后關(guān)閉應用,當再次啟動應用時,定制回復卻不見了(取而代之的是默認回復)。這種狀況可不是用戶所期望的,他們希望在重啟應用時,定制的內(nèi)容還在,為此需要信息的永久保存。
你可能認為數(shù)據(jù)放在ResponseLabel組件的Text屬性中,也應該算作“儲存”,但實際上組件屬性中的數(shù)據(jù)是臨時數(shù)據(jù),就像人的短時記憶,只要應用關(guān)閉,數(shù)據(jù)就會被“忘記”。如果希望應用能永久記住某些數(shù)據(jù),就需要將數(shù)據(jù)從短時記憶(組件的屬性或變量)轉(zhuǎn)移到永久記憶中(數(shù)據(jù)庫)。
要永久地保存數(shù)據(jù),需要使用TinyDB組件,它可以將數(shù)據(jù)存儲在Android設備內(nèi)置的數(shù)據(jù)庫中。TinyDB提供兩個功能: StoreValue(保存值)和getValue(獲取值)。前者允許應用將信息存儲在設備數(shù)據(jù)庫中,而后者則允許應用重新讀取已存儲的信息。
對于多數(shù)應用,可以采取如下策略:
1. 每當用戶提交新值,將其存儲到數(shù)據(jù)庫;
2. 應用啟動時,從數(shù)據(jù)庫中加載數(shù)據(jù)并將其賦給一個變量或?qū)傩浴?/p>
為了實現(xiàn)數(shù)據(jù)的永久保存,必須修改SubmitResponseButton.Click事件處理程序,表4-4中列出了所需要的程序塊。
表4-4 用TinyDB數(shù)據(jù)庫存儲定制回復所需要的塊
塊的類型 | 所在抽屜 | 功能 |
---|---|---|
TinyDB1.StoreValue | TinyDB1 | 將用戶的定制信息保存在手機內(nèi)置的數(shù)據(jù)庫中 |
”responseMessage” | Text | 以此作為保存數(shù)據(jù)的標簽 |
ResponseLabel.Text | ResponseLabel | 已設定的回復信息顯示在這里 |
TinyDB從ResponseLabel的Text屬性中提取內(nèi)容,并將其保存在數(shù)據(jù)庫中。如圖4-5所示,向數(shù)據(jù)庫中保存數(shù)據(jù)時,要為數(shù)據(jù)設置一個tag(標簽),本例中的tag是“responseMessage”??梢园裻ag想象成數(shù)據(jù)在數(shù)據(jù)庫中的存放地址,是數(shù)據(jù)的唯一標識。在下節(jié)中你將看到,必須使用相同的tag(“responseMessage”)才能將數(shù)據(jù)從數(shù)據(jù)庫中讀取出來。
圖 4-5 永久保存自定義回復信息
將定制回復信息保存在數(shù)據(jù)庫中,以便用戶再次啟動應用時,保存的數(shù)據(jù)可以被重新讀取出來。App Inventor提供了一個特殊的事件塊:Screen1.Initialize,當應用啟動時,將觸發(fā)該事件(我們在第3章MoleMash中使用過)。將Screen.Initialize塊拖出來,并將某些程序塊放在其中,那么這些程序塊會在應用啟動時逐一執(zhí)行。
在本應用中,Screen1.Initialize事件的處理程序會檢查數(shù)據(jù)庫中是否存放了自定義回復內(nèi)容。如果是,則使用TinyDB.GetValue函數(shù)加載存儲的內(nèi)容。實現(xiàn)這一功能所需的塊見表4-5。
表4-5 應用啟動時用于加載數(shù)據(jù)的塊
組件類型 | 所在抽屜 | 作用 |
---|---|---|
Initialize global response to | Variables | 用于存放數(shù)據(jù)庫中讀出的定制回復信息 |
“” | Text | 變量的初始值可以是任意值 |
Screen1.Initialize | Screen1 | 應用啟動時會觸發(fā)該事件 |
set global response to | Variables | 用從數(shù)據(jù)庫中讀出的值為該變量賦值 |
TinyDB1.GetValue | TinyDB1 | 從數(shù)據(jù)庫中讀取已存儲的定制回復信息 |
"responseMessage" | Text | 插入TinyDB.GetValue的tag插槽,與之前TinyDB.StoreValue使用相同文本 |
If | Control | 判斷讀出的數(shù)據(jù)中是否包含文字 |
> | Math | 檢查讀出的數(shù)據(jù)長度是否大于0 |
Length(text) | Text | 檢查文本類型數(shù)據(jù)的長度 |
get global response | Variables | 從變量中讀出的數(shù)據(jù)(定制回復信息) |
數(shù)字0 | Math | 用于比較長度 |
uuset ResponseLabel.Text to | ResponseLabel | 如果讀出的數(shù)據(jù)有內(nèi)容,放在label中 |
get global response | Variables | 從變量中讀出的數(shù)據(jù)(定制回復信息) |
如圖4-6所示,要想理解這些塊的功能,必須設想用戶的使用過程:首次打開應用,輸入自定義回復,隨時退出并再次打開應用。用戶首次啟動應用時,數(shù)據(jù)庫中沒有定制回復可供加載,因此ResponseLabel中顯示的是默認回復。再次啟動時,才有可能從數(shù)據(jù)庫中加載定制回復,并將其顯示在ResponseLabel中。
圖 4-6 應用啟動時從數(shù)據(jù)庫中加載定制回復
應用啟動時觸發(fā)Screen1.Initialize事件,并用tag “responseMessage”來調(diào)用TinyDB1.GetValue,該tag與之前用戶存儲定制回復時采用的tag相同。讀出的值放在變量response中,并對其進行檢驗,然后才能在ResponseLabel中顯示。想想看,為什么從數(shù)據(jù)庫中讀出的數(shù)據(jù),在向用戶顯示之前,要經(jīng)過檢驗呢?如果數(shù)據(jù)庫中不存在與指定tag相對應的數(shù)據(jù),TinyDB將返回空文本;而第一次啟動應用時,數(shù)據(jù)是不存在的,直到用戶輸入了自定義回復,數(shù)據(jù)才會有。由于變量response中保存了數(shù)據(jù)庫返回值,因此可以用if塊來檢查其長度是否大于0。如果大于0 ,說明的確從TinyDB讀出了定制回復信息,就會將信息顯示在ResponseLabel中;如果長度不大于0,說明之前沒有保存過定制回復信息,因此將不修改ResponseLabel的顯示內(nèi)容(保留默認自動回復內(nèi)容)。
測試:上述功能無法進行實時測試,因為每次連接“AI伴侶”啟動應用時,數(shù)據(jù)庫都會被清空。因此需要選擇“build->App(provide QR code)”,然后掃描條碼,將應用下載安裝到手機上。安裝之后,在NewResponseTextbox中輸入新的回復信息并單擊SubmitResponseButton按鈕;關(guān)閉應用并重新啟動它,這次定制回復信息出現(xiàn)了嗎?
本節(jié)將修改應用:收到短信后,手機將大聲朗讀發(fā)送者的電話號碼以及短信內(nèi)容。開車收到短信,雖然有自動回復功能,但你還是禁不住想知道短信的內(nèi)容。使用text-to-speech功能,就可以手不離方向盤而收聽到短信的內(nèi)容。
Android設備提供了text-to-speech功能,而App Inventor提供了一個TextToSpeech組件,它可以讀出任何text(文本信息 )(注意,此處“text”指的是一般意義上的字/word:一串字母、數(shù)字以及標點符號組成的文本,而不是短信文本 。)
在本章的“準備開始”部分,我們要求你從Android Market下載一個text-to-speech的模塊。如果你還沒做,現(xiàn)在該去做了。根據(jù)需要安裝并配置完模塊之后,就可以在App Inventor中使用TextToSpeech組件了。
TextToSpeech組件的使用非常簡單,只需調(diào)用它的Speak函數(shù)并插入要朗讀的文字即可。例如,圖4-7中的函數(shù)會說“Hello World”。
圖 4-7 會說“HelloWorld”的塊
在本應用中,朗讀的內(nèi)容則更為復雜,既要包含短信發(fā)送者的電話號碼,也要包含短信內(nèi)容,而不只是像“Hello World”那樣的靜態(tài)文本。這里要用到極為重要的join塊,它可以將若干文本片段(或數(shù)字以及其他字符)連接成單一的文本對象。
在之前的Texting.MessageReceived事件處理程序中,加入對TextToSpeech.Speak的調(diào)用。在之前的事件處理程序中,通過適當設置Texting組件的PhoneNumber和Message屬性,然后發(fā)送回復信息?,F(xiàn)在需要加入表4-6中所列出的塊來擴展該事件的處理程序。
表4-6 朗讀收到的短信所需的塊
塊的類型 | 所在抽屜 | 功能 |
---|---|---|
TextToSpeech1.Speak | TextToSpeech1 | 大聲讀出收到的短信 |
join | Text | 連接生成將被朗讀的文字 |
"SMS text received from" | Text | 被讀出的第一段話 |
get number | Variables | 獲得短信發(fā)送者的電話號碼 |
". The message is" | Text | 在讀完電話號碼之后稍加停頓,然后說"The message is" |
get messageText | Variables | 獲得收到的短信文本 |
在自動回復動作完成之后,將調(diào)用TextToSpeech1.Speak函數(shù),如圖4-8的下半部分所示。你可以在TextToSpeech1.Speak函數(shù)的消息槽中插入任何文本對象。在這種情況下,join塊用來生成被讀出的內(nèi)容。它將幾段文字串連在一起,最后生成類似這樣的信息:“SMS text received from 111-222-3333. The message is:hello.”
圖 4-8 大聲讀出收到的短信
測試:你需要第二部手機來測試應用。用第二部手機發(fā)送文字【必須是英文】到你的測試手機上。你的手機大聲讀出信息了嗎?它是否照常發(fā)送自動回復?
像Facebook的Places以及Google的Latitude等類型的應用,都是利用GPS信息來幫助人們跟蹤彼此的位置信息。這樣的應用最令人擔憂的是隱私問題,原因之一是它引發(fā)了人們對“老大哥”的恐懼,這里的“老大哥”指的是那些設法跟蹤其公民下落的集權(quán)政府。但是使用位置信息的應用的確非常有用,試想一個迷路的小孩,或者那些在森林里迷路的徒步旅行者。
在“開車不發(fā)短信”的應用中,位置跟蹤讓回復的短信再多一點內(nèi)容,而不只是“我正在開車”,回復的信息可以是這樣的:“我正在北京東直門內(nèi)大街209號開車”。對于那些正在等待朋友或家人到來的人來說,這些額外的信息非常有益。
App Inventor提供了LocationSensor(位置傳感器)組件,作為手機的GPS (Global Positioning System全球定位系統(tǒng))功能的接口。除了緯度和經(jīng)度信息,LocationSensor也可以接入到谷歌地圖,為司機提供當前位置的地址信息。
值得注意的是,LocationSensor并不總在讀取信息,因此務必要恰當?shù)厥褂眠@一組件。具體地講,應用只對LocationSensor.LocationChanged事件做出響應,而兩種情況會觸發(fā)LocationChanged事件:①當手機的位置傳感器第一次收到位置信息時;②隨著手機的移動,產(chǎn)生新的位置信息時。使用表4-7中列出的塊,具體方法是:當LocationChanged事件觸發(fā)時,將當前地址信息保存到變量lastKnownLocation中,再將變量值插入到自動回復信息中。
表4-7設置位置傳感器的塊
塊的類型 | 所在抽屜 | 功能 |
---|---|---|
Initialize global lastKnownLocation to | Variables | 創(chuàng)建一個變量來保存最后讀取的地址信息 |
"未知" | Text | lastKnownLocation的默認值 |
LocationSensor1.LocationChanged | LocationSensor1 | 位置傳感器第一次讀到位置信息,或每次位置信息變化時觸發(fā)該事件 |
set global lastKnownLocation to | Variables | 設置變量值,稍后會用到 |
LocationSensor1.CurrentAddress | LocationSensor1 | 當前地址信息,如:"北京市東城區(qū)東直門內(nèi)大街209號" |
當位置傳感器首次讀取位置信息時,LocationSensor1.LocationChanged事件被觸發(fā),隨著設備的移動,還會生成新的位置信息,事件將被再次觸發(fā)。由于自動回復信息中要包括地址信息,因此,通過調(diào)用LocationSensor1.CurrentAddress函數(shù) 來獲取地址信息,并將其保存在lastKnownLocation變量中,如圖4-9所示。在后臺,這個函數(shù)會調(diào)用谷歌地圖(通過API 來調(diào)用,將在第24章學到),并根據(jù)傳感器獲得的經(jīng)緯度信息來確定最近的街區(qū)地址。
圖 4-9 每當傳感器收到GPS位置信息時,用變量記錄手機的位置
注意,這些塊只完成了一半的工作,還要將位置信息插入自動回復信息中,再回復給發(fā)件人。
用變量lastKnownLocation中的值對Texting1.MessageReceived事件處理程序加以修改,向自動回復信息中添加位置信息。表4-8列出了所需要的塊。
表4-8在自動回復中顯示位置信息的塊
塊的類型 | 所在抽屜 | 功能 |
---|---|---|
join | Text | 多段文本的連接器 |
ResponseLabel.Text | ResponseLabel | 不包含位置信息的定制回復信息 |
“我最后的位置在:” | Text | 原定制信息之后的位置信息提示詞 |
global lastKnownLocation | Variables | 地址信息,如:“北京市東城區(qū)東直門內(nèi)大街209號” |
向回復中添加位置信息需要LocationSensor1.LocationChanged事件與變量lastKnownLocation的協(xié)作。如圖4-10所示,并非直接發(fā)送ResponseLabel.Text中的信息,而是使用join塊將若干段信息整合起來:原有的自動回復信息+“ 我的最后位置在:”+變量lastKnownLocation。
圖 4-10 在回復信息中加入位置信息
變量lastKnownLocation的默認值是“未知”,所以如果位置傳感器尚未產(chǎn)生位置信息,則自動回復的第二部分內(nèi)容為“我的最后位置在:未知”。如果已經(jīng)產(chǎn)生了位置信息,則自動回復的第二部分內(nèi)容有可能是這樣:“我的最后位置在:北京市東城區(qū)東直門內(nèi)大街209號”
測試:用第二部手機發(fā)送短信到運行應用的手機上,第二個手機是否接收到了帶有位置信息的自動回復?如果沒有,請確保你已經(jīng)開啟了第一部手機的GPS定位功能。
圖4-11中顯示了“開車不發(fā)短信”最終的塊的配置
圖 4-11 完整的“開車不發(fā)短信”應用(同時顯示所有注釋)
當應用已經(jīng)付諸使用,你也許會想到做一些改進,例如:
編寫另一個版本,允許用戶針對某些特定來信號碼定制回復內(nèi)容。你需要增加一個條件(if)塊,來檢查這些來信的手機號。有關(guān)條件塊(if)的更多信息,請參見第18章;
再編寫一個版本,根據(jù)用戶是否在某個緯度/經(jīng)度范圍內(nèi),來回復定制信息。這樣,如果應用判斷你在房間222,它會回復“鮑勃在222房間,現(xiàn)在不能回復短信?!庇嘘P(guān)LocationSensor以及確定邊界的更多信息,請參見第23章;
下面是本章涉及到的一些概念:
Texting組件:既可以用來發(fā)短信,也可以處理收到的信息。在調(diào)用Texting.SendMessage之前,需要為Texting組件設置PhoneNumber及Message屬性。為了回復收到的短信,需要為Texting.MessageReceived事件編寫處理程序;
TinyDB組件:用于將信息永久存儲在手機數(shù)據(jù)庫中,以便每次應用啟動時都可以加載保存過的數(shù)據(jù)。有關(guān)TinyDB的更多信息,請參見第22章;
TextToSpeech組件:對于所提供的任何文本對象,都可以大聲朗讀出來(限英文);
join塊:用于將若干片段的文字拼湊(或連接)成單一的文本對象中;
Text-To-Speech
縮寫為TTS,直譯為“從文本到語音”,是語音合成技術(shù)的一種應用,可以將文字信息實時轉(zhuǎn)換為語音。在本章中使用了Android設備的此項功能,但遺憾的是,目前Google的TTS引擎尚不支持中文的轉(zhuǎn)換,因此學員測試時還需使用英文。
text: 文本[名詞]
text: 發(fā)短信[動詞]
initialize: 初始化
speech: 講話
location: 位置
sensor: 傳感器
tiny: 微小的
DB: database數(shù)據(jù)庫
social: 社交的
storage: 存儲
prompt: 提示
response: 響應
receive: 接收
submit: 提交
hint: 提示
variable: 變量
phone: 電話
number: 數(shù)字,號碼
call: 調(diào)用,呼叫
message: 消息
send: 發(fā)送
add: 增加
comment: 注釋,評論
voice: 聲音
store: 存放
value: 值
tag: 標簽
global: 全球的,全局的
control: 控制
math: 數(shù)學
length: 長度
provide: 提供
code: 編碼
GPS: 全球定位系統(tǒng)(Global Positioning System)
change: 改變
last: 最后的
current: 當前的,現(xiàn)在的
更多建議: