Опубликован: 15.06.2012 | Доступ: свободный | Студентов: 1547 / 109 | Оценка: 4.19 / 3.63 | Длительность: 07:02:00
Специальности: Программист
Лекция 8:

Датчики и службы

< Лекция 7 || Лекция 8: 12 || Лекция 9 >
Аннотация: Данная лекция посвящена двум возможностям сбора сведений об окружающем мире в Windows Phone 7. С согласия пользователя служба определения местоположения предоставляет приложению данные о местоположении телефона в традиционных географических координатах, долгота и широта, тогда как акселерометр сообщает приложению направление вниз. Акселерометр и служба определения местоположения, довольно просты, поэтому в данной лекции также рассматриваются вопросы, касающиеся вторичных потоков выполнения, которые обрабатывают асинхронные операции и выполняют доступ к Веб-сервисам.

Датчики и сервисы

Цель лекции: научиться работать с координатами, акселерометром, картами и другими, службами и датчиками.

Устройство Windows Phone 7 должно иметь ряд аппаратных возможностей – иногда называемых датчиками – и предоставлять некоторые программные сервисы, возможно, с аппаратной поддержкой. Рассмотрим те из них, которые наиболее интересны разработчикам:

  • Wi-Fi - для доступа к Интернету телефон снабжен Wi-Fi в дополнение к доступу к данным по технологиям 3G (3G data access), предоставляемому поставщиком мобильной связи. В программное обеспечение, установленное на телефоне, включена версия Internet Explorer.
  • Камера – телефон снабжен камерой с разрешением не менее 5 мегапикселей и вспышкой. Программы могут вызывать ПО камеры для осуществления ввода с нее или регистрироваться как приложение расширений для обработки фотографий. В этом случае они будут отображаться в меню для получения доступа к сфотографированным изображениям, например, для обработки этих изображений определенным образом.
  • Акселерометр- измеряет ускорение, что является физической величиной, обозначающей изменение скорости. Если камера неподвижна, акселерометр реагирует на изменение гравитации. Программы могут получать трехмерный вектор, определяющий положение камеры относительно земли. Акселерометр также может выявлять резкие перемещения телефона.
  • Местоположение - по желанию пользователя телефон может применять множество стратегий определения своего географического местоположения. Телефон передает в аппаратное устройство GPS данные из Интернета или вышек сотовой связи. При его перемещении также могут предоставляться данные о направлении и скорости.
  • Вибрация - программное управление вибрацией телефона.
  • FM-радио - программный доступ к FM-радио.
  • Принудительные уведомления - для обновления данных, предоставляемых некоторыми Веб-сервисами, телефону пришлось бы регулярно опрашивать эти сервисы. Это могло бы приводить к разрядке батареи и сокращению времени автономной работы.

Акселерометр

Устройства Windows Phone имеют акселерометр – небольшое аппаратное устройство, по сути, измеряющее силу, которая, согласно элементарной физике, пропорциональна ускорению. Когда телефон неподвижен, акселерометр регистрирует силу притяжения, т.е. позволяет определить положение телефона относительно земли.

Моделирование уровня нивелира является основным применением акселерометра. Кроме того, акселерометр может также обеспечивать исходные данные для интерактивной анимации. Например, можно смоделировать управление курьерским мотоциклом по улицам мегаполиса, поворачивая телефон влево или вправо, как будто рулем.

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

Выходные данные акселерометра удобно представить в виде трехмерного вектора. Обычно векторы записываются полужирным шрифтом, поэтому вектор ускорения может быть обозначен так: (x, y, z). В XNA есть тип трехмерный вектор, в Silverlight нет.

Тогда как три координаты (x, y, z) точно определяют точку в пространстве, вектор (x, y, z) обозначает направление и величину. Очевидно, что точка и вектор взаимосвязаны. Направление вектора (x, y, z) – это луч из точки (0, 0, 0) в точку (x, y, z). Но вектор (x, y, z) это совсем не отрезок, соединяющий (0, 0, 0) и (x, y, z). Это направление этого отрезка.

Для вычисления модуля вектора (x, y, z) используется трехмерная форма теоремы Пифагора:

Модуль = \sqrt{x^2+y^2+z^2}

Для работы с акселерометром ассоциируем с телефоном трехмерную систему координат. Не важно, как ориентирован телефон, но положительное направление оси Y будет проходить вдоль максимального размера телефона снизу (где располагаются кнопки) вверх, и положительное направление оси X – слева направо. Ось Z направлена перпендикулярно телефону, прямо на пользователя.

Трехмерная система координат

Рис. 8.1. Трехмерная система координат

Это традиционная трехмерная система координат, такая же используется при создании 3D-графики на XNA. Ее называют правой системой координат. Расположите указательный палец правой руки вдоль положительного направления Х, средний палец – вдоль положительного направления Y, и большой палец будет указывать на положительное направление Z.

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

Когда телефон неподвижен, вектор акселерометра указывает на землю. Модуль равен 1, т.е. 1g (постоянная – ускорение свободного падения), что соответствует силе притяжения на поверхности земли. Когда телефон расположен вертикально, вектор ускорения – (0, –1, 0), т.е. направлен прямо вниз.

Поверните телефон на 90° против часовой стрелки (так называемое левостороннее альбомное расположение), и вектор ускорения станет равным (–1, 0, 0); переверните телефон "вверх ногами" – вектор равен (0, 1, 0); еще один поворот на 90° против часовой стрелки обеспечивает правостороннее альбомное расположение и вектор ускорения равный (1, 0, 0). Положите телефон на стол экраном вверх, и вектор ускорения будет (0, 0, –1). (Эмулятор Windows Phone 7 всегда возвращает это значение.)

Конечно, вектор ускорения редко будет принимать такие точные значения, даже его модуль не будет точно равен 1. Для неподвижного телефона значения модуля могут колебаться в пределах нескольких процентов для разных ориентаций. На Луне величина вектора ускорения Windows Phone 7 будет в районе 0,17, но мобильная связь неустойчивая.

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

Когда телефон, движущийся влево, начнет замедляться, вектор ускорения ненадолго направится влево до остановки устройства.

При свободном падении модуль вектора ускорения, теоретически, должен стремиться к нулю.

Для работы с акселерометром используется библиотека Microsoft.Devices.Sensors и пространство имен Microsoft.Devices.Sensors. В файле WMAppManifest.xml необходимо указать:

<Capability Name="ID_CAP_SENSORS"/>

Это задается по умолчанию.

В приложении создается экземпляр класса Accelerometer (Акселерометр), задается обработчик события ReadingChanging (Изменение показаний прибора) и вызывается метод Start.

Рассмотрим проект SilverlightAccelerometer.project, который просто обеспечивает выведение на экран текущих показаний. Центрированный TextBlock описывается в файле XAML:

Проект Silverlight: SilverlightAccelerometer Файл: MainPage.xaml (фрагмент)

<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
        <TextBlock Name="txtblk" HorizontalAlignment="Center" VerticalAlignment="Center" />
 </Grid>

Чтобы добавить библиотеку Microsoft.Devices.Sensors в проект нужно:

  1. нажать правой кнопкой на узел SilverlightAccelerometer / References в окне Solution Explorer и выберите Add Reference. На вкладке .NET появившегося окна для выбора библиотек выберите пункт Microsoft.Devices.Sensors и нажать OK;
    Добавление библиотеки Microsoft.Devices.Sensors

    Рис. 8.2. Добавление библиотеки Microsoft.Devices.Sensors
  2. добавить строчку using Microsoft.Devices.Sensors; в MainPage.xaml.cs

Это приложение будет обеспечивать вывод на экран вектора акселерометра на протяжении всего времени его выполнения, поэтому создание класса Accelerometer и вызов метода Start происходит в конструкторе:

Проект Silverlight: SilverlightAccelerometer Файл: MainPage.xaml.cs (фрагмент)

public MainPage()
        { 
            InitializeComponent();
            Accelerometer acc = new Accelerometer();
            acc.ReadingChanged += OnAccelerometerReadingChanged;
            try 
            { 
                acc.Start(); 
            } 
            catch (Exception exc) 
            { 
                txtblk.Text = exc.Message; 
            } 

        } 

Документация предупреждает, что вызов Start может привести к формированию исключения, поэтому приложение защищает себя от этого. Класс Accelerometer также поддерживает методы Stop (Остановить) и Dispose (Удалить), но в данной программе они не используются. Для обеспечения сведения о доступности акселерометра и его состоянии предоставляется свойство State.

Событие ReadingChanged обеспечивается классом аргументов события AccelerometerReadingEventArgs. Этот объект имеет свойства X, Y и Z типа double и свойство TimeStamp типа DateTimeOffset (Смещение даты-времени). В приложении SilverlightAccelerometer задача обработчика события – форматировать эти данные в строку и задать ее как значение свойства Text объекта TextBlock.

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

Немного теории. Создание и доступ ко всем элементам и объектам пользовательского интерфейса в приложении на Silverlight выполняется в основном потоке выполнения, который часто называют потоком пользовательского интерфейса или UI-потоком. Эти объекты пользовательского интерфейса не являются потокобезопасными; для них не предусмотрен одновременный доступ из множества потоков. Поэтому Silverlight не допустит доступа к объекту пользовательского интерфейса из потока, не являющегося UI-потоком.

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

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

Экземпляр Dispatcher уже доступен. Класс DependencyObject (Зависимость) описывает свойство Dispatcher типа Dispatcher, и от DependencyObject наследуется множество классов Silverlight. С экземплярами всех этих классов можно работать из потоков, не являющихся UI-потоками, потому что все они имеют свойства Dispatcher. Из любого производного от DependencyObject класса, созданного в UI-потоке, может использоваться любой объект Dispatcher. Они все одинаковые.

Класс Dispatcher определяет метод CheckAccess (Проверить возможность доступа), который возвращает true, если текущий поток имеет доступ к конкретному объекту пользовательского интерфейса. (Метод CheckAccess также дублируется самим DependencyObject.) Для случаев, когда доступ к объекту из текущего потока невозможен, Dispatcher предоставляет две версии метода Invoke (Вызвать), с помощью которых выполняется отправка заданий для UI-потока.

В проекте SilverlightAccelerometer реализована версия кода, доскональная с точки зрения синтаксиса.

В развернутой версии требуется делегат и метод, соответствующий этому делегату. Делегат (и метод) не должен иметь возвращаемого значения, но у него должно быть такое количество аргументов, которого будет достаточно для выполнения задания. В данном случае это задание состоит в присвоении строки в качестве значения свойства Text объекта TextBlock:

Проект: SilverlightAccelerometer Файл: MainPage.xaml.cs (фрагмент)

delegate void SetTextBlockTextDelegate(TextBlock txtblk, string text);
        void SetTextBlockText(TextBlock txtblk, string text) 
        { 
            txtblk.Text = text; 
        }

OnAccelerometerReadingChanged отвечает за вызов SetTextBlockText (Задать текст блока текста). Он впервые использует CheckAccess, чтобы определить возможность вызова метода SetTextBlockText напрямую. Если это невозможно, обработчик вызывает метод BeginInvoke (Начать вызов). Его первым аргументом является экземпляр делегата с методом SetTextBlockText. За ним следуют все необходимые SetTextBlockText аргументы:

Проект: SilverlightAccelerometer Файл: MainPage.xaml.cs (фрагмент)

void OnAccelerometerReadingChanged(object sender, AccelerometerReadingEventArgs args) 
        { 
            string str = String.Format("X = {0:F2}\n" + "Y = {1:F2}\n" + "
Z = {2:F2}\n\n" + "Magnitude = {3:F2}\n\n" + "{4}", 
args.X, args.Y, args.Z, Math.Sqrt(args.X * args.X + args.Y * args.Y + args.Z * args.Z), args.Timestamp); 
            if (txtblk.CheckAccess()) { SetTextBlockText(txtblk, str); 
            } 
            else 
            { 
                txtblk.Dispatcher.BeginInvoke(new SetTextBlockTextDelegate(SetTextBlockText), txtblk, str); 
            } 
        } 

Это не самый плохой вариант, но необходимость перепрыгивать из потока в поток повлекла за собой применение дополнительного метода и делегата.

В эмуляторе Windows Phone 7 нет акселерометра, поэтому он всегда возвращает значение (0, 0, –1), свидетельствующее о том, что телефон лежит на плоской поверхности. Выполнять это приложение имеет смысл только на реальном телефоне:

Результат программы

Рис. 8.3. Результат программы
< Лекция 7 || Лекция 8: 12 || Лекция 9 >