Это третья статья, посвященная выходу Nokia API для разработчиков.
Для пропустивших, вот первые две части:
Nokia Music API
Advanced Camera API
Сегодня мы поговорим об использовании Nokia Maps API.
Map Explorer
Map Explorer — простое приложение на Silverlight, которое демонстрирует, как применять Windows Phone 8 Maps API вместо Bing Maps, которые использовались в Windows Phone 7.
Основная страница приложения содержит кнопки и слайдеры, позволяющие изменять настройки карты (режим просмотра карты, наклон и направление). Более детальные настройки камеры доступны в меню настроек приложения. Основной картографический функционал, который демонстрирует приложение — это получение и отображение текущего положения телефона на карте, поиск по ключевым словам, прорисовка маршрута и направления от заданной точки до пункта назначения.
Дизайн
Приложение написано так, чтобы продемонстрировать возможности управляющих элементов Windows Phone 8 в одном окне, таких как поиск адреса, расчет маршрута до интересующей точки, позиционирование на карте. Сохранение всех управляющих элементов на экране позволяет продемонстрировать моментальный визуальный отклик при изменении параметров. При запуске приложение запрашивает доступ к данным местоположения пользователя. Рекомендуется дать приложению доступ к ним, так как ряд функций основывается на данных о местоположении. Однажды получив разрешение, приложение больше не будет выдавать запрос.
После получения ответа на запрос приложение открывается на стартовой странице. Она содержит элементы для непосредственного управления параметрами карты в картографическом режиме (дорога, обзор с воздуха, гибрид, местность), в режиме наклона (настраиваемый угол обзора карты) и направления (позволяет разворачивать карту в направлении заданного маршрута). Центрирование и приближение осуществляются перетаскиванием или «щипком».
Доступ к функционалу Windows Phone 8, завязанному на данные карты, возможен с помощью кнопок в меню приложения. Кнопка «Поиск» открывает форму ввода данных. Если найден один или более объектов, отвечающих условиям поиска, карта сдвигается при помощи анимации к первому объекту. Кнопка «Маршрут» запускает функционал построения маршрута и требует ввести пункт назначения. Заданное направление может быть включено открытием меню и выбором пункта меню «Directions On», режимов поездки два на выбор: «За рулем» и «Пешком».
Кнопка «Найти меня» запускает определение координат пользователя. Когда данные получены, карта с анимацией перемещается к точке текущего местоположения. Если при запуске приложения разрешения на определение координат не было получено, то запрос будет показан повторно. Разрешение на определение координат запустит процесс поиска.
Дополнительные настройки находятся в меню приложения, где можно включить отображение таких параметров, как достопримечательности, особенности пешеходных маршрутов и направление. Здесь же можно выбрать режим цвета карты: темный и светлый.
Обзор архитектуры
Разбор архитектуры
Интерфейс пользователя
Интерфейс пользователя состоит из MainPage и информационной AboutPage — производных от PhoneApplicationPage. MainPage содержит карту и весь картографический функционал этого приложения.
Windows Phone Location API
Windows Phone Location API используется в пространстве имен Windows.Devices.Geolocation для определения текущего местоположения. Приложение должно иметь ID_CAP_LOCATION, указанный в файле WMAppManifest.xml, чтобы использовать сервисы определения местоположения.
Maps API
Новые Windows Phone 8 Maps API предлагают действующие элементы управления картой (Microsoft.Phone.Maps.Controls) и соответствующие картографические сервисы (Microsoft.Phone.Maps.Services). Для использования Maps API приложение должно иметь ID_CAP_LOCATION, указанный в файле WMAppManifest.xml.
Прямое взаимодействие с настройками карт
Прямое взаимодействие с настройками управляющих элементов карт осуществляется весьма просто, что наглядно демонстрирует следующий пример. Слайдер для контроля приближения карты описан в файле MainPage.xaml.
<Slider x:Name="PitchSlider" ... Minimum="0" Maximum="70" Value="0" ValueChanged="PitchValueChanged"/>
Затем обработчик событий для события ValueChanged выполняется в файле MainPage.xaml.cs.
using Microsoft.Phone.Maps.Controls;
...
public partial class MainPage : PhoneApplicationPage
{
...
private void PitchValueChanged(object sender, EventArgs e)
{
if (PitchSlider != null)
{
MyMap.Pitch = PitchSlider.Value;
}
}
...
}
Получение координат текущего местоположения
Получить координаты текущего местоположения довольно просто, используя Геолокатор асинхронно. Местоположение может определяться не в конкретной точке, а приблизительно, это может быть отображено в пользовательском интерфейсе. Для этого координаты представляются в виде полупрозрачного круга с радиусом, зависящим от точности определения, поверх карты.
using System.Device.Location;
using Windows.Devices.Geolocation;
public partial class MainPage : PhoneApplicationPage
{
...
private GeoCoordinate MyCoordinate = null;
private double _accuracy = 0.0;
...
private async void GetCurrentCoordinate()
{
...
Geolocator geolocator = new Geolocator();
geolocator.DesiredAccuracy = PositionAccuracy.High;
try
{
Geoposition currentPosition = await geolocator.GetGeopositionAsync(TimeSpan.FromMinutes(1),
TimeSpan.FromSeconds(10));
_accuracy = currentPosition.Coordinate.Accuracy;
...
Dispatcher.BeginInvoke(() =>
{
MyCoordinate = new GeoCoordinate(currentPosition.Coordinate.Latitude, currentPosition.Coordinate.Longitude);
...
});
}
catch (Exception ex)
{
// Не удается определить местоположение – определение местоположения отключено в настройках
MessageBox.Show("Current location cannot be obtained. Check that location service is turned on in phone settings.");
}
...
}
...
}
Получение информации о местоположении
Запросить информацию о конкретном местоположении можно используя ReverseGeocodeQuery. В приложении Map Explorer ReverseGeocodeQuery запускается при касании метки на карте. Геокоординаты каждой метки сохраняются в настройке Tag полигона в момент создания метки.
using using Microsoft.Phone.Maps.Services;
public partial class MainPage : PhoneApplicationPage
{
...
private ReverseGeocodeQuery MyReverseGeocodeQuery = null;
...
private void Marker_Click(object sender, EventArgs e)
{
Polygon p = (Polygon)sender;
GeoCoordinate geoCoordinate = (GeoCoordinate)p.Tag;
MyReverseGeocodeQuery = new ReverseGeocodeQuery();
MyReverseGeocodeQuery.GeoCoordinate = new GeoCoordinate(geoCoordinate.Latitude, geoCoordinate.Longitude);
MyReverseGeocodeQuery.QueryCompleted += ReverseGeocodeQuery_QueryCompleted;
MyReverseGeocodeQuery.QueryAsync();
}
private void ReverseGeocodeQuery_QueryCompleted(object sender, QueryCompletedEventArgs<IList<MapLocation>> e)
{
if (e.Error == null)
{
if (e.Result.Count > 0)
{
MapAddress address = e.Result[0].Information.Address;
String msgBoxText = "";
...
if (address.Country.Length > 0) msgBoxText += "n" + address.Country;
MessageBox.Show(msgBoxText, AppResources.ApplicationTitle, MessageBoxButton.OK);
}
...
}
}
...
}
Поиск по ключевым словам на карте
GeocodeQuery может использоваться для поиска местоположения заданного запроса, например названия города или улицы. Обработчик событий GeocodeQuery_QueryCompleted вызывается и при поиске по ключевому слову, и при построении маршрута. Объяснение части, касающейся маршрута, приведено ниже. Результат GeocodeQuery представляет собой список, соответствующий SearchTerm запроса. Каждый MapLocation имеет GeoCoordinate для позиционирования местоположения на карте, равно как и детальную LocationInformation с именем, описанием и MapAdress локации.
using Microsoft.Phone.Maps.Services;
public partial class MainPage : PhoneApplicationPage
{
...
private GeoCoordinate MyCoordinate = null;
private List<GeoCoordinate> MyCoordinates = new List<GeoCoordinate>();
private GeocodeQuery MyGeocodeQuery = null;
private bool _isRouteSearch = false; // True если использован поиск маршрута, иначе false
...
private void SearchForTerm(String searchTerm)
{
...
MyGeocodeQuery = new GeocodeQuery();
MyGeocodeQuery.SearchTerm = searchTerm;
MyGeocodeQuery.GeoCoordinate = MyCoordinate == null ? new GeoCoordinate(0, 0) : MyCoordinate;
MyGeocodeQuery.QueryCompleted += GeocodeQuery_QueryCompleted;
MyGeocodeQuery.QueryAsync();
}
private void GeocodeQuery_QueryCompleted(object sender, QueryCompletedEventArgs<IList<MapLocation>> e)
{
...
if (e.Error == null)
{
if (e.Result.Count > 0)
{
if (_isRouteSearch) // Запрос сделан для определения конечной точки маршрута
{
...
}
else // Запрос сделан для поиска по ключевому слову
{
// Добавляет результаты в MyCoordinates для отображения маркеров на карте.
for (int i = 0; i < e.Result.Count; i++)
{
MyCoordinates.Add(e.Result[i].GeoCoordinate);
}
...
}
}
else
{
MessageBox.Show("No match found. Narrow your search e.g. Seattle WA.");
}
}
...
}
Отображение маршрута от текущей точки до пункта назначения
RouteQuery может использоваться для получения маршрута от одной географической точки до другой. Запрос запускается из обработчика событий GeocodeQuery_QueryCompleted в процессе поиска. Текущий пример использует только две точки для построения маршрута — начальную и конечную. Результатом RouteQuery является Route.MapRoute, представляющий собой виуализацию, которую легко применить к элементам управления картой. Route разделяется на RouteLegs между двумя точками пути. Каждый RoutLeg имеет набор RouteManeuvers, представляющих варианты маневров, которые могут быть предприняты на отрезке пути.
public partial class MainPage : PhoneApplicationPage
{
...
private GeoCoordinate MyCoordinate = null;
private List<GeoCoordinate> MyCoordinates = new List<GeoCoordinate>();
private RouteQuery MyRouteQuery = null;
private Route MyRoute = null;
private MapRoute MyMapRoute = null;
private bool _isRouteSearch = false; // True если использован поиск маршрута, иначе false
private TravelMode _travelMode = TravelMode.Driving; // Travel mode использован для построения маршрута
....
private void GeocodeQuery_QueryCompleted(object sender, QueryCompletedEventArgs<IList<MapLocation>> e)
{
...
if (e.Error == null)
{
if (e.Result.Count > 0)
{
if (_isRouteSearch) // Запрос сделан для нахождения конечной точки маршрута
{
// Сохраняет точку назначения для отображения маркеров на карте
MyCoordinates.Add(e.Result[0].GeoCoordinate);
// Маршрут от начальной точки к первому результату поиска
List<GeoCoordinate> routeCoordinates = new List<GeoCoordinate>();
routeCoordinates.Add(MyCoordinate);
routeCoordinates.Add(e.Result[0].GeoCoordinate);
CalculateRoute(routeCoordinates);
}
else // Запрос сделан путем поиска по ключевому слову
{
...
}
}
...
}
...
}
private void CalculateRoute(List<GeoCoordinate> route)
{
...
MyRouteQuery = new RouteQuery();
MyRouteQuery.TravelMode = _travelMode;
MyRouteQuery.Waypoints = route;
MyRouteQuery.QueryCompleted += RouteQuery_QueryCompleted;
MyRouteQuery.QueryAsync();
}
private void RouteQuery_QueryCompleted(object sender, QueryCompletedEventArgs<Route> e)
{
...
if (e.Error == null)
{
MyRoute = e.Result;
MyMapRoute = new MapRoute(MyRoute);
MyMap.AddRoute(MyMapRoute);
// Обновляет информацию о маршруте и направлениях
List<string> routeInstructions = new List<string>();
foreach (RouteLeg leg in MyRoute.Legs)
{
for (int i = 0; i < leg.Maneuvers.Count; i++)
{
RouteManeuver maneuver = leg.Maneuvers[i];
string instructionText = maneuver.InstructionText;
...
routeInstructions.Add(instructionText);
}
}
...
}
...
}
}
Дополнительная информация
Для более глубокого изучения информации об элементах управления картой и дополнительных сервисах можно ознакомиться с Guide to the Maps.
Загрузки
Проект Map Explorer v1.0
Map Explorer application binary file v1.0
Это приложение расположено на Nokia Developer Projects, где всегда можно посмотреть последнюю активность, сообщить об ошибке, просмотреть код, задать вопросы или даже внести свой вклад в проект.
Автор: nokiaman