Windows Phone - 利用GeoLocation取得對應的Address - 2

Windows Phone - 利用GeoLocation取得對應的Address - 2

接續<Windows Phone - 利用GeoLocation取得對應的Address - 1>說明利用WP 8.0提供的SDK取得反向地理編碼查詢物件的方式,

本篇將介紹利用Google Geocoding API的功能,將取得座標轉換成地址。

 

〉搭配Google Geocoding API

    利用Google的API是比較常見的使用方法,不過使用這個API如果您的App是希望支援China的話,那建議你不要使用

China目前仍未支援Google的服務,不一定可以正常使用它。使用該API之前請先閱讀<Google Geocoding API>的相關說明。

使用的URL格式為:

 

針對paramters從中擷取出幾個重點的參數,如下:

參數 說明
output 可用json或xml二種格式。
latlng 將為此文字經/緯度值取得最接近的人類可讀地址,搭配<反向地理編碼>的邏輯。
sensor 指出地理編碼要求的來源裝置是否附有位置感應器。這個值必須是 truefalse。
language 傳回結果所要使用的語言。請參閱<支援的網域語言清單>。

 

將URL與parameters組合成要用GeoLocation反查Address的URL如下(注意:latlng請確定兩者之間沒有任何空格):

至於這樣取得的結果與說明,請參考<反向地理編碼 (地址查閱)>的說明。

 

了解Google API的使用方式後,進一步將整合至Windows Phone的專案裡,我建立了一個專用的Class提供給外部引用者來操作,如下:

(1) 採用json格式操作,需要先將API回傳的JSON結果建立成一個個的JSON類別

#region GoogleGeoLocationAPIResult的JSON

		
		
public class GoogleGeoLocationAPIResult
{
    public ResultObject[] results { get; set; }
    public string status { get; set; }
}

		
		
public class ResultObject
{
    public Address_Components[] address_components { get; set; }
    public string formatted_address { get; set; }
    public Geometry geometry { get; set; }
    public string[] types { get; set; }
}

		
		
public class Geometry
{
    public Location location { get; set; }
    public string location_type { get; set; }
    public Viewport viewport { get; set; }
    public Bounds bounds { get; set; }
}

		
		
public class Location
{
    public float lat { get; set; }
    public float lng { get; set; }
}

		
		
public class Viewport
{
    public Northeast northeast { get; set; }
    public Southwest southwest { get; set; }
}

		
		
public class Northeast
{
    public float lat { get; set; }
    public float lng { get; set; }
}

		
		
public class Southwest
{
    public float lat { get; set; }
    public float lng { get; set; }
}

		
		
public class Bounds
{
    public Northeast1 northeast { get; set; }
    public Southwest1 southwest { get; set; }
}

		
		
public class Northeast1
{
    public float lat { get; set; }
    public float lng { get; set; }
}

		
		
public class Southwest1
{
    public float lat { get; set; }
    public float lng { get; set; }
}

		
		
public class Address_Components
{
    public string long_name { get; set; }
    public string short_name { get; set; }
    public string[] types { get; set; }
}

		
		
#endregion

    需要建立這些類別來做JSON文字與類別的序列化,這樣在程式裡操作可以直接利用物件交易,不需要不斷地拆解JSON格式。

 

(2) 搭配WebClient支援向Google Geocoding API請求轉換座標為地址

public class GoogleGeoAPI : IDisposable
{
    public delegate void ErrorInvoke(Exception e);

		
		
    public delegate void SuccessInvoke(string e);

		
		
    //查詢失敗可操作的事件通知。
    public ErrorInvoke Error;

		
		
    //查詢成功可操作的事件通知。
    public SuccessInvoke Completed;

		
		
    private WebClient gWebClient;

		
		
    public GoogleGeoAPI()
    {
        gWebClient = new WebClient();
        gWebClient.DownloadStringCompleted += gWebClient_DownloadStringCompleted;
    }

		
		
    void gWebClient_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
    {
        if (e.Error != null)
        {
            this.Error(e.Error);
        }
        else
        {
            DataContractJsonSerializer tJsonSerial = null;
            MemoryStream tMS = null;
            GoogleGeoLocationAPIResult tResultObject = null;
            ResultObject tNear = null;
            try
            {
                tJsonSerial = new DataContractJsonSerializer(typeof(GoogleGeoLocationAPIResult));
                tMS = new MemoryStream(Encoding.UTF8.GetBytes(e.Result));
                tResultObject = tJsonSerial.ReadObject(tMS) as GoogleGeoLocationAPIResult;
                //取得第一個最精準的結果
                tNear = tResultObject.results.FirstOrDefault();
                this.Completed(tNear.formatted_address);
            }
            catch (Exception ex)
            {
                this.Error(ex);
            }
            finally
            {
                if (tJsonSerial != null) tJsonSerial = null;
                if (tMS != null)
                {
                    tMS.Close();
                    tMS.Dispose();
                    tMS = null;
                }
                tResultObject = null;
                tNear = null;
            }
        }
    }

		
		
    /// <summary>
    /// 指定座標查詢地址。
    /// </summary>
    /// <param name="pLatitude">0.000000</param>
    /// <param name="pLongitude">0.000000</param>
    public void QueryAddressByLocation(string pLatitude, string pLongitude)
    {
        if (gWebClient.IsBusy == false)
        {
            string tURL = string.Format("http://maps.googleapis.com/maps/api/geocode/json?latlng={0},{1}&sensor=false&language={2}",
                            pLatitude, pLongitude, "zh-TW");

		
		
            gWebClient.DownloadStringAsync(new Uri(tURL, UriKind.Absolute));
        }
    }

		
		
    public void Dispose()
    {
        if (gWebClient.IsBusy)
        {
            gWebClient.CancelAsync();
        }
        gWebClient = null;
    }
}

 

(3) 搭配WP中取得座標的結果後,使用(2)所建立好的API

private void GeoLocationToAddress(GeoCoordinate pLocation)
{
    GoogleGeoAPI tGoogleAPI = new GoogleGeoAPI();
    tGoogleAPI.Error += (e) =>
    {
        Dispatcher.BeginInvoke(() =>
        {
            MessageBox.Show("目前座標無法轉換成地址資訊");
        });
    };
    tGoogleAPI.Completed += (o) =>
    {
        Dispatcher.BeginInvoke(() =>
        {
            //顯示地址
            MessageBox.Show(o);
        });
    };
    //指定座標latitude, longitude,記得double輸出要給0.000000詳細的字串轉換
    tGoogleAPI.QueryAddressByLocation(
        pLocation.Latitude.ToString("0.000000"), 
        pLocation.Longitude.ToString("0.000000")); 
}

如果您想知道怎麼把地址或是輸入的一個景點轉換成座標的方式,可參考<Windows Phone 7 - 使用Google Map API將地址轉成座標>。

 

======

希望對大家有所幫助。

 

Dotblogs Tags: