Блог Сергея Байдачного

Мой блог о технологиях

Использование карт (часть 1)

leave a comment »

 

Итак, разобравшись с определением местоположения, переходим к картам. Для многих разработчиков карты являются больной темой, так как во многих приложениях они являются желательным компонентом, но в Windows Phone 7 с ними было ряд существенных проблем. Во-первых, карты были исключительно в онлайн, что не позволяло строить приложения, подключающиеся к сети только тогда, когда это возможно сделать по Wi-Fi. Во-вторых, для прорисовки карт использовалась служба Bing Maps, которая хорошо работает в США и некоторых странах, но часто бесполезна для украинского пользователя. Все это сводило на нет реализацию многих сценариев по работе с картами.

В Windows Phone 8 ситуация с картами коренным образом изменилась. Карты теперь доступны в офлайн режиме, давай пользователю возможность загрузить карты для выбранных стран один раз, находясь в зоне подключения к Wi-Fi. Кроме того, все модели телефонов будут использовать карты от Nokia. А ведь именно Nokia является одним из крупнейших провайдеров картографической информации. Тут покупают данные и Microsoft для Bing и другие крупные компании. А если Вы пользовались навигатором на Nokia устройствах, то знаете, что карты содержат актуальные данные даже для Украины (где на картах заработать сложно). При этом пользователь не только может установить нужные карты, но и получать их обновления на регулярной основе. Если говорить о Bing Maps, то использование этих карт считается устаревшим подходом, хотя сам элемент еще и остался для совместимости.

Итак, давайте рассмотрим, как работают новые карты.

Загрузка карт

Естественно, чтобы использовать карты, пользователь должен иметь возможность загрузить их. Для этого есть два варианта, это использовать приложение Карты, где можно загрузить карты через настройки. Либо предоставить возможность загрузки карт прямо из приложения. Тут существует два готовых класса, это MapDownloaderTask и MapUpdaterTask. Оба класса позволяют запустить одну из задач в операционной системе Windows Phone 8. В первом случае, это приложение, позволяющее выбрать карты для загрузки, а во втором – другая часть того же приложения, позволяющая проверить наличие обновлений установленных карт и загрузить свежие. Оба класса находятся в пространстве имен Microsoft.Phone.Tasks и использование их довольно примитивно:

 

MapDownloaderTask mapDownloaderTask = new MapDownloaderTask();
mapDownloaderTask.Show();

 

К сожалению, проверить или выполнить те же действия в приложении нельзя. Поэтому все, что остается разработчику, это разместить где-то пункты меню или кнопки, позволяющие пользователю принять решение о том, что текущие карты его не удовлетворяют и загрузить нужные. Никто не запрещает нотифицировать пользователя об использовании карт при первом запуске приложения и давать ему возможность быстрого перехода к загрузкам.

Построение маршрута

Если говорить о встроенных возможностях, то тут приложениям доступно еще две задачи, представленными классами MapsTask и MapsDirectionsTasks. Первый класс позволяет запустить приложение Карты из Вашего приложения, а второй – запустить приложение Карты и построить маршрут между двумя заданными пунктами. Посмотрим на эти классы более детально.

Объект класса MapsTask имеет три свойства и может не просто отобразить карту, но и установить уровень приближения, центр карты или выполнить поиск по заданным критериям. Свойства имеют названия ZoomLevel, Center и SearchTerm соответственно. Рассмотрим вот такой код:

 

MapsTask map = new MapsTask();
map.SearchTerm = "Kyiv Zhylianskaya 75";
map.Show();

 

Чтобы заставить данный код работать в эмуляторе, необходимо загрузить карту Украины и Вы получите положение офиса Майкрософт в Киеве:

image

Использование класса MapsDirectionsTask аналогично. У него правда всего два свойства, это Start и End, которые определяют между какими точками нужно прокладывать маршрут. Если свойство Start не задано, то за начало пути будет браться текущее местоположение. Оба свойства имеют тип LabeledMapLocation, конструктор которого принимает заголовок местоположения и GPS координаты. Если координаты не заданы, то заголовок будет использоваться как текст для поиска позиции.

Вот этот кусочек кода позволяет построить путь для проезда в украинский офис Майкрософт:

 

MapsDirectionsTask map = new MapsDirectionsTask();
map.End = new LabeledMapLocation("Kyiv Zhylianskay 75", null);
map.Show();

 

Чтобы он работал в эмуляторе, нужно установить Ваше текущее положение на вкладке Location, а то путь будет строится от значения по умолчанию, а из Редмонда тяжело доехать в Киеве на машине, о чем приложение и сообщитJ

Вот как будет выглядеть экран с построенным маршрутом:

image

Использование элемента управления Map

