你把車停得盡量靠近體育館,但演唱會一結(jié)束,你卻忘了車停在哪兒,你的同伴也很茫然。幸運的是,你的Android手機還在,它從來不忘事,你新裝了一款熱門應用“Android,我的車在哪兒?”有了這個應用,在停車時點一下按鈕,Android的位置傳感器會“記住”車的GPS坐標和地址。當稍后重新打開應用時,它會指給你從現(xiàn)在位置到停車位置的方向,問題解決了!
本章涵蓋如下概念:
LocationSensor組件:確定Android設備的位置;
TinyDB組件:直接在設備數(shù)據(jù)庫中記錄數(shù)據(jù);
登陸App Inventor網(wǎng)站,開始一個新項目“AndroidWhere”(項目名稱不能有空格),將屏幕標題設置為“Android,我的車在哪兒?”,連接測試手機。
應用包含下列可視組件:
多個Label組件:顯示當前位置和“記住”的位置信息,有些Label顯示靜態(tài)文本,如GPSLabel顯示“GPS:”;其他Label,如CurrentLatLabel顯示來自位置傳感器的數(shù)據(jù)。給這些Label設定一個默認值(0,0),當GPS取得位置信息時,這個值將隨之改變;
以及三個非可視組件:
LocationSensor組件:獲取當前位置信息;
TinyDB組件:永久保存位置信息;
按照圖7-1所示的組件設計器截圖來創(chuàng)建組件。
圖 7-1 組件設計器中應用的用戶界面
跟隨表7-1,逐個拖出組件,并做相應設置,創(chuàng)建如圖7-1所示的用戶界面。
表7-1 應用中的所有組件
組件類型 | 面板中分組 | 命名 | 作用 |
---|---|---|---|
Label | User Interface | CurrentHeaderLabel | 顯示標題“當前位置” |
HorizontalArrangement | Screen Arrangement | CurrentAddrArrangement | 放置地址信息 |
Label | User Interface | CurrentAddressLabel | 顯示“地址:” |
Label | User Interface | CurrentAddressDataLabel | 顯示動態(tài)數(shù)據(jù):當前地址 |
HorizontalArrangement | Screen Arrangement | CurrentGPSArrangement | 安置GPS信息 |
Label | User Interface | GPSLabel | 顯示“GPS:” |
Label | User Interface | CurrentLatLabel | 顯示動態(tài)數(shù)據(jù):當前緯度 |
Label | User Interface | CommaLabel | 顯示“,” |
Label | ser Interface | CurrentLongLabel | 顯示動態(tài)數(shù)據(jù):當前經(jīng)度 |
Button | User Interface | RememberButton | 點擊記錄當前位置 |
Label | User Interface | RememberedAddressTitleLabel | 顯示“已記錄的地點” |
HorizontalArrangement | Screen Arrangement | RememberAddrArrangement | 安置已保存的GPS信息 |
Label | User Interface | RememberedAddressLabel | 顯示“地址:” |
Label | User Interface | RememberedAddressDataLabel | 顯示動態(tài)數(shù)據(jù):已記錄的地址 |
HorizontalArrangement | Screen Arrangement | RememberGPSArrangement | 安置已記錄的GPS信息 |
Label | User Interface | RememberedGPSlabel | 顯示“GPS:” |
Label | User Interface | RememberedLatLabel | 顯示動態(tài)數(shù)據(jù):已記錄的緯度 |
Label | User Interface | Comma2Label | 顯示“,” |
Label | User Interface | RememberedLongLabel | 顯示動態(tài)數(shù)據(jù):已記錄的經(jīng)度 |
Button | User Interface | DirectionsButton | 點擊來顯示地圖 |
LocationSensor | Sensors | LocationSensor1 | 感知GPS信息 |
TinyDB | Storage | TinyDB1 | 永久保存已記錄的位置信息 |
ActivityStarter | Connectivity | ActivityStarter1 | 打開地圖 |
用以下方式設置組件屬性:
設置顯示靜態(tài)文本的Label的Text屬性為固定文本,參照表7-1;
設置顯示動態(tài)GPS數(shù)據(jù)的Label的Text屬性為“0.0”;
設置顯示動態(tài)地址的Label的Text屬性為“未知”;
取消勾選RememberButton和DirectionsButton的Enabled屬性(設置為不可用);
**表7-2 打開谷歌地圖所要設定的ActivityStarter屬性
屬性 | 值 |
---|---|
Action | android.intent.action.VIEW |
ActivityClass | com.google.android.maps.MapsActivity |
ActivityPackage | com.google.android.apps.maps |
塊的類型 所在抽屜 作用 RememberButton.Click RememberButton 用戶點擊按鈕時觸發(fā)該事件 set RememberedAddressDataLabel.Text to RememberedAddressDataLabel 將傳感器獲得的地址信息寫入“已記錄”label中 LocationSensor1.CurrentAddress LocationSensor 該屬性保存了街道地址信息 set RememberedLatLabel.Text to RememberedLatLabel 將緯度信息寫入“已記錄”label中 LocationSensor1.Latitude LocationSensor 該屬性保存了緯度信息 set RememberedLongLabel.Text to RememberedLongLabel 將經(jīng)度信息寫入“已記錄”label中 LocationSensor1.Longitude LocationSensor 該屬性保存了經(jīng)度信息 set DirectionsButton.Enabled to DirectionsButton 設置DirectionsButton的Enabled屬性 true Logic 設置DirectionsButton的Enabled屬性為真 塊的作用
當用戶點擊RememberButton時,當前位置信息將寫入“已記錄”label中,如圖7-3所示。
圖 7-3 將當前位置信息寫入“已記錄”label中
注意到DirectionsButton已可用,這會有點兒小麻煩,因為如果用戶立即點擊DirectionsButton,記住的位置也是當前位置,因而地圖中不會提供方向有關的信息。但是,人們似乎不會這么做,當用戶移動位置時(例如步行到演唱會),則當前位置將偏離已記錄的位置。
測試:將應用的新版本下載到手機,并再次測試。當單擊RememberButton時,當前位置信息是否被寫入到“已記錄”的label中?
顯示“已記錄”位置的方向
當用戶點擊DirectionsButton 時,應用將打開谷歌地圖,地圖中顯示從用戶當前位置到“已記錄”位置(即停車的位置)的方向。
ActivityStarter組件可以打開任何Android應用,也包括谷歌地圖,但必須做一些相應的設置。不過像打開瀏覽器或地圖這樣的應用,設置起來相當簡單。
打開地圖的關鍵是設置ActivityStarter.DataUri屬性,該屬性無異于你在瀏覽器中直接輸入的網(wǎng)址。要想搞清楚這一點,只需在瀏覽器中打開http://maps.google.com,并詢問,比如舊金山與奧克蘭之間的方向。當結(jié)果出來時,點擊地圖的左上部的鏈接按鈕,并檢查顯示的URL。這正是你在應用中所需要的URL。
所不同的是,帶有方向的地圖涉及到兩個位置,即起點和終點,它們分別用一組特定的GPS坐標來表示(而非城市之間)。該URL必須采用以下形式:
http://maps.google.com/maps?saddr=37.82557,-122.47898&daddr=37.81079,-122.47710
在瀏覽器中輸入網(wǎng)址,說說看,它指引你跨越了那個著名的地標性建筑?
這里需要為URL設定動態(tài)參數(shù):起點地址(saddr)和終點地址(daddr)。在前幾章中,你已經(jīng)學會用join塊將文本連接起來,這里也是如此。將當前位置和已記錄位置的GPS數(shù)據(jù)插入到URL中,設置ActivityStarter.DataUri屬性為URL,然后調(diào)用ActivityStarter.StartActivity。表7-5列出了此項功能所需要的塊。
塊的作用
用戶點擊DirectionsButton時,事件處理程序生成一個地圖URL,然后調(diào)用ActivityStarter打開地圖應用并加載地圖,如圖7-4所示,用join創(chuàng)建的URL發(fā)送給地圖應用。
圖 7-4 生成一個URL,用來打開地圖并指示方向
最終的URL包含了地圖域名(http://maps.google.com/maps)以及兩個URL參數(shù):saddr與daddr,用來指定方向的起點位置及終點位置。在本應用中,saddr被設定為當前位置的緯度和經(jīng)度,而daddr被設定為已記錄的停車位置的緯度和經(jīng)度。
表7-5 打開一張帶有方向指示的地圖所需要的塊
塊的類型 所在抽屜 作用 DirectionsButton.Click DirectionsButton 用戶點擊”指示方向”按鈕觸發(fā)該事件 set ActivityStarter1.DataUri to ActivityStarter1 設置要打開地圖的URL join Text 將URL的各組成部分連接起來 “http://maps.google.com/maps?saddr=” Text URL中固定的部分,后面接起點經(jīng)緯度 CurrentLatLabel.Text CurrentLatLabel 當前位置的緯度值 “,” Text 放在經(jīng)緯度值之間的逗號 CurrentLongLabel.Text CurrentLongLabel 當前位置的經(jīng)度值 “&daddr=” Text URL中的第二個參數(shù),后面接終點經(jīng)緯度 RememberedLatLabel.Text RememberedLatLabel 已記錄位置的緯度 “,” Text 放在經(jīng)緯度值之間的逗號 RememberedLongLabel.Text RememberedLongLabel 已記錄位置的經(jīng)度 ActivityStarter1.StartActivity ActivityStarter1 打開地圖
測試:用手機下載新的版本并再次測試,一旦取得讀數(shù),單擊RememberButton然后走開。當單擊DirectionsButton時,地圖是否提示您如何追溯你的腳步?點擊幾次后退按鈕。你是否有回到了你的應用?
永久保存已記錄的位置信息
現(xiàn)在已經(jīng)具備了一個全功能的應用:記住起點位置,并從當前用戶所在的位置繪制一張回到起點的地圖。雖然用戶“記住”了位置,但假如應用被關閉,然后再重新打開,“記住”的信息也將消失。實際上你希望用戶能夠記錄下車的位置,關閉應用,走到別處,然后重新啟動應用,并獲取已記錄的車輛所在位置的方向。
如果你能想起“開車不發(fā)短信”應用(第4章),說明你的思路是正確的,我們需要使用TinyDB數(shù)據(jù)庫來永久保存這些數(shù)據(jù),采取的方案也與之前的應用類似:
1. 當用戶點擊RememberButton時,位置信息存儲到數(shù)據(jù)庫中;
2. 當應用啟動時,從數(shù)據(jù)庫中加載位置信息并保存到一個變量或?qū)傩灾小?/p>
從修改RememberButton.Click事件處理程序開始,來存儲這些要被“記住”的信息。存儲緯度、經(jīng)度和地址三組信息,需要三次調(diào)用TinyDB.StoreValue。表7-6列出了所要補充的塊。
表7-6 永久保存位置信息所需要的塊
塊的類型 所在抽屜 作用 TinyDB1.StoreValue(3) TinyDB1 將數(shù)據(jù)保存在設備數(shù)據(jù)庫中 “address” Text 插入TinyDB1.StoreValue的tag插槽中 LocationSensor1.CurrentAddress LocationSensor1 插入TinyDB1.StoreValue的value插槽中,永久保存地址信息 “l(fā)at” Text 插入第二個TinyDB1.StoreValue的tag插槽中 LocationSensor.CurrentLatitude LocationSensor 插入第二個TinyDB1.StoreValue的value插槽中,永久保存緯度信息 “l(fā)ong” Text 插入第三個TinyDB1.StoreValue的tag插槽中 LocationSensor.CurrentLongitude LocationSensor 插入第三個TinyDB1.StoreValue的value插槽中,永久保存經(jīng)度信息 塊的作用
如圖7-5所示,TinyDB1.StoreValue將LocationSensor屬性中的位置信息保存到數(shù)據(jù)庫中。你該記得在“開車不發(fā)短信”中,StoreValue函數(shù)有兩個參數(shù),tag與value,tag充當已存儲數(shù)據(jù)的標識,value是你實際想保存的數(shù)據(jù),即本例中的LocationSensor數(shù)據(jù)。
圖 7-5 在數(shù)據(jù)庫中存儲被“記住”的位置信息
啟動應用時讀取“記住”的位置信息
將數(shù)據(jù)保存在數(shù)據(jù)庫中,是為了以后可以調(diào)用它。在本應用中,如果用戶在保存了位置信息之后退出應用,那么當應用重新打開時,你希望從數(shù)據(jù)庫中讀出信息并顯示給用戶。
在前幾章中討論過,應用的啟動會觸發(fā)Screen.Initialize事件,而在啟動時從數(shù)據(jù)庫中讀取數(shù)據(jù)是一種慣例,我們也不例外。
使用TinyDB.GetValue函數(shù)來讀取存儲的GPS數(shù)據(jù)。要讀取的存儲數(shù)據(jù)包括地址、緯度及經(jīng)度,因此要調(diào)用GetValue函數(shù)三次。像在“開車不發(fā)短信”中一樣,要事先檢查數(shù)據(jù)庫中否保存了數(shù)據(jù)(如,第一次啟動應用時,TinyDB.GetValue將返回一個空文本)。
挑戰(zhàn)一下自己,看看是否可以獨立創(chuàng)建這些塊,然后再與圖7-6進行比較。
圖 7-6 在應用啟動時,從數(shù)據(jù)庫中讀取數(shù)據(jù),如果數(shù)據(jù)不為空則顯示數(shù)據(jù)
塊的作用
理解這些塊的方法是設想用戶的使用過程:用戶首次打開應用,先保存位置信息,稍后再次打開應用。首次打開應用,數(shù)據(jù)庫中沒有信息可加載,也不必填寫“已記錄”label或啟用DirectionsButton。在后續(xù)的使用中,如果確有數(shù)據(jù)存儲,就要從數(shù)據(jù)庫中加載這些位置信息。
首先用“address”為tag(標簽)調(diào)用TinyDB1.GetValue函數(shù),之前在存儲位置信息時使用過這個tag。讀取的值保存在變量tempAddress中,并檢查其是否為空。
if塊將檢查從數(shù)據(jù)庫中讀出的數(shù)據(jù)。如果TinyDB對指定的tag沒有返回值,則返回空文本。首次啟動應用時沒有數(shù)據(jù)可讀,直到用戶點擊了RememberButton。由于變量tempAddress中保存了數(shù)據(jù)庫的返回值,因此if塊將檢查tempAddress的長度,如果長度>0,則TinyDB有地址信息返回,也表明經(jīng)緯度.GetValue讀出經(jīng)緯度信息。當設置完所有信息,最后啟用DirectionsButton。
測試:將新版本應用下載到手機,并再次測試。點擊RememberButton,并確?!坝涀 弊x數(shù)。關閉應用并再次打開。那些數(shù)據(jù)是否還在?
完整的應用:Android,我的車在哪兒?
圖7-7顯示了完整的“Android,我的車在哪兒?”應用中所用到的塊。
圖 7-7 “Android,我的車在哪兒”應用中所有的塊
改進
可以嘗試如下改進:
創(chuàng)建一個“Android,他們在哪兒?”的應用,讓一群人可以了解彼此行蹤。無論你在徒步旅行還是在公園散步,這個應用都有助于你節(jié)省時間,甚至可能挽救生命。應用中的數(shù)據(jù)是共享的,因此要使用web數(shù)據(jù)庫,用TinyWebDB組件來替代TinyDB。更多信息請參見第22章。
- 創(chuàng)建一個“行蹤”應用,用列表來記錄自己的位置改變,即行蹤。當記錄數(shù)達到一定數(shù)量時,或超過一定時間時,開始一個新的“行蹤”,因為即使是輕微的位移也會產(chǎn)生一個新的位置讀數(shù)。這類應用需要使用列表來存儲位置記錄,需要幫助時請參見第19章。
小結(jié)
下面是本章涉及到的概念:
LocationSensor組件:可以報告用戶的緯度、經(jīng)度及當前的街區(qū)地址。當傳感器首次獲得數(shù)據(jù)或數(shù)據(jù)發(fā)生變化(設備移動)時,將觸發(fā)LocationChanged事件。有關LocationSensor的更多信息,請參見第23章;
ActivityStarter組件:可以在一個應用中打開其他應用,包括谷歌地圖。對于地圖,需要將ActivityStarter的DataUri屬性設置為想要打開的地圖的URL地址。如果你想顯示兩個GPS坐標之間的方向,URL應該寫成下面的格式,你可以用實際位置的GPS坐標來替換下面的示例數(shù)據(jù):http://maps.google.com/maps/?saddr=0.1,0.1&daddr=0.2,0.2;
join用來將文本片段拼湊(連擊)成單一的文本對象,也可以讓靜態(tài)文本與動態(tài)數(shù)據(jù)相連接。對于地圖URL來說,GPS坐標就是動態(tài)數(shù)據(jù);
- TinyDB讓數(shù)據(jù)永久地保存在在手機的數(shù)據(jù)庫中。保存在變量或?qū)傩灾袛?shù)據(jù),會隨著應用的關閉而丟失,但存儲在數(shù)據(jù)庫中的數(shù)據(jù),可以在每次啟動應用時被載入。有關TinyDB和數(shù)據(jù)庫的詳細信息,請參見第22章。
資源下載
更多建議: