Windows Phone 7 - 使用Google Map API將地址轉成座標

Windows Phone 7 - 使用Google Map API將地址轉成座標

最近在撰寫一個使用Bing Map來操作的App,遇到要提供用戶可以輸入自己的地址,並且地址轉成座標後,

自動標示於地圖上。其實這功能在撰寫Android App裡我已經有遇過了,剛好最近在撰寫WP7,又拿出來簡

單的做個筆記。

Google Map API提供開發人員可以將輸入的地址轉成對應的座標,可以在<Google Geocoding API >參考得到。

然而,該篇將介紹在WP7中如何取得資料的方式。

 

Google Geocoding API

由於Google提供「http://maps.googleapis.com/maps/api/geocode/output?parameters」該網址段,透過參數的方式,

只需在特定的Query String key加上要搜尋的地址與要回傳的格式內容,即可以完成我們需要的功能。至於詳細參數的使

用方式,我透過擷取<Google Geocoding API>的內容,如下:

參數 類型 說明
output json (建議使用) 表示輸出格式為 JavaScript 物件註釋 (JSON);
  xml 表示輸出格式為 XML,相對資料大小比json大很多;
     
parameters address (必要):您要進行地理編碼的地址。address與latlng,擇一使用。
  latlng (必要):您將為此文字經/緯度值取得最接近的人類可讀地址。
address與latlng,擇一使用。
  bounds (選用):您可在此檢視區的邊框中,進一步自訂調整地理編碼結果。(如需詳細資訊,請參閱下方的「檢視區自訂調整」)。
  region (選用):將區域代碼指定為 ccTLD (「頂層網域」) 的兩位字元值。(如需詳細資訊,請參閱下方的「區域自訂調整」)。
  language (選用):結果傳回時使用的語言。請參閱「支援的網域語言清單」。
  sensor (必要):指出地理編碼要求的來源裝置是否附有位置感應器。這個值必須是 truefalse

重要用的參數是:address與sensor,所以往下就來看看回傳的結果,並說明要建立成.NET可以讀取的序列化類別為何。

 

a. 使用URL取得JSON回傳結果

    使用Google Geocoding API方式,只需在指定的網址內加上需要的key & value,如下:

http://maps.googleapis.com/maps/api/geocode/json?address=1600+Amphitheatre+Parkway,+Mountain+View,+CA&sensor=true_or_false

回傳的結果,我們透過<http://jsonviewer.stack.hu/>的結果來加以分析:

圖片1

透過上圖可以看到,有很多集合的部分,這些集合的部分要轉成資料類別時,這些集合就是一個Collection的屬性,

例如:result、address_components、geometry、types屬性。那單一值就是透過string類型來加以儲存,例如:

status、location_type、formatted_address、lat、lng、long_name、short_name。

從上圖也可以看出,Geocoding  API提供的轉換後的完整資訊,當然,如果今天隨便輸入地址的話,回傳的結果就

不一樣了,相關的錯誤訊息,也可以直接參數Google Geocoding API上的說明。如果今天需要是找附近資訊的話,

就需要用另一個Google Places API 了。

 

 

〉轉成至WP7的寫法

    撰寫WP7處理JSON的內容,在很多文章都提過,與WP7相關的文章,可以參考下述連結的作法:

<[WP7] 使用 JSON 方式來處理 台北市公開政府資料平臺(ODGI) 資料 ─ 以旅館業範例>,由於該篇的作業非常清楚,

這裡我就不再重覆說明相關的作法,只針對如何定義接收Google Geocoding API回傳結果的資料類別,以下直接撰

寫程式來說明如何定義。

 

a. 先定義要儲存的資料實體

   1: using System;
   2: using System.Runtime.Serialization;
   3: using System.Collections.Generic;
   4:  
   5: namespace Location.Data
   6: {
   7:     /// <summary>
   8:     /// Google Map API, Address convert to Location, Data Entity. by Json format.
   9:     /// </summary>
  10:     [DataContract]
  11:     public class GAddressGeoCollection
  12:     {
  13:         public GAddressGeoCollection() { }
  14:         /// <summary>
  15:         /// JSON回傳的results集合。
  16:         /// </summary>
  17:         [DataMember]
  18:         public List<GAddressGeoResult> results { get; set; }
  19:         /// <summary>
  20:         /// JSON回傳的status字串。
  21:         /// </summary>
  22:         [DataMember]
  23:         public string status { get; set; }
  24:     }
  25:  
  26:     /// <summary>
  27:     /// results資料結構。
  28:     /// </summary>
  29:     [DataContract]
  30:     public class GAddressGeoResult
  31:     {
  32:         public GAddressGeoResult() { }
  33:         //[DataMember]
  34:         //public List<GAddressComponent> address_components { get; set; }
  35:         [DataMember]
  36:         public string formatted_address { get; set; }
  37:         /// <summary>
  38:         /// 座標資料集合。
  39:         /// </summary>
  40:         [DataMember]
  41:         public GAddressGeoEntity geometry { get; set; }
  42:     }
  43:  
  44:     [DataContract]
  45:     public class GAddressComponent
  46:     {
  47:         public GAddressComponent() { }
  48:         [DataMember]
  49:         public string long_name { get; set; }
  50:         [DataMember]
  51:         public string short_name { get; set; }
  52:         //[DataMember]
  53:         //public string types { get; set; }
  54:     }
  55:  
  56:     [DataContract]
  57:     public class GAddressGeoEntity
  58:     {
  59:         public GAddressGeoEntity() { }
  60:         [DataMember]
  61:         public GAddressLocation location { get; set; }
  62:         [DataMember]
  63:         public string location_type { get; set; }
  64:     }
  65:  
  66:     [DataContract]
  67:     public class GAddressLocation
  68:     {
  69:         public GAddressLocation() { }
  70:         [DataMember]
  71:         public string lat { get; set; }
  72:         [DataMember]
  73:         public string lng { get; set; }
  74:     }
  75: }

上述主要定義了接收Google Geocoding API的資料類別,該類別由的「屬性名稱」要與JSON回傳結果中元素名稱一致,

才能對應起來,例如:results、status。然而,results是一個集合,所以另外定義了GAddressGeoResult的類別來接收

results的結果,以這個概念往下去推演,results中也有很多集合,這些集合的item也需要一個獨立的資料類別來定義,

如此一來,整個資料實體就能完成對應起來了。

 

b. 實作要呼叫Google Geocoding API的Handler

    [注意] 要使用的參考包括:

    System.Runtime.Serialization; System.ServiceModel; System.Servicemodel.Web;

   1: public class GoogleSearchHandler
   2: {
   3:     private string gSearchURL = "http://maps.googleapis.com/maps/api/geocode/json?address={0}&sensor=true";
   4:  
   5:     /// <summary>
   6:     /// 搜尋地址,並轉換成座標。
   7:     /// </summary>
   8:     /// <param name="pAddress"></param>
   9:     public void SearchAddress(string pAddress)
  10:     {
  11:         if (DeviceNetworkInformation.IsWiFiEnabled || DeviceNetworkInformation.IsCellularDataEnabled
  12:             || DeviceNetworkInformation.IsNetworkAvailable)
  13:         {
  14:             try
  15:             {
  16:                 gSearchURL = string.Format(gSearchURL, pAddress);
  17:                 WebClient tWebClient = new WebClient();
  18:                 tWebClient.DownloadStringCompleted +=
  19:                             new DownloadStringCompletedEventHandler(tWebClient_DownloadStringCompleted);
  20:                 tWebClient.DownloadStringAsync(
  21:                     new Uri(gSearchURL));
  22:             }
  23:             catch (Exception)
  24:             {
  25:                 throw;
  26:             }
  27:         }
  28:     }
  29:  
  30:     /// <summary>
  31:     /// 取得指定URL回傳的結果,觸發事件。
  32:     /// </summary>
  33:     /// <param name="sender"></param>
  34:     /// <param name="e"></param>
  35:     void tWebClient_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
  36:     {
  37:         GAddressGeoCollection tCollection = null;
  38:         Exception tException = null;
  39:         if (e.Error == null)
  40:         {
  41:             try
  42:             {
  43:                 tCollection = new GAddressGeoCollection();
  44:                 DataContractJsonSerializer tJsonSerial = new DataContractJsonSerializer(typeof(GAddressGeoCollection));
  45:                 MemoryStream tMS = new MemoryStream(Encoding.UTF8.GetBytes(e.Result));
  46:                 tCollection = tJsonSerial.ReadObject(tMS) as GAddressGeoCollection;
  47:                 //判斷搜尋結果不為Null時,才是真正可以使用的資料
  48:                 if (tCollection != null && tCollection.results != null)
  49:                 {
  50:                     Utility.GAddressGeoResult = tCollection.results[0];
  51:                 }
  52:             }
  53:             catch (Exception ex)
  54:             {
  55:                 tException = ex;
  56:             }
  57:         }
  58:     }
  59: }

上述是範例程式主要透過WebClient呼叫DownloadStringAsync的事件來進行資料的下載後,再透過.NET內鍵的

DataContractJsonSerializer類別將資料加以序列化,配置成上述定義的資料類別。

 

c. 執行結果
006 007

 

[補充]

a. 如果今天希望透過座標找到附近相關的地方資訊的話,可以參考<Google Places API>,並且注意下方的參數使用方式:

參數 類型 說明
output xml (建議使用) 表示輸出格式為 JavaScript 物件註釋 (JSON)
  json 表示輸出格式為 XML (傳輸量會較JSON大)
     
parameters location (必要) 您要擷取「地方資訊」附近的經緯度值。這必須以 google.maps.LatLng 物件方式提供。
  radius (必要) 「地方資訊」結果傳回的距離 (以公尺為單位)。建議的最佳作法是根據位置感應器提供的位置信號精確性,設定 radius。請注意,設定 radius 會將結果自訂調整至所指示的區域,但不會將結果完全限制在指定的區域。
  types (選用) 將結果限制為至少符合一個指定類型的「地方資訊」。類型應以直立線符號分隔 (type1|type2|etc)。請參閱「支援類型的清單」。
  language (選用) 指出應以何種語言傳回結果 (如有可能) 的語言代碼。請參閱「支援語言的清單」及其代碼。請注意,我們經常更新支援的語言,因此這份清單可能會有遺漏。
  name (選用) 用以比對地方資訊名稱的字詞。結果將會限制在包含所傳遞之 name 值的結果中。包含名稱時,所搜尋的區域可能會擴大,以確保會有適當數量的結果。
  sensor (必要) 表示來自裝置的「地點」要求是否使用位置感應器 (如 GPS) 來判斷這項要求中所傳送的位置。這個值必須是 truefalse
  key (必要) 您應用程式的 API 金鑰。此金鑰會識別您的應用程式,以進行配額管理,如此一來,從您的應用程式新增的「地方資訊」就可立即供您的應用程式使用。請造訪 API 控制台建立「API 專案」,並取得您的金鑰。

======

以上是簡單記錄撰寫的心得,由於LBS的盛行,這樣的功能是一定要學會的。這樣才能撰寫出相關在地圖上

加上更多豐富內容的App。撰寫的內容有點偷懶,請多包涵。

 

References:

[WP7] 使用 JSON 方式來處理 台北市公開政府資料平臺(ODGI) 資料 ─ 以旅館業範例

Google Places API (重要)

Google Distance Matrix API (重要)

Google Directions API (重要)

Google Geocoding API (重要)

 

Dotblogs Tags: