Windows Mobile

Использование GPS и веб-карт для приложений с поддержкой местоположения

Кристофер Митчелл

Загружаемый файл с кодом доступен в коллекции кода MSDN
Обзор кода в интерактивном режиме

В данной статье рассматриваются следующие вопросы.

  • Веб-службы MapPoint
  • Кэширование задач и карт
  • Получение близлежащих интересующих объектов
  • Создание новых задач
В данной статье используются следующие технологии:
Windows Mobile 6, MapPoint

Cодержание

Использование MapPoint для определения местоположения
Задачи и Pocket Outlook
Архитектура приложения
Получение близлежащих объектов
Добавление задач
По дороге в будущее

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

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

Windows Mobile предоставляет много интерфейсов и возможностей, которые позволяют устройству остаться информированным об его среде – где оно, есть ли сигнал, насколько сильный сигнал и так далее. Но как эти устройства можно использовать в приложениях? Наиболее выдающейся и, возможно, полезной из этих возможностей является поддержка местоположения. Это должно дать пользователям возможность создавать поддерживающие местоположение приложения, начиная от достаточно очевидной программы спутниковой навигации, до гораздо более замысловатого списка задач, о котором будет рассказано здесь.

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

Использование MapPoint для определения местоположения

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

fig01.gif

Рис. 1. Приложение Wheretodo

Первая вещь, которая требуется данному приложению – это географические данные. Для целей этой статьи, я решил использовать Веб-службу Microsoft MapPoint. Эта веб-служба является технологией, лежащей в основе Карт Live Search и Virtual Earth, а также предоставляет поиск услуг для Европы и Соединенных Штатов. Предоставленный пример кода использует параметры данных европейской карты; это необходимо будет изменить, чтобы заставить его работать где-то еще.

MapPoint берет широту и долготу GPS, а также коды поиска для определенных типов магазинов в качестве своих аргументов. Информация о расположении может быть предоставлена служебной программой FakeGPS, установленной на симуляторе или смартфоне. (Дополнительную информацию об этой служебной программе см. в боковой панели "FakeGPS".)

MapPoint предоставляет веб-службу XML с API-интерфейсом SOAP. Эта веб-служба разделяется на четыре основных службы: общую службу, службу поиска, службу визуализации и службу маршрута. Основой службой, интересующей данное приложение, является служба поиска, но если требуется дать указать направления пользователю или карте, другие службы можно использовать для расширения этой функции.

Общая служба (CommonServiceSoap), содержит классы, методы и функции, общие для служб поиска, маршрута и визуализации, а также являющиеся базовыми служебными функциями.

Службу поиска (FindServiceSoap) можно использовать для обнаружения адресов, географических объектов, координат широты и долготы и интересующих мест из данных веб-службы MapPoint. Можно также анализировать адреса и возвращать информацию о местоположении для указанной широты и долготы.

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

Служба маршрута (RouteServiceSoap) создает маршруты, рекомендации направлений для водителя и представления вычисленного маршрута (используемые для создания высвеченного маршрута на карте) основанные на промежуточных пунктах, устанавливает параметры выбора сегмента и маршрута и создает представления сегментов и рекомендаций в виде карт.

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

Задачи и Pocket Outlook

Объектная модель Pocket Outlook (Pocket Outlook Object Model – POOM) позволяет добавлять меню и функции к приложениям задач и контактов в Windows Mobile и управлять связанными с ними элементами и данными. Приложение с поддержкой местоположения в основном интересуют три элемента: IAppointment, ITask и IContact.

IAppointment представляет назначенную встречу в папке календаря. Ее объект может представлять собрание, однократную встречу или повторяющееся собрание либо встречу.

ITask представляет назначенную, делегированную или самоназначенную задачу, которую следует выполнить в указанный промежуток времени. Элементы задачи содержатся внутри папки задач.

IContact представляет контакт в папке контактов. Его методы можно использовать для сохранения, удаления, дублирования или отображения контакта. Интерфейс IPOutlookItemCollection можно использовать для добавления новых контактов или получения уже существующих.

Пример приложения будет использовать ITask. (С точки зрения функций, я мог бы использовать IAppointment, но этот интерфейс не настолько подходит к немедленным потребностям приложения.) POOM подобен объектной модели настольного Outlook и больше о ней можно узнать на MSDN, из статьи "Различия между объектной моделью Pocket Outlook и объектной моделью Outlook".

Архитектура приложения

Приложения с поддержкой местоположения состоят из двух цепей функций. Первая – это система, отслеживающая текущие задачи и вопросы, как показано на рис. 2. Задачи сохраняются в таблице базы данных SQL Server Compact. Вдобавок, набор вспомогательных данных хранится внутри другой таблицы, именуемой geocache («геокэш»). Использование отдельной таблицы является средством ограничения требуемых подключений, как я объясню ниже.

fig02.gif

Рис. 2. Отслеживание и предупреждение задач с поддержкой местоположения

Информация для ближайших точек предоставляется веб-службой Microsoft MapPoint. В веб-службе MapPoint имеются различные источники данных для различных частей мира и некоторые из них имеют больше возможностей, чем другие. Источник данных, используемый образцом приложения – это NavTech.EU. После того, как информация собрана, определенные расчеты расстояния могут быть выполнены и предупреждения выданы, там где они нужны.

Вторая цепь событий (см. рис. 3) добавляет задачи к списку задач на устройстве Windows Mobile через POOM. Эта платформа также позволяет доступ к календарю и функциям SMS.

fig03.gif

Рис. 3. Системный процесс для добавления задач к приложению Wheretodo

Задачи и кэш представляют первую часть цепи событий отслеживания и предупреждения. Диспетчер задач просто получает список задач от POOM. Он также управляет таблицей geocache, что решает проблемы с использованием веб-служб на устройствах с потенциально ограниченным подключением. Уровень подключения устройства может варьироваться от перманентного подключения до редкого подключения или даже отсутствия подключения.

Чтобы приспособиться к большому диапазону уровней подключения, нужны адекватная политика КЭШа для данных веб-службы и простая система, которой известно, как извлечь максимум из подключения. Хотя себе легко можно представить очень сложные сценарии, для целей этой статьи была установлена простая радиусная политика кэша. Например, в MapPoint помещается запрос, ищущий все китайские рестораны, торгующие на вынос, в пределах определенного радиуса от текущего местоположения, скажем 80 километров (км). После проезда 40 км в определенном направлении, задается новый поиск. Это основано на той центральной идее, что каждый запрос к веб-службе затратен.

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

Журналы того, где были выполнены запросы, хранятся в базе данных geocachelog и проверяются перед выполнением любых дополнительных запросов, чтобы от веб-службы не запрашивалась дублирующаяся информация. Это также дает возможность заранее заполнить систему существенным объемом информации.

FakeGPS

sidebarfig.gif

Приложение FakeGPS

SDK Windows Mobile 6 содержит служебное приложение, именуемое FakeGPS, которое позволяет протестировать приложение с помощью имитируемых данных GPS. Информацию по установке и тестированию с использованием FakeGPS, см. в статье библиотеки MSDN "Использование служебной программы FakeGPS."

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

Получение близлежащих объектов

Следующий компонент определяет, как заполняется geocache. Когда приложению необходимо найти местоположение, вызывается функция GetNearByPOI (см. рис. 4). Код запрашивает веб-службу MapPoint. Отметьте, что показанный здесь код был упрощен для ясности и отличается от такового в прилагающемся файле кода.

Рис. 4. Получение близлежащих интересных объектов

private void GetNearByPOI(
  string KeyWord, LatLong CurrentPosition) {

  FindServiceSoap findService = new FindServiceSoap();
  FindNearbySpecification findNearBySpec = new FindNearbySpecification();
  findService.Credentials = 
    new System.Net.NetworkCredential(myUserName, myPassword);
  findService.PreAuthenticate = true;

  findNearBySpec.Distance = Convert.ToDouble(inputdistance.Text);
  findNearBySpec.LatLong = new LatLong();
  findNearBySpec.LatLong.Latitude = CurrentPosition.Latitude;
  findNearBySpec.LatLong.Longitude = CurrentPosition.Longitude;

  findNearBySpec.Filter = new FindFilter();
  //findNearBySpec.Filter.EntityTypeName = KeyWord;
  findNearBySpec.Filter.EntityTypeName = "FoodType3"; // SIC CODE
  findNearBySpec.DataSourceName = "NavTech.EU";

  FindResults foundResults;
  foundResults = findService.FindNearby(findNearBySpec);

  string connectionString;
  string fileName = System.IO.Path.GetDirectoryName(
    System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase) + 
    "\\wheretodo.sdf";
  string password = "sa";
  connectionString = string.Format("DataSource=\"{0}\"; Password='{1}'", 
    fileName, password);
  SqlCeConnection cn = new SqlCeConnection(connectionString);
  cn.Open();
  SqlCeCommand cmd;

  //Loop Round and add it to the geocache
  foreach (FindResult fr in foundResults.Results) {
    //This needs to include LongLat in geocache
    string sql = 
      "insert into geocache2 (POI_Name, POI_Address, POI_Tel, POI_Web, " +
      "POI_POST_ZIP, POI_Lat, POI_Long, POI_KeyWord) " +
      "values (@Name, @Address, @Tel, @Web, @POST_ZIP, '" + 
      fr.FoundLocation.LatLong.Latitude.ToString() + 
      "', '" + fr.FoundLocation.LatLong.Longitude.ToString() + "', '" + 
      KeyWord.ToString() + "')";
    cmd = new SqlCeCommand(sql, cn);
    cmd.Parameters.Add("@Name", SqlDbType.NVarChar, 255, "Name").Value = 
      fr.FoundLocation.Entity.Properties[0].Value.ToString();
    cmd.Parameters.Add("@Address", SqlDbType.NVarChar, 255, "Address").Value = 
      fr.FoundLocation.Entity.Properties[1].Value.ToString() + 
      fr.FoundLocation.Entity.Properties[2].Value.ToString();
    cmd.Parameters.Add("@Tel", SqlDbType.NVarChar, 255, "Tel").Value = 
      fr.FoundLocation.Entity.Properties[9].Value.ToString();
    cmd.Parameters.Add("@Web", SqlDbType.NVarChar, 255, "Web").Value = 
      "http://m.live.com";
    cmd.Parameters.Add("@POST_ZIP", SqlDbType.NVarChar, 255, "POST_ZIP").Value = 
      fr.FoundLocation.Entity.Properties[7].Value.ToString();
    cmd.ExecuteNonQuery();

    //Update geocachelog
    sql = "insert into GeoCodeLog (Keyword, Lat, Long ) values ('" + KeyWord + 
      "', '" + fr.FoundLocation.LatLong.Latitude.ToString() + "', '" + 
      fr.FoundLocation.LatLong.Longitude.ToString() + "' )";
    cmd = new SqlCeCommand(sql, cn);
    cmd.ExecuteNonQuery();
  }
}