Перейдем теперь к использованию карт непосредственно в приложении. Тут основным компонентом является класс Map, который можно разместить в виде элемента в XAML файле или добавить на страницу динамически. Правда, чтобы приступить к работе с классом Map, необходимо задекларировать соответствующую возможность в манифесте с помощью элемента с именем ID_CAP_MAP:

 

<Capabilities>
 <Capability Name="ID_CAP_NETWORKING" />
 <Capability Name="ID_CAP_LOCATION" />
 <Capability Name="ID_CAP_MAP" />
</Capabilities>

 

Подобную декларацию можно установить и в графическом редакторе манифеста.

Чтобы добавить карту на страницу приложения в XAML рекомендую воспользоваться панелью инструментов и просто перетащить элемент Map в нужное место. Тогда декларация необходимого пространства имен происходит автоматически. В любом случае, класс Map объявлен в пространстве имен и сборке, которые не декларируются по умолчанию, поэтому среди атрибутов страницы (элемент PhoneApplicationPage) должна появится следующая запись:

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

 

Ну а сам элемент выглядит достаточно просто:

<Controls:Map Name="myMap" />
 

И чудо, карта работает. Никаких регистраций на внешних сайтах, никаких ключей и условий по количеству транзакций. Ведь все карты расположены локально у пользователя и речь не идет о продаже какой-то услуги, как это было с Bing Maps.

Естественно, тут не все так просто. Сборка Microsoft.Phone.Maps.dll содержит три пространства имен с большим количеством классов.

Первое пространство имен Microsoft.Phone.Maps включает всего два класса. Эти классы содержат внутреннюю информацию для картографической службы (когда идет к ней обращение), включая ID приложения и данные аутентификации. Видимо, данный механизм используется, чтобы убедиться, что карты отдаются «по адресу», то есть только пользователи Windows Phone получат эту уникальную возможность. Нам эти классы не пригодятся, в отличие от всех остальных.

Оставшийся набор классов был разделен на два пространства имен, это Microsoft.Phone.Maps.Controls и Microsoft.Phone.Maps.Services. В первом находятся все классы, которые связаны с построением самого элемента (карты) и его составляющих (дополнительных объектов). А во втором – утилитные классы, которые позволяют выполнить запросы для построения маршрутов, поиска данных по координатам и др. Мы рассмотрим большинством из них, но сначала закончим работать с классом Map.

Рассмотрим основные свойства, которые можно устанавливать у объекта типа Map. Тут можно выделить следующие:

· Center – позволяет отцентрировать карту по заданной позиции GPS. Свойство имеет тип System.Device.Location.GeoCoordinate, конструктор которого принимает в качестве параметров долготу и широту. Если разработчик хочет задать центр внутри XAML, то тут существует автоматический конвертер GeoCoordinateConverter, который позволяет записать долготу и широту в виде строки текста из двух значений, разделенных запятой;

· ZoomLevel – это свойство позволяет установить уровень приближения карты. По умолчанию значение равно 1 и позволяет показать на экране телефона всю карту. Максимальное значение равно 20;

· CartographicMode – карты от Nokia поддерживают четыре режима отображения, которые содержатся в перечислимом типе MapCartographicMode. Естественно, что разработчик может установить любой из них и предоставить пользователю переключать режимы в процессе работы. Вот список этих режимов: Road, Aerial, Hybrid и Terrain. Первый режим позволяет отобразить только графическую схему дорог и домов, во втором случае пользователь получает спутниковый снимок, а в третьем и четвертом случае можно увидеть дороги, наложенные на спутниковую карту или только на рельеф местности;

· ColorMode – если Вы пользовались GPS навигаторами, то знаете, что многие из них в ночное время могут автоматически или по запросу переходить в ночной режим, применяя отличную от дневного цветовую гамму. Подобная функциональность есть и у карт Nokia. Так свойство ColorMode способно принимать одно из двух значений перечислимого типа MapColorMode, это Dark и Light. Догадайтесь сами, какое значение отвечает за какой из режимовJ

· LandmarksEnabled – свойство позволяет включить отображение ориентиров, которые становятся видны при приближении 16 или больше. Самое удивительное, что включив ориентиры и просматривая карту Днепропетровска я нашел их аж две штуки, это Главпочтамт и Национальный горный университет. Это уже радует, хотя я ожидал увидеть хотя бы один памятник Владимиру Ильичу, но увы;

image

· PedestrianFeaturesEnabled – это свойство позволяет указать, нужно ли отображать специальные обозначения для пешеходов. Тут могут быть лестницы, переходы, пешеходные мостики и др. На самом деле я смог найти только немного обозначений для Киеве, а для моего любимого Днепропетровска таких обозначений не было. Может быть не очень и нужны, так как сложных развязок в «четыре этажа» у нас нет, а пешеход в основном ходит по землеJ Обозначения отображаются только при приближении карты 16 и больше.

· Pitch – данное свойство позволяет задать наклон карты в градусах (изображение выше с наклоном), придав карте эффект объемности;

