חדשות הערוץ
Rx Challenge #3
בניהו עשת |  06/03/2015

לילה טוב
אסף צוראל |  02/03/2015

Complexity is a Disease and Tests are a Symptom
נועם כפיר |  12/01/2015

SDP conference summary
מיכאל הברמן |  30/12/2014

Events Events Events
עידו פלטו |  03/09/2014

Debug and View Expressions in VS 2013
מנו (עמנואל) כהן ישר |  01/07/2014

Welcome
לידן חכמון |  06/05/2014

TFS API Part 52 – Getting Work Item History
שי רייטן |  30/10/2013

Demos and Slide deck from Sela Open house
רן ואלה |  29/07/2013

HTML5 Graphics
סבסטיאן פדריבה |  09/06/2013

Introduction to Hadoop on Windows Azure
דמיטרי שכטמן |  15/12/2011

M-V-VM or maybe S-V-VM?
אלון לוי |  06/12/2010

 
שידורים קרובים

MVP, MCPD, MCT CTO, Sela USA
What’s New in Windows Phone 8 (6 out of 8)–Location services and maps
אלכס גולש פורסם בתאריך:06/11/2012 07:56:35

Windows Phone 8 brings long awaited updates to location services and brand new map control (with associated services) which is based on Nokia maps.

Location services

So what’s new in location services. First of all – the new WinRT API which is shared with Windows 8. To use location services application must declare the following capability in application manifest:

<Capability Name="ID_CAP_LOCATION" />

The “main” class – Geolocator – belongs to Windows.Devices.Geolocation namespace and enables location tracking in good old “events” way and also new async model as follows:

Geoposition currentPosition = await geoLocator.GetGeopositionAsync();

// or

Geoposition currentPosition = await geoLocator.GetGeopositionAsync(TimeSpan.FromMinutes(1), TimeSpan.FromSeconds(30));

Note: geoLocator is an instance of Geolocator object. Second call limits the results age and awaiting timeout.

The object itself could be activated as follows:

if (geoLocator == null)

{

geoLocator = new Windows.Devices.Geolocation.Geolocator();

geoLocator.DesiredAccuracy = Windows.Devices.Geolocation.PositionAccuracy.High; //Request high accuracy from GPS device

geoLocator.DesiredAccuracyInMeters = 1; //Must have very pcise for walking/running/biking tracking. Could use values of 50-100 for car

geoLocator.ReportInterval = 1000; //1 second between updates usually is needed for constant updates for scenarios such as walking/running/biking tracking.

geoLocator.StatusChanged += geoLoc_StatusChanged; //Subscribe for status changes

geoLocator.PositionChanged += geoLoc_PositionChanged; //Subscribe for continues position changes updates

}

The PositionChanged result brings information such as CivicAddress, Coordinate information with Latitude, Longitude, Speed, Heading, Accuracy, Altitude, etc. fields which crucial for location-aware applications.

Sample code snippet for PositionChanged event:

if (position.CivicAddress != null)

Debug.WriteLine(string.Format("City = {0}, Postal Code = {1}, State = {2}, Country = {3}",

position.CivicAddress.City,

position.CivicAddress.PostalCode,

position.CivicAddress.State,

position.CivicAddress.Country));

 

Dispatcher.BeginInvoke(() =>

{

txtLat.Text = position.Coordinate.Latitude.ToString();

txtLon.Text = position.Coordinate.Longitude.ToString();

txtSpeed.Text = position.Coordinate.Speed.HasValue ? position.Coordinate.Speed.ToString() : "UNKNOWN";

txtHeading.Text = position.Coordinate.Heading.HasValue ? position.Coordinate.Heading.ToString() : "UNKNOWN";

});

Note: this sample code simply outputs the info on screen. While this change in API is interesting, the real power comes with ability to track the location when application is not active – works in background.

Background Execution

As you probably remember, on Windows Phone only one app runs in the foreground – the one which is visible on screen. When user navigates away from an app (either by pssing the Start button or by launching another app) the current app is suspended and may be terminated and tombstoned. In Windows Phone 8, a location-tracking app can continue to run in the background after the user navigates away, as long as the app continues to actively track location. This feature is absolutely must for scenarios such as an app that provides turn-by-turn directions. Let’s see how to enable the background execution.

First of all – to work in background the application must actively track the location: use Geolocator.

Also, to successfully use the Geolocator application must declare location capability (ID_CAP_LOCATION) as described above.

Next, application must require background execution in DefaultTask definition in application manifest as follows:

<DefaultTask Name="_default" NavigationPage="MainPage.xaml">

<BackgroundExecution>

<ExecutionType Name="LocationTracking" />

</BackgroundExecution>

</DefaultTask>

Note: If more than one application requires background execution, only last one will be allowed to work in background. All pvious/other “background executions” will be stopped.

Last, but not least, the application must handle RunningInBackground event which raised when location-tracking application transitions to background. When this event is raised, the application should stop all tasks that are not related to location tracking, including updates to the app’s UI. Subscribing to this even is done through App.xaml:

