本文章是由機器翻譯。

Windows Phone 8.1

Windows Phone 8.1 的定位服務

Keith Pijanowski

下載代碼示例

每一代的 Windows Phone 帶來改進的映射功能,和 Windows Phone 8.1,與採用Visual Studio2013年新地圖控制項更新 3,也不例外。如果你需要的只是一個簡單的地圖,集中在一個指定的位置,你可以完成此與只需要幾行代碼的新地圖控制。但是,如果您需要對使用者交互作出回應,自訂控制項的外觀或計算路線,您還可以使用新的地圖控制項和映射服務 API 對於這些更複雜的情況。

這篇文章將涵蓋新的 Windows Phone 8.1 地圖控制項和映射服務 Api。我要開始顯示基本的地圖顯示功能,然後再看看顯示如何將圖釘放在地圖上位於指定位址的更多高級功能。我還會展示你如何 XAML 將控制項放在地圖控制項,以及如何獲得 GPS 定位 (和位址),對應于地圖控制項上的特定點。這是有用的如果您想要允許使用者觸摸感興趣的位置,然後確定 GPS 定位和街道位址。最後,我將演示如何計算開車和走路的方向。

好的姊妹篇,我會掩護的材料是 2014 年 9 月的文章,"創建一個位置感知應用程式與地理圍牆,"被托尼冠軍。一個地點座標是周圍可以與 Windows 註冊一個 GPS 定位指定的區域。一旦註冊了該區域,應用程式可以接收通知,當設備進入或離開該區域。地理圍牆也是新的 Windows Phone 8.1。如果您要構建的應用程式使用地理圍牆,請考慮使用地圖控制項以允許使用者指定 geofences,並表明他們現有的 geofences。

在撰寫本文時,是手機的為每個風味和平板電腦平臺的不同地圖控制項:

  • Windows Phone Silverlight 8.0/8.1 應用程式: Microsoft.Phone.Maps.Controls.Map
  • Windows 應用商店 8.x 版應用程式: Bing.Maps.Map
  • Windows Phone 8.1 運行時應用程式: Windows.UI.Xaml.Controls.Maps

這篇文章的重點是新地圖控制項,可以為 Windows Phone 8.1 運行時編寫的應用程式中使用的映射服務。

使用者入門

驗證您的應用程式您的 Windows Phone 應用程式需要每次使用地圖控制項或 Windows.Services.Maps 命名空間中的映射服務進行身份驗證。要驗證您的應用程式,您需要地圖服務 ApplicationID 和地圖服務的身份驗證權杖,這兩個國家可以從您的開發人員儀表板在 Windows Phone 開發人員中心中檢索。你會發現從 MSDN 庫文章在得到 ApplicationID 和 AuthenticationToken 的分步 bit.ly/1y78M2F

一旦你有,你需要將 ApplicationID 放在您的應用程式的 Package.appxmanifest 檔中。執行此操作的說明也在 MSDN 庫文章。您也將在您將看到本文中稍後在代碼中,使用地圖服務的身份驗證權杖。

功能許多這篇文章中的示例使用使用者當前的位置和地圖控制項可能需要使用互聯網。因此,互聯網和位置的能力應宣佈在應用程式清單檔中所示圖 1。然而,映射服務還沒有互聯網連接時工作地圖下載供離線使用。下載地圖的詳細資訊,請參閱"如何到下載和更新離線映射 (XAML)"在 bit.ly/1nXBOrS

宣佈互聯網和定位功能
圖 1 宣佈互聯網和定位功能

顯示地圖

顯示一個簡單的地圖向頁中添加地圖控制項是那樣輕鬆加入任何其他控制項。您可以拖動控制項從Visual Studio工具箱拖到您的頁上,或您可以輸入 XAML,如下所示:

<Maps:MapControl
  x:Name="myMapControl"
  MapServiceToken="Place your token here."
  Height="200" Width="300"
  HorizontalAlignment="Center"
  Margin="0,0,0,12"
  />

請注意 MapServiceToken 屬性。此屬性必須有地圖服務身份驗證權杖,被分配到您的應用程式開發人員儀表板的 Windows Phone 開發人員中心中的價值。另外,請注意您可以定位地圖控制項像其他任何控制項。地圖控制項並不需要佔據整個螢幕。一個小地圖縮放到特定位置可以使有效視覺上包含特定位置資訊的網頁。另一方面,地圖放大的時候 (或者可能縮小由使用者) 將需要額外的房地產。這種映射,請考慮使用整頁。

前面的 XAML 將產生枯燥無味的結果,如果被放在一個應用程式並運行。此控制項將顯示地圖完全縮小。因此,使用地圖控制項的下一步是確定某個特定的位置為中心點的地圖,以及縮放級別。

下面的代碼首先計算該使用者當前的位置,然後設置該位置到地圖的中心屬性。它也將縮放級別設置為 15。 縮放級別的最小值是 1,顯示地圖完全縮小 — — 並在您的地圖控制項中顯示半個地球。縮放級別的最大值是 20,可以縮放地圖控制項特定的街道位址:

Geolocator geolocator = new Geolocator();
Geoposition geoposition = null;
try
{
  geoposition = await geolocator.GetGeopositionAsync();
}
catch (Exception ex)
{
  // Handle errors like unauthorized access to location
  // services or no Internet access.
}
myMapControl.Center = geoposition.Coordinate.Point;
myMapControl.ZoomLevel = 15;

將圖像添加到地圖控制項如果您想要標記您的地圖上的特定位置,您可以添加到地圖控制項的標題圖像。中的代碼圖 2 將指向該設備的當前的位置,將從專案的資源資料夾中的圖像添加到地圖控制項。

圖 2 添加到地圖控制項的自訂圖像

Geolocator geolocator = new Geolocator();
Geoposition geoposition = null;
try
{
  geoposition = await geolocator.GetGeopositionAsync();
}
catch (Exception ex)
{
  // Handle errors like unauthorized access to location services or no Internet access.
}
MapIcon mapIcon = new MapIcon();
mapIcon.Image = RandomAccessStreamReference.CreateFromUri(
  new Uri("ms-appx:///Assets/PinkPushPin.png"));
mapIcon.NormalizedAnchorPoint = new Point(0.25, 0.9);
mapIcon.Location = geoposition.Coordinate.Point;
mapIcon.Title = "You are here";
myMapControl.MapElements.Add(mapIcon);

要將圖像添加到您的地圖控制項,首先創建一個 MapIcon 物件,然後將其位置屬性設置為 Geopoint,表示感興趣在你的地圖上的位置。中的代碼圖 2 使用使用者當前的位置。Title 屬性是將圖像添加到地圖控制項上方顯示的文本。

若要指定圖像,將使用 RandomAccessStreamReference.CreateFromUri 方法的 MapIcon 的圖像屬性設置。這是 Windows.Storage.Streams 命名空間中的靜態方法。圖像應該是大約 50 x 50 圖元 ; 如果它是更大,它將被縮減。

當您的目的是圖像的指向一個特定的位置時,它是圖像的最佳的做法是圖像的使用 MapIcon 的 NormalizedAnchorPoint 屬性。此屬性允許您指示在您將放置超過指定 Geopoint 的圖像內點。如果您的圖像是 pin 的一個圖釘,這將是 pin 的尖端。如果您正在使用一個箭頭圖像,這一點將箭頭的提示。NormalizedAnchorPoint 屬性的預設值是使用的值創建一個 Point 物件 (0,0),其中表示圖像的左上角。圖像的右下角是 (1,1)。此坐標系描繪在圖 3 與幾個採樣點。

座標系統用於 NormalizedAnchorPoint 屬性
圖 3 座標系統用於 NormalizedAnchorPoint 屬性

如果用作地圖圖示的圖像包含一個指標,NormalizedAnchorPoint 屬性設置不正確,地圖圖示將指向錯誤的位置,在你的地圖上。如果你的形象僅僅是一個點或小圓圈,您將使用一個值 (0.5,0.5),這是中心的形象。

如果你不指定圖像,個地圖控制已顯示的預設圖像圖 4,將使用。

預設地圖圖示
圖 4 預設地圖圖示

正如你所看到的預設的 MapIcon 圖像具有指標位於底部中心的形象。因此,規範­AnchorPoint 屬性需要設置為 (0.5、 1.0)。

最後的細節需要注意有關代碼是 MapIcon 物件添加到地圖的 MapElements 集合中,所以可以將多個 MapIcon 添加到您的地圖,如果你想。

那裡是地圖圖示和標題將顯示沒有保證。如果它將掩蓋其他元素或在地圖上的標籤,它可能被隱藏。地圖縮小 (縮放級別減少) 和地圖控制項進行調整以適應更多的資訊,這是尤其如此。

中的代碼圖 2 顯示在地圖圖 5,假設你正在看一場棒球比賽在芬威公園。

地圖控制項顯示芬威公園在波士頓,麻塞諸塞州
圖 5 地圖控制項顯示芬威公園在波士頓,麻塞諸塞州

將控制項添加到地圖控制項將 XAML 添加到地圖控制項的控制項是類似于添加圖像。下面的代碼創建一個橢圓、 大小轉一圈、 將其添加到地圖控制項,和中心地理座標:

// Create a circle
Windows.UI.Xaml.Shapes.Ellipse fence = 
  new Windows.UI.Xaml.Shapes.Ellipse();
fence.Width = 30;
fence.Height = 30;
fence.Stroke = new SolidColorBrush(Colors.DarkOrange);
fence.StrokeThickness = 2;
MapControl.SetLocation(fence, geoposition.Coordinate.Point);
MapControl.SetNormalizedAnchorPoint(fence, new Point(0.5, 0.5));
myMapControl.Children.Add(fence);

請注意必須使用地圖控制項的靜態函數 SetLocation 將附加到橢圓物件的地理座標。同樣,SetNormalizedAnchorPoint 函數用於附加的正常化錨點屬性。

從 UIElement 或 MapItemsControl 繼承的任何控制項可以添加到地圖控制項使用這些技術。

獲取位置

地圖控制項的心是 BasicGeoposition 物件,它可以表示使用只是三個數字的地球上的每個位置:緯度、 經度和海拔高度。不只是這是劃分全球範圍內的有效途徑,也是精確。每個位置都有其自身獨特的緯度、 經度和海拔高度。沒有兩個的位置將有相同的組合。

不幸的是,您的應用程式去介面與人類,人類不喜歡表示以純數位值的位置。因此,全球範圍內被劃分成各大洲,國家在各大洲,國家,在區域內的城鎮,城鎮內的街道地區 (或國家) 內。而大陸的名稱、 國家名稱和郵政代碼是獨一無二的地區有時可以包含具有相同名稱的兩個或多個城鎮。此外,一個小鎮可能有兩個或多個具有相同名稱的街道。底線是可能的位址必須與兩個或更多位置相混淆。當處理 (離的國家名稱、 郵遞區號或鎮) 位址不完整表示形式,這是尤其如此。

因此,如果您的應用程式要拿出更多的使用者當前的位置,可以直接從設備檢索,你會需要以前描述的數值和已命名的系統之間進行轉換。將位址轉換到地理位置的過程稱為地理編碼。將地理位置轉換為人類可讀位址的過程被稱為反向地理編碼。

將位址轉換為地理位置 (地理) 地理編碼位址需要映射的使用服務 Api — — 在 Windows.Services.Maps 命名空間中找到的類的集合。若要使用這些 Api,您需要設置您的身份驗證權杖在 ServiceToken MapService 類的靜態屬性。下面的程式碼演示如何做到這一點 (這篇文章的其餘部分將假定下面這行代碼是在 OnLaunched 事件中應用程式):

MapService.ServiceToken = "Place your token here";

一旦設置的身份驗證權杖,您可以使用 FindLocationsAsync 靜態函數,在 MapLocationFinder 類中發現。下面介紹了如何使用 FindLocationsAsync 函數:

Geolocator geolocator = new Geolocator();
Geoposition currentPosition = await geolocator.GetGeopositionAsync();

MapLocationFinderResult result = await MapLocationFinder.FindLocationsAsync(
  address, currentPosition.Coordinate.Point, 5);

FindLocationsAsync 函數的第一個參數是一個位址的字串表示形式。任何字串可能會傳遞給此函數。後端映射服務,FindLocationsAsync 函數進行通信,會盡其所能,找到一個匹配的位置。第二個參數被稱為參考點,表示應開始搜索的地理位置。此參數有時被稱為一個暗示。如果使用得當可大幅度提高返回的位置與速度,他們計算的關聯性。例如,如果您知道使用者做一個本地搜索,然後通過在使用者的當前位置作為參考點。但是,如果您知道使用者規劃她的假期,通過在她的酒店的位置。最後一個參數是將返回的地點的最大數目。

FindLocationsAsync 函數的傳回值是一個 MapLocationFinderResult 類型的物件。如果搜索是成功還是失敗,它會告訴你的。如果搜索成功,MapLocation­FinderResult 物件將包含一個 MapLocation 物件的集合。中的代碼圖 6 檢查成功的搜索,並如果它是成功的地方到 ListView 控制項集合,以便可以向使用者顯示所有匹配的位置。MapLocation 物件包含人類可讀的位址資訊和可以使用的個地圖控制的地理資訊。中的代碼圖 6 可以很容易將轉換為地圖控制項上顯示圖釘。

圖 6 檢索位置搜索的結果

if (result.Status == MapLocationFinderStatus.Success)
{
  List<string> locations = new List<string>();
  foreach (MapLocation mapLocation in result.Locations)
  {
    // create a display string of the map location
    string display = mapLocation.Address.StreetNumber + " " +
      mapLocation.Address.Street + Environment.NewLine +
      mapLocation.Address.Town + ", " +
      mapLocation.Address.RegionCode + "  " +
      mapLocation.Address.PostCode + Environment.NewLine +
      mapLocation.Address.CountryCode;
    // Add the display string to the location list.
    locations.Add(display);
  }
  // Bind the location list to the ListView control.
  lvLocations.ItemsSource = locations;
}
else
{
  // Tell the user to try again.
}

地理位置轉換的位址 (反向地理編碼) 映射應用程式可以提供的另一個有用特性就是能夠從地圖控制項感動地區獲得一個人類可讀的位址。此功能的代碼,你首先需要去感動使用者控制項的位置的方式。這可以通過使用地圖控制項的 MapTapped 事件。地圖控制項也具有一個螺絲的事件,在地圖控制項的 XAML 子被觸碰時被激發。地圖控制項的任何直接的自來水經過 MapTapped 事件。中的代碼圖 7 演示一種實現的 MapTapped 事件,在 TextBlock 控制項中顯示的抽頭位置的位址。

圖 7 找到一個抽頭位置在地圖上的位址控制

private async void myMapControl_MapTapped(MapControl sender, 
  MapInputEventArgs args)
{
  // Find the address of the tapped location.
  MapLocationFinderResult result =
    await MapLocationFinder.FindLocationsAtAsync(args.Location);
  if (result.Status == MapLocationFinderStatus.Success)
  {
    if (result.Locations.Count > 0)
    {
      string display = result.Locations[0].Address.StreetNumber + " " +
        result.Locations[0].Address.Street;
      tbAddress.Text = display;
    }
  }
}

有幾個細節值得在此實現中的 MapTapped 事件呼喚。第一,已與抽頭位置相關聯的 geopoint 是通過 args 傳遞到此事件。位置。 FindLocationsAtAsync 函數可以使用此 geopoint 獲取一個人類可讀的位址。此函數是靜態函數在 MapLocationFinder 類中,是映射服務 API (Windows.Services.Maps 命名空間) 的一部分。此函數返回一個 MapLocationFinderResult 物件,包含一個狀態屬性和一個 MapLocation 物件的集合。即使傳回值允許為 MapLocation 物件的集合,通常會有只有一個 MapLocation 物件。然而,可能有一高層建築在某個地方有兩個或更多的街道位址與它關聯的世界。如果使用者按一下大場或湖,仍然會傳回值。如果附近沒有實際的街道位址,MapLocation 物件將包含只區域、 國家和郵遞區號。

路線

映射服務可以計算從給定的起始點到給定的終結點路線。地圖控制項本身是能夠顯示的路線,可以作為駕駛路線或步行路線計算。

駕車路線顧名思義,駕駛路線為了要趕在一些車輛不會走錯了路,一條單行道,必須遵守所有其他規則的道路。中的代碼圖 8 計算行車路線從紐約城的中央車站去中央公園。

圖 8 計算開車路線

// Start at Grand Central Station.
BasicGeoposition startLocation = new BasicGeoposition();
startLocation.Latitude = 40.7517;
startLocation.Longitude = -073.9766;
Geopoint startPoint = new Geopoint(startLocation);
// End at Central Park.
BasicGeoposition endLocation = new BasicGeoposition();
endLocation.Latitude = 40.7669;
endLocation.Longitude = -073.9790;
Geopoint endPoint = new Geopoint(endLocation);
// Get the route between the points.
MapRouteFinderResult routeResult =
await MapRouteFinder.GetDrivingRouteAsync(
  startPoint,
  endPoint,
  MapRouteOptimization.Time,
  MapRouteRestrictions.None,
  290);

該代碼是相當簡單的。靜態函數 MapRouteFinder.GetDrivingRouteAsync 傳遞起點、 終點、 優化參數 (稍後說明) 和一個參數,指定限制 (也稍後介紹)。第五也是最後的參數是可選的標題,它指定當前方向­的使用者在 com 中­通過度 (0 度代表北,180 度代表南,等等)。路線計算使用者開車時,這非常有用。當使用標題參數時,路線是基於計算使用者的當前方向的旅行。路線第一幾雙腿將包含使用者到達最佳可能路線,這是特別有用,使用者可能會在單程路上的城市內的軍事演習朝著錯誤的方向前進。更改標題為在代碼中的 135 圖 8 將導致路由計算等,它包含一個法律的方式來改變方向。

一旦你有一個結果從 MapRouteFinder.GetDrivingRoute­非同步功能,您需要檢查它。如果成功檢索到一條路線,然後作為轉由轉向指示顯示。路線也可以直觀地顯示在地圖控制項。中的代碼圖 9 作為轉由轉向指示顯示從中央車站到中央公園的路線。

圖 9 遍歷路由的雙腿和路線機動

if (routeResult.Status == MapRouteFinderStatus.Success)
{
  // Use the route to initialize a MapRouteView.
  MapRouteView viewOfRoute = new MapRouteView(routeResult.Route);
  viewOfRoute.RouteColor = Colors.Blue;
  viewOfRoute.OutlineColor = Colors.Blue;
  // Add the new MapRouteView to the Routes collection
  // of the MapControl.
  MapwithDrivingRoute.Routes.Add(viewOfRoute);
  // Fit the MapControl to the route.
  await MapwithDrivingRoute.TrySetViewBoundsAsync(
    routeResult.Route.BoundingBox,
    null,
    Windows.UI.Xaml.Controls.Maps.MapAnimationKind.Bow);
}

MapRoute 物件包含指示要遍歷該路線及路線以米為單位的長度應採取多長時間的摘要資訊。MapRoute 物件通過使用 MapRouteLeg 物件和 MapRouteManeuver 物件組織路由資訊。MapRoute 包含一個或多個 MapRouteLeg 物件,每個 MapRouteLeg 包含一個或多個 MapRouteManeuver 物件。將向使用者顯示的資訊是 MapRouteManeuver 物件中。MapRouteManeuver 物件包含往往­傳統指令退出資訊 (如果適用)、 機動和機動通知 (如果適用) 的長度。Kind 屬性也是非常有用的。示例值包括左的轉彎、 右轉彎,等等。它可以用於將圖像與每個機動相關聯。Kind 屬性的可能值的完整清單可以發現在 bit.ly/1nXOyi7圖 10 顯示在應用程式中這些方向的將外觀。

的轉由轉動方向行駛的路線
圖 10 的轉由轉動方向行駛的路線

路線也可以顯示圖形在地圖控制項內 (見圖 11)。

圖 11 顯示路線,直觀地在地圖控制項中

// Display summary info about the route.
tbTurnByTurn.Inlines.Add(new Run()
{
  Text = "Total estimated time (minutes) = "
    + routeResult.Route.EstimatedDuration.TotalMinutes.ToString("F1")
});
tbTurnByTurn.Inlines.Add(new LineBreak());
tbTurnByTurn.Inlines.Add(new Run()
{
  Text = "Total length (kilometers) = "
    + (routeResult.Route.LengthInMeters / 1000).ToString("F1")
});
tbTurnByTurn.Inlines.Add(new LineBreak());
// Display the directions.
tbTurnByTurn.Inlines.Add(new Run()
{
  Text = "DIRECTIONS"
});
tbTurnByTurn.Inlines.Add(new LineBreak());
// Loop through the legs and maneuvers.
int legCount = 0;
foreach (MapRouteLeg leg in routeResult.Route.Legs)
{
  foreach (MapRouteManeuver maneuver in leg.Maneuvers)
  {
    tbTurnByTurn.Inlines.Add(new Run()
    {
      Text = maneuver.InstructionText
    });
    tbTurnByTurn.Inlines.Add(new LineBreak());
  }
}