· Heading – это свойство задает поворот карты в градусах вокруг центра, позволяя разработчику реагировать на смену ориентации устройства и выводить карту в наиболее удобном режиме.

Все перечисленные свойства можно установить непосредственно, а можно, используя метод SetView. Достоинство этого метода заключается в том, что он способен визуализировать установку новых параметров, применив красивые анимационные эффекты изменяя старые свойства на новые по линейному или параболическому законам. Давайте воспользуемся этим методом, чтобы определить текущее местоположение и отобразить его на карте:

 

private async void OneShotLocation_Click()
{
    //переменную следует выбрать откуда-то из хранилища настроек пользователя
    //и установить в реальное значение
    bool isAllow=true;

    Geolocator geolocator = new Geolocator();

    if (geolocator.LocationStatus == PositionStatus.Disabled)
    {
        if (MessageBox.Show(
            "Определение позиции заблокировано. Перейти к настройкам телефона?",
            "Ошибка настроек", MessageBoxButton.OKCancel)==MessageBoxResult.OK)
        {
            await Launcher.LaunchUriAsync(new Uri("ms-settings-location:"));
        }
        return;
    }

    geolocator.DesiredAccuracyInMeters = 50;

    if (!isAllow)
    {
        if (MessageBox.Show(
            "Разрешить определение позиции устройства для приложения?",
            "Настройки", MessageBoxButton.OKCancel) == MessageBoxResult.OK)
        {
            //сохранить выбранное значение для дальнейшего использования
            //чтобы в следующий раз им заполнять isAllow
        }
        else
        {
            return;
        }
    }

    try
    {
        Geoposition geoposition = await geolocator.GetGeopositionAsync(
            TimeSpan.FromMinutes(5),
            TimeSpan.FromSeconds(10)
            );
                
        myMap.LandmarksEnabled = true;
        myMap.SetView(ConvertGeocoordinate(geoposition.Coordinate), 
16, 0, 45, MapAnimationKind.Parabolic);

        Ellipse myCircle = new Ellipse();
        myCircle.Fill = new SolidColorBrush(Colors.Blue);
        myCircle.Height = 20;
        myCircle.Width = 20;
        myCircle.Opacity = 50;

        MapOverlay myLocationOverlay = new MapOverlay();
        myLocationOverlay.Content = myCircle;
        myLocationOverlay.PositionOrigin = new Point(0.5, 0.5);
        myLocationOverlay.GeoCoordinate = 
            ConvertGeocoordinate(geoposition.Coordinate);

        MapLayer myLocationLayer = new MapLayer();
        myLocationLayer.Add(myLocationOverlay);

        myMap.Layers.Add(myLocationLayer);
    }
    catch (Exception ex)
    {
        MessageBox.Show("Что-то случилось странное!");
    }
}

public GeoCoordinate ConvertGeocoordinate(Geocoordinate geocoordinate)
{
    return new GeoCoordinate
        (
        geocoordinate.Latitude,
        geocoordinate.Longitude,
        geocoordinate.Altitude ?? Double.NaN,
        geocoordinate.Accuracy,
        geocoordinate.AltitudeAccuracy ?? Double.NaN,
        geocoordinate.Speed ?? Double.NaN,
        geocoordinate.Heading ?? Double.NaN
        );
}  

 

Несмотря на большой объем, код тут достаточно простой. Как и раньше, мы определили позицию устройства и получили объект типа Geoposition, который содержит полученную позицию внутри свойства Coordinate типа Geocoordinate. Тут проблема в том, что карты работают с более сложным объектом типа GeoCoordinate. Несмотря на схожее название (разница в одну букву), GeoCoordinate содержит больше информации, поэтому нам нужно написать специальный метод, который будет выполнять преобразование из одного типа в другой. Этот метод находится в самом конце и называется ConvertGeocoordinate.

Далее, чтобы добавить на карту любой UIElement (в нашем случае голубой кружок), необходимо его завернуть в объект типа MapOverlay, привязав последний к конкретным координатам и указав положение содержимого относительно заданной позиции (выбрав (0.5, 0.5) мы контент располагаем строго по центру.

Из объектов типа MapOverlay мы формируем слой карты, который накладываем на исходную карту. Слой карты описывается классом MapLayer и позволяет хранить любое количество объектов типа MapOverlay. Созданный слой мы добавляем в коллекцию Layers нашей карты. Ну и чтобы красиво переместить карту в нужную позицию, мы использовали метод SetView, о котором писали выше.

Реклама

Written by Sergiy Baydachnyy

13.12.2012 в 20:12

Опубликовано в Windows Phone

Tagged with

Добавить комментарий

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход / Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход / Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход / Изменить )

Google+ photo

Для комментария используется ваша учётная запись Google+. Выход / Изменить )

Connecting to %s

%d такие блоггеры, как: