第 4 章 開車不發(fā)短信

2018-02-24 15:51 更新

本章將創(chuàng)建一款“開車不發(fā)短信”的應(yīng)用,讓你在開車時能夠自動回復(fù)收到的短信。一名計算機(jī)入門課上的新生首創(chuàng)了這款應(yīng)用,與美國國家農(nóng)場保險公司開發(fā)的一款裝機(jī)量巨大的應(yīng)用相類似。App Inventor可以利用Android手機(jī)中的某些強(qiáng)大功能,包括SMS短信處理、數(shù)據(jù)庫管理、文本轉(zhuǎn)成語音以及位置傳感器等,本應(yīng)用就是一個典型的例子。

美國國家安全委員會(NSC)于2010年1月發(fā)布的研究結(jié)果表明,每年有至少28%的交通事故——將近160萬次車禍源于司機(jī)在開車時使用手機(jī),其中至少20萬次交通事故與發(fā)短信有關(guān)(http://www.nsc.org/pages/nscestimates16millioncrashescausedbydriversusingcellphonesandtexting.aspx)。因此,許多國家已經(jīng)全面禁止司機(jī)開車時使用手機(jī)。

Daniel Finnegan,一個舊金山大學(xué)的學(xué)生,在2010年秋季學(xué)期的App Inventor編程課上,提出了一個了不起的想法,用一個應(yīng)用來解決開車發(fā)短信泛濫的問題。如圖4-1所示,他創(chuàng)建的應(yīng)用可以對收到的任何短信進(jìn)行自動回復(fù),如回復(fù)“我正在開車,稍后與您聯(lián)系”之類的內(nèi)容。

{%}

{%}

圖 4-1 “開車不發(fā)短信”

課堂上的頭腦風(fēng)暴增加了應(yīng)用的功能,也豐富了本教程,這些內(nèi)容發(fā)布在App Inventor網(wǎng)站上:

  • 用戶可以根據(jù)情況改變回復(fù)內(nèi)容:例如,如果你正在開會或看電影,而不是開車,回復(fù)內(nèi)容可以做相應(yīng)的修改;

  • 應(yīng)用可以大聲朗讀來信內(nèi)容:盡管有自動回復(fù),但對來信的好奇心也會置你于死地;

  • 回復(fù)內(nèi)容可以包含您當(dāng)前的位置信息:如果你的另一半正在家做晚飯,他或她可能想知道你何時能到家,但又擔(dān)心回短信會危及安全。

就在本應(yīng)用發(fā)布到App Inventor網(wǎng)站后的幾周,State Farm Insurance創(chuàng)建了名為“On the Move”的Android應(yīng)用,http://www.statefarm.com/aboutus/newsroom/20100819.asp【譯者沒找到On the Move,不過該公司的確有幾個好的應(yīng)用值得嘗試】,其功能與“開車不發(fā)短信”類似。該公司將這項服務(wù)作為“掌上代理”應(yīng)用的升級內(nèi)容,免費(fèi)向所有人開放,并在YouTube網(wǎng)站發(fā)布視頻:http://www.youtube.com/watch?v=3xtjzO0-Hfw【譯者訪問該網(wǎng)址,提示“此視頻未公開”】。

我們無法確認(rèn)Daniel的應(yīng)用或App Inventor網(wǎng)站的教程是否對“On the Move”產(chǎn)生了影響,但有趣的是,這讓我們思考一種可能性:在一門編程基礎(chǔ)課上創(chuàng)建的應(yīng)用(竟然由一個創(chuàng)意寫作的學(xué)生創(chuàng)建?。┮苍S會促成軟件的批量生產(chǎn),或至少是對軟件生產(chǎn)的生態(tài)系統(tǒng)有所貢獻(xiàn)。當(dāng)然,這也說明了App Inventor降低了軟件開發(fā)的門檻,以至于無論是誰,只要有一個好主意,都可以快速、低成本地把想法變成一個實實在在的、可交互的應(yīng)用。

學(xué)習(xí)內(nèi)容

相比前幾章來說,這是一個更加復(fù)雜的應(yīng)用,因此我們每次只完成一項功能,從自動回復(fù)開始。以下是將要學(xué)習(xí)的內(nèi)容:

  • Texting組件:具有收發(fā)短信功能;

  • TextBox組件:用于提交自定義回復(fù)信息(需要與Button組件配合使用);

  • TinyDB數(shù)據(jù)庫組件:用于保存自定義信息,即使應(yīng)用已經(jīng)關(guān)閉,信息也不會丟失;

  • Screen.Initialize事件:在應(yīng)用啟動時加載自定義回復(fù)內(nèi)容;

  • Text-to-Speech組件:用于大聲朗讀文字;

  • LocationSensor組件:報告司機(jī)的當(dāng)前位置。

準(zhǔn)備開始

本應(yīng)用的運(yùn)行,需要手機(jī)上Text-To-Speech(TTS)模塊的支持。該模塊包含在Android 2或更高的版本中,如果你的操作系統(tǒng)是Android 1.x,需要從Google Play下載。在手機(jī)上:

1. 打開Google Play應(yīng)用;

2. 搜索TTS;

3. 選擇應(yīng)用Text-To-Speech Extended并安裝。

TTS模塊安裝后,可以測試其功能。對于Android2以上版本,在"設(shè)置->輔助功能"中打開“文字轉(zhuǎn)換語音輸出”功能,根據(jù)需要設(shè)置默認(rèn)語言及語速,然后選擇“收聽示例”。如果沒聽到任何聲音,請確認(rèn)手機(jī)音量已調(diào)高;還可以更改TTS引擎默認(rèn)屬性設(shè)置,來改變聲音效果。

TTS模塊設(shè)置完成后,登陸App Inventor網(wǎng)站開始新項目“NoTextingWhileDriving”(項目名中不能有空格),然后設(shè)置屏幕的標(biāo)題為“開車不發(fā)短信”,最后通過WiFi與測試手機(jī)(AI伴侶)連接。

設(shè)計組件

應(yīng)用的用戶界面很簡單:一個顯示自動回復(fù)內(nèi)容的Label,一個編輯自動回復(fù)信息的文本輸入框和一個提交輸入結(jié)果的按鈕。還需要拖入一個Texting組件、一個TinyDB組件、一個TextToSpeech組件以及一個LocationSensor組件,這些組件都將出現(xiàn)在“不可視組件”區(qū)。你可以在圖4-2中看到上述組件在設(shè)計器中的截圖。

{%}

圖 4-2 組件設(shè)計器中的“開車不發(fā)短信”應(yīng)用

將表4-1中列出的組件拖到預(yù)覽窗口中,創(chuàng)建出圖4-2中所示的用戶界面。

表4-1 “開車不發(fā)短信”應(yīng)用中的全部組件

組件類型 面板中分組 命名 作用
Label User Interface PromptLabel 讓用戶了解應(yīng)用的功能
Label User Interface ResponseLabel 顯示即將發(fā)送的自動回復(fù)信息
TextBox User Interface NewResponseTextbox 用戶在此處輸入定制的回復(fù)信息
Button User Interface SubmitResponseButton 用戶點(diǎn)擊來提交、保存回復(fù)信息
Texting Social Texting1 處理短信事務(wù)
TinyDB Storage TinyDB1 將自動回復(fù)信息保存在數(shù)據(jù)庫中
TextToSpeech Media TextToSpeech1 大聲朗讀來信
LocationSensor Sensors LocationSensor1 感知電話所在位置

按照以下方式設(shè)置組件屬性:

  • 設(shè)置PromptLabel的Text屬性為“當(dāng)本應(yīng)用正在運(yùn)行時,將用下面的文字來回復(fù)所有收到的短信?!?/p>

  • 設(shè)置ResponseLabel的Text屬性為“我正在開車,稍后與您聯(lián)系?!辈⒐催xFontBold(粗體字)屬性;

  • 設(shè)置NewResponseTextbox的Text屬性為“”(讓文本框為空,等待用戶輸入);

  • 設(shè)置NewResponseTextbox的Hint(提示)屬性為“輸入新的回復(fù)內(nèi)容”,Width設(shè)為“Fill Parent”;

  • 設(shè)置SubmitResponseButton的Text屬性為“修改回復(fù)內(nèi)容?!?/li>

為組件添加行為

從基本的自動回復(fù)行開始,再逐步添加更多功能。

編程實現(xiàn)自動回復(fù)

自動回復(fù)功能需要用到App Inventor的Texting組件,可以把它想象成一個藏在手機(jī)里的小矮人,它知曉如何收發(fā)短信。該組件用Texting.MessageReceived事件塊來響應(yīng)“收到短信”,拖出該事件塊,并在塊內(nèi)放入一些命令塊,看看當(dāng)你收到短信時,會發(fā)生什么事情。這里我們希望能夠自動回復(fù)預(yù)先編輯好的內(nèi)容。

發(fā)送短信的操作需要調(diào)用Texting1.SendMessage塊,將其放在Texting1.MessageReceived塊內(nèi)。Texting1.SendMessage塊只能發(fā)送短信,至于要發(fā)什么內(nèi)容,以及發(fā)給誰,需要在調(diào)用之前,由你來告訴它:表4-2列出了自動回復(fù)行為所需要的塊,而圖4-3顯示了它們在塊編輯器中的樣子。

**表4-2 自動回復(fù)短信所需要的塊

塊的類型 所在抽屜 功能
Texting1.MessageReceived Texting 手機(jī)收到短信時會啟動該事件的處理程序
set Texting1.PhoneNumber to Texting 在發(fā)送短信前設(shè)置接收者電話號碼
get number Variables 獲取短信發(fā)送者的電話號碼
set Texting.Message to Texting 設(shè)置要發(fā)送的短信內(nèi)容
ResponseLabel.Text ResponseLabel 用戶預(yù)輸入的短信內(nèi)容
call Texting1.SendMessage Texting 發(fā)送短信

{%}

圖 4-3 對收到的短信進(jìn)行自動回復(fù)

塊是作用

手機(jī)收到短信將觸發(fā)Texting1.MessageReceived事件。如圖4-3所示,發(fā)送者的手機(jī)號保存在參數(shù)number中,短信內(nèi)容保存在參數(shù)messageText中。自動回復(fù)就是要向發(fā)送者發(fā)送一條短信,為此要先設(shè)置Texting組件的兩個關(guān)鍵屬性:PhoneNumber及Message。PhoneNumber設(shè)置為發(fā)送者的手機(jī)號,Message設(shè)置為ResponseLabel中顯示的內(nèi)容:“我正在開車,稍后與您聯(lián)系。”設(shè)置完成之后,調(diào)用Texting. SendMessage實現(xiàn)自動回復(fù)。

注釋是編程工作的重要組成部分,它可以告訴其他程序員那些與代碼有關(guān)的重要信息。在塊上單擊右鍵,在快捷菜單中選擇“Add Comment”(添加注釋),此時塊的左上方會出現(xiàn)藍(lán)色問號,點(diǎn)擊藍(lán)色問號,會彈出文本輸入框,可供輸入注釋信息;點(diǎn)擊藍(lán)色問號還可以隱藏注釋信息。注釋在應(yīng)用中不是必須的,這里添加注釋是為了介紹每個塊的功能。

很多人用注釋來記錄創(chuàng)建應(yīng)用的過程;注釋可以解釋程序的功能,但不會改變程序的行為。無論是你自己今后要修改程序,還是其他人要對程序做個性化設(shè)置,注釋都是非常重要的?!皼]有不變的軟件”已經(jīng)成為共識,因此,代碼的注釋是軟件工程中非常重要的環(huán)節(jié),尤其像App Inventor這樣的開源軟件。

 測試: 需要用第二部手機(jī)來測試程序。如果沒有,可以注冊申請Google Voice或其他類似的服務(wù),并從注冊的服務(wù)中給你的手機(jī)發(fā)送短信。用第二部手機(jī)給正在運(yùn)行本應(yīng)用的手機(jī)發(fā)短信,第二部手機(jī)是否收到了回信?

輸入一個定制的回復(fù)

下面來添加更多的程序塊,允許用戶輸入自定義的回復(fù)內(nèi)容。在組件設(shè)計器中,已經(jīng)添加了名為NewResponseTextbox的TextBox組件,用于輸入自定義回復(fù)信息,當(dāng)用戶點(diǎn)擊SubmitResponseButton時,NewResponseTextbox中的內(nèi)容被復(fù)制到ResponseLabel中,這就是自動回復(fù)短信的內(nèi)容。表4-3列出了在ResponseLabel中顯示新的回復(fù)內(nèi)容所需的塊。

表4-3 顯示自定義回復(fù)所需的塊

塊的類型 所在抽屜 功能
SubmitResponseButton.Click SubmitResponseButton 點(diǎn)擊按鈕提交新的回復(fù)信息
set ResponseLabel.Text to ResponseLabel 為該Label設(shè)置新的文本內(nèi)容
NewResponseTextbox.Text NewResponseTextbox 用戶在這里輸入新的回復(fù)內(nèi)容

塊的作用

一個典型的輸入表單 的作用是:首先在文本框中輸入文字,然后單擊提交按鈕來通知系統(tǒng)做處理。圖4-4顯示了用戶點(diǎn)擊“修改回復(fù)內(nèi)容”按鈕時, SubmitResponseButton.Click事件被觸發(fā)。

{%}

圖 4-4 將用戶輸入的信息設(shè)置為自動回復(fù)內(nèi)容

事件處理程序?qū)⒂脩粼贜ewResponseTextbox中輸入的文字復(fù)制到ResponseLabel中,而ResponseLabel保存的是自動回復(fù)信息,因此要確保新輸入的信息顯示在ResponseLabel中。

 測試:輸入一段自定義信息并提交,然后用第二部手機(jī)發(fā)送短信到測試手機(jī)上,看看這次自動回復(fù)的是新定制的內(nèi)容嗎?

將定制回復(fù)保存到數(shù)據(jù)庫中

你創(chuàng)建了一個偉大的應(yīng)用,卻留下了一個陷阱:用戶輸入了定制回復(fù),然后關(guān)閉應(yīng)用,當(dāng)再次啟動應(yīng)用時,定制回復(fù)卻不見了(取而代之的是默認(rèn)回復(fù))。這種狀況可不是用戶所期望的,他們希望在重啟應(yīng)用時,定制的內(nèi)容還在,為此需要信息的永久保存。

你可能認(rèn)為數(shù)據(jù)放在ResponseLabel組件的Text屬性中,也應(yīng)該算作“儲存”,但實際上組件屬性中的數(shù)據(jù)是臨時數(shù)據(jù),就像人的短時記憶,只要應(yīng)用關(guān)閉,數(shù)據(jù)就會被“忘記”。如果希望應(yīng)用能永久記住某些數(shù)據(jù),就需要將數(shù)據(jù)從短時記憶(組件的屬性或變量)轉(zhuǎn)移到永久記憶中(數(shù)據(jù)庫)。

要永久地保存數(shù)據(jù),需要使用TinyDB組件,它可以將數(shù)據(jù)存儲在Android設(shè)備內(nèi)置的數(shù)據(jù)庫中。TinyDB提供兩個功能: StoreValue(保存值)和getValue(獲取值)。前者允許應(yīng)用將信息存儲在設(shè)備數(shù)據(jù)庫中,而后者則允許應(yīng)用重新讀取已存儲的信息。

對于多數(shù)應(yīng)用,可以采取如下策略:

1. 每當(dāng)用戶提交新值,將其存儲到數(shù)據(jù)庫;

2. 應(yīng)用啟動時,從數(shù)據(jù)庫中加載數(shù)據(jù)并將其賦給一個變量或?qū)傩浴?/p>

為了實現(xiàn)數(shù)據(jù)的永久保存,必須修改SubmitResponseButton.Click事件處理程序,表4-4中列出了所需要的程序塊。

表4-4 用TinyDB數(shù)據(jù)庫存儲定制回復(fù)所需要的塊

塊的類型 所在抽屜 功能
TinyDB1.StoreValue TinyDB1 將用戶的定制信息保存在手機(jī)內(nèi)置的數(shù)據(jù)庫中
”responseMessage” Text 以此作為保存數(shù)據(jù)的標(biāo)簽
ResponseLabel.Text ResponseLabel 已設(shè)定的回復(fù)信息顯示在這里

塊的作用

TinyDB從ResponseLabel的Text屬性中提取內(nèi)容,并將其保存在數(shù)據(jù)庫中。如圖4-5所示,向數(shù)據(jù)庫中保存數(shù)據(jù)時,要為數(shù)據(jù)設(shè)置一個tag(標(biāo)簽),本例中的tag是“responseMessage”??梢园裻ag想象成數(shù)據(jù)在數(shù)據(jù)庫中的存放地址,是數(shù)據(jù)的唯一標(biāo)識。在下節(jié)中你將看到,必須使用相同的tag(“responseMessage”)才能將數(shù)據(jù)從數(shù)據(jù)庫中讀取出來。

{%}

圖 4-5 永久保存自定義回復(fù)信息

應(yīng)用啟動時讀取定制信息

將定制回復(fù)信息保存在數(shù)據(jù)庫中,以便用戶再次啟動應(yīng)用時,保存的數(shù)據(jù)可以被重新讀取出來。App Inventor提供了一個特殊的事件塊:Screen1.Initialize,當(dāng)應(yīng)用啟動時,將觸發(fā)該事件(我們在第3章MoleMash中使用過)。將Screen.Initialize塊拖出來,并將某些程序塊放在其中,那么這些程序塊會在應(yīng)用啟動時逐一執(zhí)行。

在本應(yīng)用中,Screen1.Initialize事件的處理程序會檢查數(shù)據(jù)庫中是否存放了自定義回復(fù)內(nèi)容。如果是,則使用TinyDB.GetValue函數(shù)加載存儲的內(nèi)容。實現(xiàn)這一功能所需的塊見表4-5。

表4-5 應(yīng)用啟動時用于加載數(shù)據(jù)的塊

組件類型 所在抽屜 作用
Initialize global response to Variables 用于存放數(shù)據(jù)庫中讀出的定制回復(fù)信息
“” Text 變量的初始值可以是任意值
Screen1.Initialize Screen1 應(yīng)用啟動時會觸發(fā)該事件
set global response to Variables 用從數(shù)據(jù)庫中讀出的值為該變量賦值
TinyDB1.GetValue TinyDB1 從數(shù)據(jù)庫中讀取已存儲的定制回復(fù)信息
"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ù)(定制回復(fù)信息)
數(shù)字0 Math 用于比較長度
uuset ResponseLabel.Text to ResponseLabel 如果讀出的數(shù)據(jù)有內(nèi)容,放在label中
get global response Variables 從變量中讀出的數(shù)據(jù)(定制回復(fù)信息)

塊的功能

如圖4-6所示,要想理解這些塊的功能,必須設(shè)想用戶的使用過程:首次打開應(yīng)用,輸入自定義回復(fù),隨時退出并再次打開應(yīng)用。用戶首次啟動應(yīng)用時,數(shù)據(jù)庫中沒有定制回復(fù)可供加載,因此ResponseLabel中顯示的是默認(rèn)回復(fù)。再次啟動時,才有可能從數(shù)據(jù)庫中加載定制回復(fù),并將其顯示在ResponseLabel中。

{%}

圖 4-6 應(yīng)用啟動時從數(shù)據(jù)庫中加載定制回復(fù)

應(yīng)用啟動時觸發(fā)Screen1.Initialize事件,并用tag “responseMessage”來調(diào)用TinyDB1.GetValue,該tag與之前用戶存儲定制回復(fù)時采用的tag相同。讀出的值放在變量response中,并對其進(jìn)行檢驗,然后才能在ResponseLabel中顯示。想想看,為什么從數(shù)據(jù)庫中讀出的數(shù)據(jù),在向用戶顯示之前,要經(jīng)過檢驗?zāi)??如果?shù)據(jù)庫中不存在與指定tag相對應(yīng)的數(shù)據(jù),TinyDB將返回空文本;而第一次啟動應(yīng)用時,數(shù)據(jù)是不存在的,直到用戶輸入了自定義回復(fù),數(shù)據(jù)才會有。由于變量response中保存了數(shù)據(jù)庫返回值,因此可以用if塊來檢查其長度是否大于0。如果大于0 ,說明的確從TinyDB讀出了定制回復(fù)信息,就會將信息顯示在ResponseLabel中;如果長度不大于0,說明之前沒有保存過定制回復(fù)信息,因此將不修改ResponseLabel的顯示內(nèi)容(保留默認(rèn)自動回復(fù)內(nèi)容)。

 測試:上述功能無法進(jìn)行實時測試,因為每次連接“AI伴侶”啟動應(yīng)用時,數(shù)據(jù)庫都會被清空。因此需要選擇“build->App(provide QR code)”,然后掃描條碼,將應(yīng)用下載安裝到手機(jī)上。安裝之后,在NewResponseTextbox中輸入新的回復(fù)信息并單擊SubmitResponseButton按鈕;關(guān)閉應(yīng)用并重新啟動它,這次定制回復(fù)信息出現(xiàn)了嗎?

大聲讀出收到的短信

本節(jié)將修改應(yīng)用:收到短信后,手機(jī)將大聲朗讀發(fā)送者的電話號碼以及短信內(nèi)容。開車收到短信,雖然有自動回復(fù)功能,但你還是禁不住想知道短信的內(nèi)容。使用text-to-speech功能,就可以手不離方向盤而收聽到短信的內(nèi)容。

Android設(shè)備提供了text-to-speech功能,而App Inventor提供了一個TextToSpeech組件,它可以讀出任何text(文本信息 )(注意,此處“text”指的是一般意義上的字/word:一串字母、數(shù)字以及標(biāo)點(diǎn)符號組成的文本,而不是短信文本 。)

在本章的“準(zhǔn)備開始”部分,我們要求你從Android Market下載一個text-to-speech的模塊。如果你還沒做,現(xiàn)在該去做了。根據(jù)需要安裝并配置完模塊之后,就可以在App Inventor中使用TextToSpeech組件了。

TextToSpeech組件的使用非常簡單,只需調(diào)用它的Speak函數(shù)并插入要朗讀的文字即可。例如,圖4-7中的函數(shù)會說“Hello World”。

{%}

圖 4-7 會說“HelloWorld”的塊

在本應(yīng)用中,朗讀的內(nèi)容則更為復(fù)雜,既要包含短信發(fā)送者的電話號碼,也要包含短信內(nèi)容,而不只是像“Hello World”那樣的靜態(tài)文本。這里要用到極為重要的join塊,它可以將若干文本片段(或數(shù)字以及其他字符)連接成單一的文本對象。

在之前的Texting.MessageReceived事件處理程序中,加入對TextToSpeech.Speak的調(diào)用。在之前的事件處理程序中,通過適當(dāng)設(shè)置Texting組件的PhoneNumber和Message屬性,然后發(fā)送回復(fù)信息。現(xiàn)在需要加入表4-6中所列出的塊來擴(kuò)展該事件的處理程序。

表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 獲得收到的短信文本

塊的功能

在自動回復(fù)動作完成之后,將調(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 大聲讀出收到的短信

 測試:你需要第二部手機(jī)來測試應(yīng)用。用第二部手機(jī)發(fā)送文字【必須是英文】到你的測試手機(jī)上。你的手機(jī)大聲讀出信息了嗎?它是否照常發(fā)送自動回復(fù)?

在回復(fù)中加入位置信息

像Facebook的Places以及Google的Latitude等類型的應(yīng)用,都是利用GPS信息來幫助人們跟蹤彼此的位置信息。這樣的應(yīng)用最令人擔(dān)憂的是隱私問題,原因之一是它引發(fā)了人們對“老大哥”的恐懼,這里的“老大哥”指的是那些設(shè)法跟蹤其公民下落的集權(quán)政府。但是使用位置信息的應(yīng)用的確非常有用,試想一個迷路的小孩,或者那些在森林里迷路的徒步旅行者。

在“開車不發(fā)短信”的應(yīng)用中,位置跟蹤讓回復(fù)的短信再多一點(diǎn)內(nèi)容,而不只是“我正在開車”,回復(fù)的信息可以是這樣的:“我正在北京東直門內(nèi)大街209號開車”。對于那些正在等待朋友或家人到來的人來說,這些額外的信息非常有益。

App Inventor提供了LocationSensor(位置傳感器)組件,作為手機(jī)的GPS (Global Positioning System全球定位系統(tǒng))功能的接口。除了緯度和經(jīng)度信息,LocationSensor也可以接入到谷歌地圖,為司機(jī)提供當(dāng)前位置的地址信息。

值得注意的是,LocationSensor并不總在讀取信息,因此務(wù)必要恰當(dāng)?shù)厥褂眠@一組件。具體地講,應(yīng)用只對LocationSensor.LocationChanged事件做出響應(yīng),而兩種情況會觸發(fā)LocationChanged事件:①當(dāng)手機(jī)的位置傳感器第一次收到位置信息時;②隨著手機(jī)的移動,產(chǎn)生新的位置信息時。使用表4-7中列出的塊,具體方法是:當(dāng)LocationChanged事件觸發(fā)時,將當(dāng)前地址信息保存到變量lastKnownLocation中,再將變量值插入到自動回復(fù)信息中。

表4-7設(shè)置位置傳感器的塊

塊的類型 所在抽屜 功能
Initialize global lastKnownLocation to Variables 創(chuàng)建一個變量來保存最后讀取的地址信息
"未知" Text lastKnownLocation的默認(rèn)值
LocationSensor1.LocationChanged LocationSensor1 位置傳感器第一次讀到位置信息,或每次位置信息變化時觸發(fā)該事件
set global lastKnownLocation to Variables 設(shè)置變量值,稍后會用到
LocationSensor1.CurrentAddress LocationSensor1 當(dāng)前地址信息,如:"北京市東城區(qū)東直門內(nèi)大街209號"

塊的功能

當(dāng)位置傳感器首次讀取位置信息時,LocationSensor1.LocationChanged事件被觸發(fā),隨著設(shè)備的移動,還會生成新的位置信息,事件將被再次觸發(fā)。由于自動回復(fù)信息中要包括地址信息,因此,通過調(diào)用LocationSensor1.CurrentAddress函數(shù) 來獲取地址信息,并將其保存在lastKnownLocation變量中,如圖4-9所示。在后臺,這個函數(shù)會調(diào)用谷歌地圖(通過API 來調(diào)用,將在第24章學(xué)到),并根據(jù)傳感器獲得的經(jīng)緯度信息來確定最近的街區(qū)地址。

{%}

圖 4-9 每當(dāng)傳感器收到GPS位置信息時,用變量記錄手機(jī)的位置

注意,這些塊只完成了一半的工作,還要將位置信息插入自動回復(fù)信息中,再回復(fù)給發(fā)件人。

發(fā)送帶有位置信息的回復(fù)

用變量lastKnownLocation中的值對Texting1.MessageReceived事件處理程序加以修改,向自動回復(fù)信息中添加位置信息。表4-8列出了所需要的塊。

表4-8在自動回復(fù)中顯示位置信息的塊

塊的類型 所在抽屜 功能
join Text 多段文本的連接器
ResponseLabel.Text ResponseLabel 不包含位置信息的定制回復(fù)信息
“我最后的位置在:” Text 原定制信息之后的位置信息提示詞
global lastKnownLocation Variables 地址信息,如:“北京市東城區(qū)東直門內(nèi)大街209號”

塊的功能

向回復(fù)中添加位置信息需要LocationSensor1.LocationChanged事件與變量lastKnownLocation的協(xié)作。如圖4-10所示,并非直接發(fā)送ResponseLabel.Text中的信息,而是使用join塊將若干段信息整合起來:原有的自動回復(fù)信息+“ 我的最后位置在:”+變量lastKnownLocation。

{%}

圖 4-10 在回復(fù)信息中加入位置信息

變量lastKnownLocation的默認(rèn)值是“未知”,所以如果位置傳感器尚未產(chǎn)生位置信息,則自動回復(fù)的第二部分內(nèi)容為“我的最后位置在:未知”。如果已經(jīng)產(chǎn)生了位置信息,則自動回復(fù)的第二部分內(nèi)容有可能是這樣:“我的最后位置在:北京市東城區(qū)東直門內(nèi)大街209號”

 測試:用第二部手機(jī)發(fā)送短信到運(yùn)行應(yīng)用的手機(jī)上,第二個手機(jī)是否接收到了帶有位置信息的自動回復(fù)?如果沒有,請確保你已經(jīng)開啟了第一部手機(jī)的GPS定位功能。

完整的應(yīng)用:開車不發(fā)短信

圖4-11中顯示了“開車不發(fā)短信”最終的塊的配置

{%}

圖 4-11 完整的“開車不發(fā)短信”應(yīng)用(同時顯示所有注釋)

改進(jìn)

當(dāng)應(yīng)用已經(jīng)付諸使用,你也許會想到做一些改進(jìn),例如:

  • 編寫另一個版本,允許用戶針對某些特定來信號碼定制回復(fù)內(nèi)容。你需要增加一個條件(if)塊,來檢查這些來信的手機(jī)號。有關(guān)條件塊(if)的更多信息,請參見第18章;

  • 再編寫一個版本,根據(jù)用戶是否在某個緯度/經(jīng)度范圍內(nèi),來回復(fù)定制信息。這樣,如果應(yīng)用判斷你在房間222,它會回復(fù)“鮑勃在222房間,現(xiàn)在不能回復(fù)短信?!庇嘘P(guān)LocationSensor以及確定邊界的更多信息,請參見第23章;

  • 另一個版本,當(dāng)短信發(fā)送者的手機(jī)號碼在某個“通知”列表中時,發(fā)出提醒鈴聲。關(guān)于如何使用列表,請參閱第19章。

小結(jié)

下面是本章涉及到的一些概念:

  • Texting組件:既可以用來發(fā)短信,也可以處理收到的信息。在調(diào)用Texting.SendMessage之前,需要為Texting組件設(shè)置PhoneNumber及Message屬性。為了回復(fù)收到的短信,需要為Texting.MessageReceived事件編寫處理程序;

  • TinyDB組件:用于將信息永久存儲在手機(jī)數(shù)據(jù)庫中,以便每次應(yīng)用啟動時都可以加載保存過的數(shù)據(jù)。有關(guān)TinyDB的更多信息,請參見第22章;

  • TextToSpeech組件:對于所提供的任何文本對象,都可以大聲朗讀出來(限英文);

  • join塊:用于將若干片段的文字拼湊(或連接)成單一的文本對象中;

  • LocationSensor組件:可以報告手機(jī)的緯度、經(jīng)度及當(dāng)前的街道地址。為了確認(rèn)它是否收到了位置信息,可以訪問LocationSensor.LocationChanged事件處理程序中的相關(guān)參數(shù)。該事件在第一次收到位置信息時被觸發(fā),并在每次位置信息更新后被再次觸發(fā)。有關(guān)LocationSensor的更多信息,請參見第23章。

背景知識

Text-To-Speech

縮寫為TTS,直譯為“從文本到語音”,是語音合成技術(shù)的一種應(yīng)用,可以將文字信息實時轉(zhuǎn)換為語音。在本章中使用了Android設(shè)備的此項功能,但遺憾的是,目前Google的TTS引擎尚不支持中文的轉(zhuǎn)換,因此學(xué)員測試時還需使用英文。

英漢對照

text: 文本[名詞]

text: 發(fā)短信[動詞]

initialize: 初始化

speech: 講話

location: 位置

sensor: 傳感器

tiny: 微小的

DB: database數(shù)據(jù)庫

social: 社交的

storage: 存儲

prompt: 提示

response: 響應(yīng)

receive: 接收

submit: 提交

hint: 提示

variable: 變量

phone: 電話

number: 數(shù)字,號碼

call: 調(diào)用,呼叫

message: 消息

send: 發(fā)送

add: 增加

comment: 注釋,評論

voice: 聲音

store: 存放

value: 值

tag: 標(biāo)簽

global: 全球的,全局的

control: 控制

math: 數(shù)學(xué)

length: 長度

provide: 提供

code: 編碼

GPS: 全球定位系統(tǒng)(Global Positioning System)

change: 改變

last: 最后的

current: 當(dāng)前的,現(xiàn)在的

資源下載

NoTexting.aia

NoTexting.apk

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號