Статьи

Добавление геолокации и карт в приложения для Windows Phone

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

Окончательный проект для этого урока на GitHub .

Добавление карты

Сначала нам нужно создать приложение для хранения нашей карты, сделайте это с помощью сочетания клавиш Ctrl + Shift + N или выбрав пункт меню Файл -> Создать -> Проект… Оба способа приведут вас к окну ниже. Слева убедитесь, что вы выбрали Windows Phone , затем выберите Пустое приложение (Windows Phone) . Дайте вашему приложению имя и нажмите Ok .

Новый проект

Открыв MainPage.xaml, вы увидите черный пустой MainPage . Если вы хотите добавить новый заголовок страницы по умолчанию и имя приложения, удалите его, щелкните правой кнопкой мыши проект и выберите « Добавить» -> «Новый элемент» … _

Новый предмет

Выберите Basic Page и назовите его MainPage .

Основная страница

При следующей подсказке нажмите Да . Он автоматически добавляет файлы, необходимые для управления навигацией по страницам. Эти классы попадают в папку с именем Common .

Общие файлы

Теперь, чтобы добавить карту, просто перетащите MapControl из панели инструментов и поместите его в сетку LayoutRoot в Outline документа . Вы также можете оставить его внутри дизайнера. Код xaml будет сгенерирован автоматически, как вы можете видеть ниже.

Добавить MapControl

Если вы хотите добавить элемент управления самостоятельно, добавьте эту строку кода в теги сетки ControlRoot .

 <maps:MapControl /> 

Он нуждается в ссылке внутри открывающего тега Page или приведет к ошибке.

 xmlns:maps="using:Windows.UI.Xaml.Controls.Maps" 

Этого достаточно для создания элемента управления, но мы добавим еще пару свойств.

На этом этапе вы можете запустить ваше приложение, и оно будет скомпилировано без ошибок, но при запуске вы увидите вместо карты сообщение с предупреждением: MapServiceToken не указан. Мы решаем это на следующем этапе.

Ошибка MapService

Добавить MapServiceToken

Чтобы использовать MapControl в своем приложении, вы должны быть зарегистрированным разработчиком Windows и зарезервировать имя для своего приложения, чтобы сгенерировать токен для использования службы.

Когда вы это сделаете, перейдите на панель разработчика и выберите свое приложение. Слева нажмите Сервисы , затем Карты . Нажмите кнопку Получить токен, который появляется справа.

Картографический сервис получить токен

Вы увидите две строки: идентификатор приложения и токен аутентификации . Второе — это то, что нам нужно.

Токен аутентификации картографического сервиса

Возвращаясь к нашему проекту, в представлении «Код» MainPage.xaml обновите следующие строки:

 <Grid Grid.Row="1" x:Name="ContentRoot" Margin="0"> <maps:MapControl x:Name="MyMap" MapServiceToken="<your authentication token>" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Margin="10"/> </Grid> 

Здесь я добавил MapServiceToken , имя для MapServiceToken управления и несколько свойств, чтобы карта почти полностью заполнила экран. Не забудьте заменить <your authentication token> на свой токен. MapControl не показывает фактическую карту в режиме конструктора, он показывает окно, в которое поместится карта, поэтому вы не сможете сразу увидеть, что происходит. Запустите приложение, чтобы увидеть результат.

Первый успешный заезд

Получить текущее местоположение

Одним из наиболее распространенных требований к приложениям является получение информации о местоположении пользователей в мире и сбор данных о местоположении.

Чтобы получить это, откройте MainPage.xaml.cs и добавьте следующие пространства имен.

 using System; using Windows.Devices.Geolocation; using Windows.UI.Popups; 

