使用 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 ,此連結將被作為我的資料來源。

image

接下來打開 Visual Studio 2012,開啟一空白 Windows Store App 專案,打開 MainPage.xaml 並規劃介面如以下:

image

各位可以看到畫面左邊我拉了一個 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),如以下:

image

了解資料結構後,就能參考使用 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 設計非同步程式)

跑起來會長得像這樣:

image

接下來是實作當使用者點選 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;
}

使用者點選後就會長得像這樣:

image

最後,我想讓使用者能看到由目前所在位置到選取地點的規劃路線,所以實作右下角的 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 規劃路線即可。取得目前所在位置細節另可參考這篇文章

 

實作之後的執行畫面:

image  

程式碼: https://sdrv.ms/ZzMsuo

 

附註: 台灣目前一些公開資訊開放平台: 行政院農委會開放資料平台台北市政府新北市政府台中市台南市教育局文化部臺灣中央政府的資料入口網站「data.gov.tw 」