使用 JSON 及 Geolocation- 小於 50 行程式碼的 Windows Store App 又一番
我想寫個小 App ,首先是想抓取台北市政府資料開放平台 (https://data.taipei.gov.tw) 所提供的 JSON 資料,例如溫泉業者、停車場、各區運動中心等等,然後顯示選擇場所的附近地圖,進而取得由所在位置出發的路線規劃。
開始 coding! (此文所用程式碼在https://sdrv.ms/ZzMsuo,請自由下載使用)
我們先來看看台北市提供的「OK認證-游泳場所業」的資料如以下,可以看到「資料介接」的 JSON 連結為: https://data.taipei.gov.tw/opendata/apply/json/N0JCNzMwNEYtMkRDQi00ODNFLUIzQjMtN0E0ODM4RTU4NUUz ,此連結將被作為我的資料來源。
接下來打開 Visual Studio 2012,開啟一空白 Windows Store App 專案,打開 MainPage.xaml 並規劃介面如以下:
各位可以看到畫面左邊我拉了一個 ListBox 控制項,畫面右邊拉了一個 WebView,是準備用來呈現地圖的,同時右下角有個RadioButton group 及一個 Button 按鈕。
以下我實作了一個 GetJSON() 方法:
private async Task GetJSON()
{
string strURI = "https://data.taipei.gov.tw/opendata/apply/json/N0JCNzMwNEYtMkRDQi00ODNFLUIzQjMtN0E0ODM4RTU4NUUz";
var http = new HttpClient();
http.MaxResponseContentBufferSize = Int32.MaxValue;
var response = await http.GetStringAsync(strURI);
JsonValue jsonValue = JsonValue.Parse(response.ToString());
int arraySize = jsonValue.GetArray().Count;
this.listArray = new string[arraySize];
this.telArray = new string[arraySize];
this.addrArray = new string[arraySize];
for (int i = 0; i < arraySize; i++)
{
IJsonValue element = jsonValue.GetArray()[i];
string strName = element.GetObject().GetNamedString("name");
listArray[i] = strName;
string strTel = element.GetObject().GetNamedString("tel");
telArray[i] = strTel;
string strAddr = element.GetObject().GetNamedString("poi_addr");
addrArray[i] = strAddr;
}
}
以上程式基本上作了兩件事:
1. 把 JSON 資料抓下來:各位可以看到我只用了一個 GetStringAsync() 方法就將資料抓取下來成為一個JSON字串。
2. 接下來是要處理所得到的 JSON 字串:在處理之前我們得先了解此 JSON 字串的結構,以此資料為例,會發現此JSON字串為一包含多個物件 (objects) 之陣列 (arrays),如以下:
了解資料結構後,就能參考使用 JavaScript 物件標記法這篇文章,如以上的程式碼,利用一個 for 迴圈讀取陣列中的所有物件,取得所需要的值;再於以下的 OnNavigatedTo() 方法中,將所有的游泳場所名塞入位於畫面左側的 ListView:
protected async override void OnNavigatedTo(NavigationEventArgs e)
{
await GetJSON();
for (int i = 0; i < listArray.Length; i++)
{
listBox1.Items.Add(listArray[i].ToString());
}
// Register for DataRequested events
DataTransferManager.GetForCurrentView().DataRequested += OnDataRequested;
}
在此請注意,GetJSON() 方法中因為至少呼叫一個非同步方法(即 GetStringAsync()),所以在方法的宣告前要加一個 async ;同時在呼叫此 GetJSON() 方法之前得加上一個 await 的關鍵字。 (這部份可參考: 使用 Async 和 Await 設計非同步程式)
跑起來會長得像這樣:
接下來是實作當使用者點選 ListView 裡的游泳場所後,會在右邊的 WebView 中呈現 選取所在地的 Google 地圖 (透過URI string的方式):
private void listBox1_Tapped_1(object sender, TappedRoutedEventArgs e)
{
strSelectedList = listBox1.SelectedValue.ToString();
strSelectedAddress = addrArray[listBox1.SelectedIndex].ToString();
strSelectedTel = telArray[listBox1.SelectedIndex].ToString();
webView.Source = new Uri(Uri.EscapeUriString
("https://maps.google.com/?output=embed&num=1&saddr=" + strSelectedAddress));
listName.Text = strSelectedList;
listTel.Text = strSelectedTel;
listAddr.Text = strSelectedAddress;
}
使用者點選後就會長得像這樣:
最後,我想讓使用者能看到由目前所在位置到選取地點的規劃路線,所以實作右下角的 Button 按鈕程式如下:
private async void Button_Click_1(object sender, RoutedEventArgs e)
{
if (strSelectedAddress.Length > 0)
{
if (geo == null)
{
geo = new Geolocator();
}
try
{
Geoposition pos = await geo.GetGeopositionAsync();
string strSADDR = pos.Coordinate.Latitude.ToString() + "," +
pos.Coordinate.Longitude.ToString();
webView.Source = new Uri(Uri.EscapeUriString(
"https://maps.google.com/?num=1&saddr=" +
strSADDR + "&daddr=" + strSelectedAddress +
"&dirflg=" + strDirFlg));
}
catch (Exception)
{
new Windows.UI.Popups.MessageDialog(
"您的機器沒有定位服務(GPS)或目前服務是關閉的,請透過「設定」快速鍵重新開啟。
\nYour location services are currently turned off.
Use the Settings charm to turn them back on.").ShowAsync();
}
}
}
各位可以看到我首先取得目前所在位置的經緯度,是透過 Geolocator.GetGeopositionAsync() 這個方法來取得;接下來只是再度重組一個 URI string,透過Google Maps 規劃路線即可。取得目前所在位置細節另可參考這篇文章。
實作之後的執行畫面:
程式碼: https://sdrv.ms/ZzMsuo