Взгляните на раздел, где вызываются CurrentPosition.Latitude и CurrentPosition.Longitude. Он, в конечном итоге, происходит от промежуточного драйвера GPS, уровня программного обеспечения, находящегося между приложением и драйвером устройства для оборудования GPS. Этот уровень абстракции позволяет приложениям быть написанными однажды и работать с несколькими устройствами GPS. API-интерфейс промежуточного драйвера GPS предоставляется через библиотеку машинногокода. К этой библиотеке можно получить доступ из управляемого кода, используя пример, входящий в SDK для Windows Mobile 6 Professional (см. "Использование промежуточного драйвера GPS из управляемого кода)".

После того, как получено текущее местоположение и близлежащие интересующие объекты, относящиеся к задаче и определенные здесь кодами в стандартном отраслевом классификационном коде (standard industrial classification – SIC), используемыми в источнике данных Navtech.EU, необходимо определить, насколько именно далеко эти точки находятся от текущего местоположения. Я использовал значения широты и долготы, возвращенные веб-службой и GPS (в данном случае, FakeGPS); рис. 5 показывает, как я преобразовал эти значения в расстояние.

Рис. 5. Вычисление расстояния

private double GetLatLongTuppleDistance(
  double Lat1, double Long1, double Lat2, double Long2) {

  //Convert Degress to Radians for Calculations
  double Lat1r = ConvertDegreesToRadians(Lat1);
  double Lat2r = ConvertDegreesToRadians(Lat2);
  double Long1r = ConvertDegreesToRadians(Long1);
  double Long2r = ConvertDegreesToRadians(Long2);

  // Spherical law of cosines formula—ignores the effect of hills
  double R = 6371; // Earth's radius (km)
  double d = Math.Acos(Math.Sin(Lat1r) * Math.Sin(Lat2r) +
    Math.Cos(Lat1r) * Math.Cos(Lat2r) *
    Math.Cos(Long2r—Long1r)) * R;
  //Returns distances in km
  return d;
} 

Сферическая функция тригонометрии, основанная на сферической теореме косинусов (обобщающей теорему Пифагора) предоставляет функцию, преобразующую пары широты и долготы в дистанцию в километрах. Здесь, очевидным образом, делаются некоторые существенные допущения насчет блокировки местоположения пользователя из точки, которую он пытается найти. Поскольку земпля – не идеальная сфера, в использовании этих формул будут ошибки. Для миль, разделите километр на 1,609344 и, в случае если гребете в булочную на лодке, для морских миль разделите километр на 1,852.

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

Добавление задач

Само собой, прежде чем приложение может найти местоположение, пользователю необходимо добавить задачи к мобильному устройству. POOM отражает объектную модель Outlook, но область ее функций уменьшена, из-за практических ограничений мобильных устройств.

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

OutlookSession outlooksession = new OutlookSession();
Task NewTask = new Task();
NewTask.Body = textBox2.Text.ToString();

string MyString = dateTimePicker2.Value.ToShortDateString() + " " + dateTimePicker1.Text.ToString();
DateTime MyDateTime = new DateTime();
MyDateTime = DateTime.ParseExact(MyString, "M/d/yy h:mm:ss tt", null);
NewTask.DueDate = MyDateTime.ToUniversalTime();
NewTask.Subject = textBox1.Text.ToString();
outlooksession.Tasks.Items.Add(NewTask);

Различные параметры могут быть изменены для установки даты окончания и текста тела задачи с последующим добавлением их в POOM.

Этот компонент составляет последнюю часть двух цепей компонентов, используемых для предоставления функций приложения wheretodo. Интерфейс пользователя системы очень прост и предоставляет способ установки всей необходимой информации и определения кодов SIC, которые будет искать приложение. Приложение в целом просто помещается в бесконечный цикл, для демонстрации использования приложений с поддержкой местоположения. Его очень легко можно добавить как фоновую службу к мобильному устройству, чтобы сделать его интеграцию в среду Windows Mobile 6 или Windows Mobile 5 более эффективной и чистой.

Материалы с данными по мобильным приложениям

Написание одного кода для мобильных и настольных приложений

Поездки. Адаптируемые приложения для Windows Mobile.

Точки данных. Доступ к данным из мобильных приложений.

По дороге в будущее

Читатели увидели один тип устройства с поддержкой местоположения и средство, облегчающее разработку таких приложений. Эту базовую концепцию поддерживающего местоположение списка задач можно легко расширить для RFID.

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

Тем, кто заинтересован в создании собственного установщика для этого или другого свежеобновленного приложения, учитывающего расположение, стоит заглянуть в мою статью из выпуска журнала MSDN Magazine за октябрь 2007 года (Приспособьте уровень громкости звонка под фоновый шум).

Я хотел бы посвятит эту статью Тому Пассею (Tom Passey), доброму другу, который, вместе со своей женой, множество раз проявлял заботу обо мне, оставив самые теплые воспоминания. Мои наилучшие пожелания вам всем.

Кристофер Митчелл (Christopher Mitchell) получил степень кандидата наук в области машинного обучения и обработки музыкального/звукового сигнала, работал в компании Kauffman/NCGE и сейчас открывает собственное дело в Кембридже, Великобритания. По совместительству он читает лекции в расположенном там отделении университета Anglia Ruskin. Вы можете связаться с Крисом по адресу chris.mitchell@anglia.ac.uk.