Добавьте два метода внутри класса MainPage .

 private async void getLocation() { Geolocator gl = new Geolocator { DesiredAccuracy = PositionAccuracy.High }; try { Geoposition gp = await gl.GetGeopositionAsync( maximumAge:TimeSpan.FromMinutes(1), timeout:TimeSpan.FromSeconds(20)); message("Lat: " + gp.Coordinate.Point.Position.Latitude + "\n Lon: " + gp.Coordinate.Point.Position.Longitude, "Coordinates"); } catch (Exception e) { message(e.Message, "ERROR!"); } } private async void message(string body, string title) { var dlg = new MessageDialog( string.Format(body), title); try { await dlg.ShowAsync(); } catch (Exception) { } } - private async void getLocation() { Geolocator gl = new Geolocator { DesiredAccuracy = PositionAccuracy.High }; try { Geoposition gp = await gl.GetGeopositionAsync( maximumAge:TimeSpan.FromMinutes(1), timeout:TimeSpan.FromSeconds(20)); message("Lat: " + gp.Coordinate.Point.Position.Latitude + "\n Lon: " + gp.Coordinate.Point.Position.Longitude, "Coordinates"); } catch (Exception e) { message(e.Message, "ERROR!"); } } private async void message(string body, string title) { var dlg = new MessageDialog( string.Format(body), title); try { await dlg.ShowAsync(); } catch (Exception) { } } 

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

Настоящая работа здесь происходит в getLocation() . Сначала мы объявляем Geolocator с высокой точностью положения. Мы даже можем установить точность в метрах, используя

 gl.DesiredAccuracyInMeters = 100; 

В обоих случаях точность зависит от того, что мы хотим получить с данными о местоположении, которые мы получаем.

Мы также можем установить MovementThreshold и ReportInterval . MovementThreshold — это расстояние, на которое нужно переместиться, чтобы его на самом деле назвали ходом и вызвать событие PositionChanged . ReportInterval дает время (в миллисекундах) поставщику местоположения для обновления. Если у вас есть кнопка, которая позволяет пользователю узнать свое местоположение, и пользователь решает нажать ее 100 раз, вызов не будет повторяться дважды за один и тот же интервал.

Вернуться к getLocation() . У нас есть блок try-catch который содержит асинхронный вызов для получения GeoPosition с использованием ранее упомянутого геолокации и устанавливает два параметра.

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

timeout — это время, которое мы готовы ждать ответа, поэтому, если у нас есть расчеты, основанные на данных, которые мы получаем, они не задержат процесс.

Наконец, вызовите getLocation() . Я добавил AppBarButton с событием щелчка. Добавьте приведенный ниже код в MainPage.xaml перед тегом Grid .

 <Page.BottomAppBar> <CommandBar> <AppBarButton Icon="Target" Label="Get Location" Click="AppBarButton_Click"/> </CommandBar> </Page.BottomAppBar> 

Используйте этот метод в качестве обработчика событий внутри MainPage.xaml.cs .

 private void AppBarButton_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e) { getLocation(); } 

Если вы запустите приложение сейчас, вы получите следующее исключение.

Ошибка GetLocation

Это происходит потому, что нам нужно объявить, когда мы хотим получить местоположение пользователей, чтобы это не было сделано без их разрешения. Откройте Package.appxmanifest в обозревателе решений . В разделе « Возможности » нажмите вкладку «+» в списке.

Объявить возможность размещения

Запустите приложение и нажмите кнопку « Получить местоположение» на панели команд. Через пару секунд, в зависимости от вашей сети, появится сообщение с вашим местоположением.

GetLocation успешно

Изменить центр карты и уровень масштабирования

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

 private void CenterMap(double lat, double lon) { MyMap.Center = new Geopoint(new BasicGeoposition() { Latitude = lat, Longitude = lon }); } 

Возможно, вы заметили, что карта пока показывает континенты. Если вы хотите увеличить масштаб до определенной страны или города, вы можете сделать это всего одной строкой кода. Но разные устройства имеют разные размеры экрана, и масштаб может быть не на должном уровне, или что, если пользователь хочет уменьшить? Хорошим подходом является добавление ползунка, чтобы пользователь мог контролировать уровень масштабирования. Сначала мы добавляем элемент управления в MainPage.xaml прямо под тегом map.

 <Slider x:Name="slider" VerticalAlignment="Bottom" Margin="15,0" LargeChange="1" Maximum="20" Minimum="1" SmallChange="1" ValueChanged="slider_ValueChanged"/> 

Слайдер может иметь целочисленные значения от 1 до 20. Чтобы перехватить событие ValueChanged, мы используем следующий метод, добавленный в MainPage.cs .

 private void slider_ValueChanged(object sender, Windows.UI.Xaml.Controls.Primitives.RangeBaseValueChangedEventArgs e) { if (slider != null) MyMap.ZoomLevel = (int)slider.Value; } 

Осталось только обновить метод GetLocation() который у нас уже есть. Изменения вносятся в блок try.

 try { Geoposition gp = await gl.GetGeopositionAsync( maximumAge:TimeSpan.FromMinutes(1), timeout:TimeSpan.FromSeconds(20)); //message("Lat: " + gp.Coordinate.Latitude + //"\n Lon: " + gp.Coordinate.Longitude, "Coordinates"); CenterMap(gp.Coordinate.Point.Position.Latitude, gp.Coordinate.Point.Position.Longitude); MyMap.ZoomLevel = (int)slider.Value; } - try { Geoposition gp = await gl.GetGeopositionAsync( maximumAge:TimeSpan.FromMinutes(1), timeout:TimeSpan.FromSeconds(20)); //message("Lat: " + gp.Coordinate.Latitude + //"\n Lon: " + gp.Coordinate.Longitude, "Coordinates"); CenterMap(gp.Coordinate.Point.Position.Latitude, gp.Coordinate.Point.Position.Longitude); MyMap.ZoomLevel = (int)slider.Value; } 

Результат на скриншоте ниже. Пользователь может запросить их местоположение и увеличить или уменьшить масштаб.

Карта с ползунком

Добавление кнопок

Последнее, что я расскажу — это кнопки. Это хороший способ сделать точки заметными на карте.

Я добавил AppBarToggleButton чтобы показать AppBarToggleButton представляющую местоположение пользователя на карте. Теперь CommandBar выглядит так:

 <Page.BottomAppBar> <CommandBar> <AppBarButton Icon="Target" Label="Get Location" Click="AppBarButton_Click"/> <AppBarToggleButton x:Name="PushPinToggle" Icon="MapPin" Label="Toggle Pushpin" Checked="AppBarToggleButton_Checked" IsChecked="False" Unchecked="AppBarToggleButton_Unchecked"/> </CommandBar> </Page.BottomAppBar> 

События check / uncheck обрабатываются двумя методами, которые добавляют или удаляют метку из дочерних элементов карты.

 private void AppBarToggleButton_Checked(object sender, Windows.UI.Xaml.RoutedEventArgs e) { AddPushpin(MyMap.Center.Position.Latitude, MyMap.Center.Position.Longitude, Colors.Blue); } private void AppBarToggleButton_Unchecked(object sender, Windows.UI.Xaml.RoutedEventArgs e) { MyMap.Children.Clear(); } 

Работа здесь происходит в методе AddPushpin , который имеет три параметра: широту и долготу местоположения и цвет кнопки, который является необязательным.

 public void AddPushpin(double lat, double lon, Color c) { BasicGeoposition location = new BasicGeoposition(); location.Latitude = lat; location.Longitude = lon; var pin = new Ellipse() { Fill = new SolidColorBrush(c), Stroke = new SolidColorBrush(Colors.White), StrokeThickness = 1, Width = 40, Height = 40, }; pin.Tapped += pin_Tapped; Windows.UI.Xaml.Controls.Maps.MapControl.SetLocation(pin, new Geopoint(location)); MyMap.Children.Add(pin); } void pin_Tapped(object sender, Windows.UI.Xaml.Input.TappedRoutedEventArgs e) { message("This is your location.", ""); } 

В моем случае канцелярская кнопка — это эллипс. Вы можете установить различные свойства, такие как размер, цвет, границы и т. Д. Я также добавил EventHandler когда пользователь нажимает на пин-код. Вы можете отобразить больше информации об этом месте с помощью DialogMessage как мы делали ранее.

Осталось только MapControl этому MapControl географическое местоположение, иначе это будет эллипс, нарисованный над MapControl . Увеличение и уменьшение или перемещение вокруг не изменят положение булавки.

Теперь, когда все MapControl , добавьте свою MapControl дочерние MapControl и запустите приложение в последний раз.

Вывод

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

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

Спасибо за уделенное время. Пусть код будет с вами!