<shell:PhoneApplicationService

Launching="Application_Launching" Closing="Application_Closing"

Activated="Application_Activated" Deactivated="Application_Deactivated"

RunningInBackground="PhoneApplicationService_RunningInBackground"/>

Handling the event in code:

public static bool isRunningInBackground = false;

 

private void PhoneApplicationService_RunningInBackground(object sender, RunningInBackgroundEventArgs e)

{

isRunningInBackground = true;

 

//Stop all unnecessary processes

}

 

private void Application_Activated(object sender, ActivatedEventArgs e)

{

isRunningInBackground = false;

}

In my simple scenario, the location updates from background execution will be used to update application’s main tile:

FlipTileData ftd = new FlipTileData()

{

Count = updatesCount,

Title = "Position updated",

BackTitle = position.Coordinate.Timestamp.ToLocalTime().ToString(),

BackContent = string.Format("New position is LAT: {0}, LON: {1}",

position.Coordinate.Latitude,

position.Coordinate.Longitude),

WideBackContent = string.Format("New position is LAT: {0}, LON: {1}. Moving with speed of {2} m/s with course of {3}°",

position.Coordinate.Latitude,

position.Coordinate.Longitude,

position.Coordinate.Speed.HasValue ? position.Coordinate.Speed.ToString() : "UNKNOWN",

position.Coordinate.Heading.HasValue ? position.Coordinate.Heading.ToString() : "UNKNOWN"),

};

 

mainTile.Update(ftd);

Those updates produces the following results:

imageimage

Note: please see the video at the end of this post to see the application working in background

Maps

In additional to great improvements to location services described above, Windows Phone 8 switches map component to Nokia maps. The new control could be found in Microsoft.Phone.Maps.Controls namespace (Microsoft.Phone.Maps assembly) and could be instantiated either from XAML or code behind. Sample XAML initialization:

<Controls:Map HorizontalAlignment="Center" VerticalAlignment="Center"

Width="450" Height="400" x:Name="map"

PedestrianFeaturesEnabled="True" LandmarksEnabled="True" ZoomLevel="17"/>

Note: the controls namespace defined in XAML’s header file as follows:

xmlns:Controls="clr-namespace:Microsoft.Phone.Maps.Controls;assembly=Microsoft.Phone.Maps"

Once defined, the map’s properties could be also altered from code behind:

map.Pitch = 40;

Map supports different cartographic modes (Road, Hybrid, Areal, Terrain), color modes (Light, Dark), psenting landmarks/pedestrian features, pitch and rotation:

image

In addition, map supports multiple overlay layers which could be psented over map (car icon on image above) as follows:

BitmapImage bitmapImage = new BitmapImage(new Uri("/Images/car.png", UriKind.Relative));

Image img = new Image();

img.Source = bitmapImage;

 

mapOverlay = new MapOverlay();

mapOverlay.PositionOrigin = new Point(0.5, 0.5);

mapOverlay.Content = img;

mapOverlay.GeoCoordinate = map.Center;

 

MapLayer MyLayer = new MapLayer();

MyLayer.Add(mapOverlay);

map.Layers.Add(MyLayer);

Last, the map provides services, such as GeocodeQuery, ReverseGeocodeQuery and RouteQuery. Latter could be used to calculate (and display on ap) route between two given geo coordinates as follows:

RouteQuery routeQuery = new RouteQuery();

routeQuery.QueryCompleted += routeQuery_QueryCompleted;

 

void routeQuery_QueryCompleted(object sender, QueryCompletedEventArgs<Route> e)

{

Route theRoute = e.Result;

MapRoute calculatedMapRoute = new MapRoute(theRoute);

map.AddRoute(calculatedMapRoute);

}

 

private void btnShowRoute_Click(object sender, RoutedEventArgs e)

{

if (!routeQuery.IsBusy)

{

List<GeoCoordinate> routeCoordinates = new List<GeoCoordinate>();

routeCoordinates.Add(new GeoCoordinate(48.860339, 2.337599)); //Eiffel Tower coordinates

routeCoordinates.Add(new GeoCoordinate(48.8583, 2.2945)); //Louvre coordinates

 

routeQuery.Waypoints = routeCoordinates;

routeQuery.QueryAsync();

 

map.Center = new GeoCoordinate(48.8583, 2.2945); //Center map on first coordinates

}

}

Clicking the “Show Route” button calculates the route and shows it on map:

image

The navigation instructions are also available and could be psented to user as follows:

//...

List<string> legsList = new List<string>();

foreach (RouteLeg leg in MyRoute.Legs)

{

foreach (RouteManeuver routeManeuver in leg.Maneuvers)

{

legsList.Add(routeManeuver.InstructionText);

}

}

 

//lstRouteList is a list showing the legs

lstRouteList.ItemsSource = legsList;

Working sample application video:

Sample location aware application

 

Next time I will blog about in-app-purchases (IAP) and new Windows.ApplicationModel.Store namespace shared with Windows 8.

 

Stay tuned,

Alex