在地圖控制項中顯示一條路線,首先需要創建一個視圖使用 MapRouteView 類的路線。一旦你有你可以將其添加到路由集合地圖控制項的視圖。最後,地圖控制項的 TrySetViewBoundsAsync 函數將地圖調整控制項大小這樣的整條路線是可見的。此函數甚至還帶有動畫參數,可提供一種視覺效果,如被重繪地圖控制項以適應路線。圖 12 顯示這會像應用程式中。

行駛的路線在地圖控制項中
圖 12 行駛的路線在地圖控制項中

路由優化駕駛路線可以優化時間、 距離和交通方面。MapRouteOptimization 枚舉提供的值在圖 13 優化計算的一條路線。

圖 13 MapRouteOptimization 枚舉

隨時間變化 將優化路線,這樣它可以在最短的時間距離和速度限制為每個機動路線覆蓋。
距離 路由將優化這樣它可以覆蓋在給每個機動的距離最短的距離。
TimeWithTraffic 將優化路線,這樣它可以在最短的時間距離,覆蓋時速限制,以及當前的交通條件,為每個機動路線。

 

路由限制駕駛路線還可以計算有限制,如"沒有公路"或"不收費的公路"。MapRoute­限制枚舉提供中顯示的值圖 14 限制的駕駛路線計算。

圖 14 MapRouteRestrictions 枚舉

沒有限制應用到的一條路線計算。路徑可以包含包括公路、 隧道、 渡輪、 收費公路和土路的演習。
公路 路由將不會包含任何機動的飛機,在一條公路上行走。
運輸量 路由將不包含任何在收費公路上行走的演習。
渡輪 路由將不包含任何需要使用的一艘渡輪的演習。
隧道 路由將不會包含任何機動的飛機,穿過一條隧道。
DirtRoads 路由將不會包含任何機動的飛機,在一條土路上行走。

 

這些值可以進行邏輯組合。例如,下面的代碼是可防止使用高速公路和收費道路的限制:

MapRouteFinderResult routeResult =
  await MapRouteFinder.GetDrivingRouteAsync(
  startPoint,
  endPoint,
  MapRouteOptimization.Time,
  MapRouteRestrictions.Highways || MapRouteRestrictions.TollRoads);

行走的路線計算行走的路線非常相似的計算的駕駛路線。下面的代碼將計算基於相同的結束點駕駛路線如行走路線:

// Get the route between the points.
MapRouteFinderResult routeResult =
  await MapRouteFinder.GetWalkingRouteAsync(
  startPoint,
  endPoint);

MapRouteFinder.GetWalkingRouteAsync 用於執行此計算的靜態函數。不同計算的駕駛路線的相應函數,此函數具有允許優化、 限制或當前標題沒有重載。這些屬性不影響行走路線計算,因為速度限制和交通情況並不是有關。此外,可以輕鬆地更改當前標題列。在最短的距離計算的行走路線。在圖像圖 15圖 16 顯示行走的路線,從中央車站到中央公園。

的轉由轉動方向行走的路線
圖 15 的轉由轉動方向行走的路線

行走路線地圖控制項所示
圖 16 行走路線地圖控制項所示

總結

在這篇文章我展示如何使用新的地圖控制項的 Windows Phone 8.1,包括基本的地圖顯示、 添加圖像和添加控制項。我也介紹了基礎測繪服務 API,並看了看地理編碼、 反向地理編碼和路由計算。

應考慮到的映射相關的其他主題的數目:貼面影像填滿、 資料繫結和管理離線地圖。你可以找到有關這些主題的 Windows 開發人員中心資訊 (bit.ly/X7S7ei)。


KeithPijanowski 在軟體行業有 20 多年的經驗。他曾為創業公司和大公司在從編寫代碼對商業發展的角色。目前,他正在為自己作為一名獨立顧問。Pijanowski 住在紐約市區,但永遠不會有為紐約體育隊歡呼。聯繫到他在 keithpij@msn.comtwitter.com/keithpij

感謝以下的微軟技術專家對本文的審閱:邁克奧馬利
邁克奧馬利是高級專案經理,在微軟的作業系統。他一直在 Mmap-相關開發商微軟三年來的經驗和在生成位置感知應用程式開發提出了每年。