Опубликован: 02.08.2013 | Доступ: свободный | Студентов: 464 / 17 | Длительность: 18:38:00
Специальности: Программист
Самостоятельная работа 16:

Работа с датчиками, определение местоположения

Аннотация: Данная лабораторная работа посвящена методам взаимодействия со встроенными датчиками устройства.

Цель работы: освоить методы работы со встроенными датчиками

Встроенные датчики

При разработке для Windows Phone можно использовать показания встроенных датчиков устройства, сведения о них можно найти в обзорном материале по пространству имен Windows.Devices.Sensors (http://msdn.microsoft.com/en-us/library/windowsphone/develop/br206408.aspx). Один из доступных датчиков – акселерометр, он позволяет организовывать управление программами путем перемещения телефона в пространстве.

При работе с акселерометром данные, которые можно от него получить, представляют сведения об ускорении устройства в гравитационных единицах. Например, (1,0,0). Если сопоставить эти данные с телефоном, то, если расположить телефон кнопками, расположенными под экраном, вниз, лицевой стороной к наблюдателю, окажется, что ось Y проходит вдоль длинной стороны экрана (положительное направление оси – вверх), X – вдоль короткой (положительное направление оси – вправо), ось Z располагается перпендикулярно экрану (положительное направление – в сторону наблюдателя). Это остаётся справедливым и при поворотах телефона.

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

Таким образом, оказывается, например, если телефон лежит на горизонтальной поверхности неподвижно, экраном вверх, показания акселерометра выглядят как (0, 0, -1). Если расположить телефон вертикально, кнопками вниз, мы имеем в показаниях (0, -1, 0), перевернув телефон "вверх ногами" – (0, 1, 0). Если повернуть телефон на 90° против часовой стрелки – мы получим (-1,0,0). Акселерометр очень чувствителен, даже при неподвижном устройстве показания не бывают в точности равными идеальным, к тому же, они колеблются в небольших пределах.

В демонстрационном проекте P16_1, на странице AccPage.xaml показана работа с акселерометром. В этом примере мы, кроме того, рассматриваем использование карты и работу с сервисом определения местоположения (этот пример основан на примере Simple Map control sample, скачать пример в исходном виде можно здесь: http://code.msdn.microsoft.com/wpapps/Simple-Map-control-sample-fc94908f). На рис. 47.1. показан состав проекта и страница настройки возможностей в редакторе манифеста приложения. Обратите внимание на то, что включены возможности ID_CAP_LOCATION и ID_CAP_MAP – в противном случае приложение работать не будет.

Проект, демонстрирующий работу акселерометра и службы определения местоположения

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

На странице находятся три текстовых блока, мы перемещаем их в плоскости страницы в соответствии с данными об ускорении по осям X и Y, при этом выводим в соответствующих полях сведения об ускорении. В одном из полей мы выводим данные по оси Z, при этом мы не используем для управления объектами эти данные. В Листинге 24.1 вы можете видеть код файла AccPage.xaml.cs. Обратите внимание на то, что код здесь максимально упрощён, в реальном приложении, использующем акселерометр, нужно позаботиться о дополнительных механизмах, в частности, об обработке ошибок.

using System;
using Microsoft.Phone.Controls;
using Microsoft.Devices.Sensors;
using System.Windows.Media;
namespace P16_1
{
    public partial class AccPage : PhoneApplicationPage
    {
        //Для акселерометра
        private Accelerometer accelerometer;
        //Для трансформации
        private TranslateTransform moveTranslation;
    
        public AccPage()
        {
            InitializeComponent();
            //Новый экземпляр объекта Accelerometer
            accelerometer = new Accelerometer();
            //Время между обновлениями показаний акселерометра
            accelerometer.TimeBetweenUpdates = TimeSpan.FromMilliseconds(20);
            //Подключаем обработчик события, возникающего при получении новых данных
            accelerometer.CurrentValueChanged += new System.EventHandler<SensorReadingEventArgs<AccelerometerReading>>
(accelerometer_CurrentValueChanged);
            //Запуск акселерометра
            accelerometer.Start();
            //Новая трансформация
            moveTranslation = new TranslateTransform();
            
            //Назначаем трансформацию текстовым блокам
            txtX.RenderTransform = this.moveTranslation;
            txtY.RenderTransform = this.moveTranslation;
            txtZ.RenderTransform = this.moveTranslation;
        }
        //Обработчик
        void accelerometer_CurrentValueChanged(object sender, 
SensorReadingEventArgs<AccelerometerReading> e)
        {
            //Вызов метода, который работает с объектами в потоке пользовательского интерфейса
            Dispatcher.BeginInvoke(() => MoveObject(e.SensorReading));
        }
        //Метод для перемещения объекта
        void MoveObject(AccelerometerReading accData)
        {
            //Задаем текст для вывода в текстовые блоки
            txtX.Text = "X=" + accData.Acceleration.X.ToString();
            txtY.Text = "Y=" + accData.Acceleration.Y.ToString();
            txtZ.Text = "Z=" + accData.Acceleration.Z.ToString();
            //Перемещаем блоки на плоскости
            moveTranslation.X += accData.Acceleration.X * 2;
            moveTranslation.Y -= accData.Acceleration.Y * 2;
            //Задаём границы области, которые не могут пересечь перемещаемые объекты
            if (moveTranslation.X <= 0)
            {
                moveTranslation.X = 0;
            }
            if (moveTranslation.Y <= 0)
            {
                moveTranslation.Y = 0;
            }
            if (moveTranslation.X >= 300)
            {
                moveTranslation.X = 300;
            }
            if (moveTranslation.Y >= 550)
            {
                moveTranslation.Y = 550;
            }
        }
    }
}
Листинг 47.1. Код файла AccPage.xaml.cs

Обратите внимание на обработчик accelerometer_CurrentValueChanged. Этот обработчик выполняется в собственном потоке, а пользовательский интерфейс – в собственном. В итоге, для того, чтобы обратиться к элементу пользовательского интерфейса, нам понадобится воспользоваться диспетчером (Dispatcher), с помощью которого можно направить задание из одного потока в другой. В данном случае мы используем лямбда-выражение.