Цель работы: освоить методы работы со встроенными датчиками
При разработке для 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;
}
}
}
}
Обратите внимание на обработчик accelerometer_CurrentValueChanged. Этот обработчик выполняется в собственном потоке, а пользовательский интерфейс – в собственном. В итоге, для того, чтобы обратиться к элементу пользовательского интерфейса, нам понадобится воспользоваться диспетчером (Dispatcher), с помощью которого можно направить задание из одного потока в другой. В данном случае мы используем лямбда-выражение.
На странице MapPage.xaml показана работа с картой и службой определения местоположения, пример подготовлен на основе примера "Simple Map control sample" ("Пример работы с картой"), скачать пример в исходном виде можно здесь: http://code.msdn.microsoft.com/wpapps/Simple-Map-control-sample-fc94908f.
В файле CoordinateConverter.cs находится статический метод, который используется для разбора показателей о географическом расположении пользователя, Листинг 24.2.
using System;
using System.Device.Location; //Для класса GeoCoordinate.
using Windows.Devices.Geolocation; //Для класса Geocoordinate.
namespace P16_1
{
public static class CoordinateConverter
{
public static GeoCoordinate ConvertGeocoordinate(Geocoordinate 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
);
}
}
}
В файле MapPage.xaml (Листинг 24.3) содержится объявление элемента управления Map. Обратите внимание на то, что для использовании этого элемента управления в приложении, которое будет опубликовано, нужно указать идентификатор приложения и ключ аутентификации. Его можно получить на https://www.bingmapsportal.com/.
<phone:PhoneApplicationPage
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:maps="clr-namespace:Microsoft.Phone.Maps.Controls;assembly=Microsoft.Phone.Maps"
x:Class="P16_1.MapPage"
mc:Ignorable="d"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="Portrait" Orientation="Portrait"
shell:SystemTray.IsVisible="True">
<!--LayoutRoot is the root grid where all page content is placed-->
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!--TitlePanel contains the name of the application and page title-->
<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
<TextBlock Text="{Binding LocalizedResources.ApplicationTitle,
Source={StaticResource LocalizedStrings}}"
Style="{StaticResource PhoneTextNormalStyle}" Margin="12,0"/>
<TextBlock Text="{Binding LocalizedResources.NavPageName,
Source={StaticResource LocalizedStrings}}"
Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
</StackPanel>
<!--ContentPanel - place additional content here-->
<Grid x:Name="ContentPanel" Grid.Row="1"
Margin="12,0,12,0">
<maps:Map x:Name="sampleMap" LandmarksEnabled="False" Loaded="sampleMap_Loaded"/>
</Grid>
</Grid>
</phone:PhoneApplicationPage>
И в этом файле, и в файле кода, при создании панели приложения, используются строковые ресурсы из файла AppResources.resx и механизм привязки данных.
В Листинге 24.4 приведен код файла MapPage.xaml.cs. Здесь присутствуют, помимо механизмов для работы с картой и для определения местоположения, и вспомогательные механизмы. В частности, обратите внимание на объект currentLocation – именно в нём хранятся данные, полученные после определения местоположения, он же используется и для позиционирования маркера местоположения на карте. При работе с картой применяется масштабирование карты, включение и отключение маркера, указывающего на расположение устройства, включение и отключение меток на карте.
using System;
using System.Windows;
using Microsoft.Phone.Shell;
using Microsoft.Phone.Controls;
using P16_1.Resources;
using Microsoft.Phone.Maps;
using Microsoft.Phone.Maps.Controls;
using System.Device.Location; // Для класса GeoCoordinate.
using Windows.Devices.Geolocation; //Для класса Geocoordinate.
using System.Windows.Shapes;
using System.Windows.Media;
namespace P16_1
{
public partial class MapPage : PhoneApplicationPage
{
//Параметры масштабирования карты
const int MIN_ZOOM_LEVEL = 1;
const int MAX_ZOOM_LEVEL = 20;
const int MIN_ZOOMLEVEL_FOR_LANDMARKS = 16;
//Параметры определения местоположения и вывода дополнительных сведений
ToggleStatus locationToggleStatus = ToggleStatus.ToggledOff;
ToggleStatus landmarksToggleStatus = ToggleStatus.ToggledOff;
//Для определения местоположения
GeoCoordinate currentLocation = null;
MapLayer locationLayer = null;
// Конструктор.
public MapPage()
{
InitializeComponent();
// Создание панели приложения ApplicationBar.
BuildLocalizedApplicationBar();
// Получение текущего расположения.
GetLocation();
}
//Перед публикаией приложения здесь нужно указать параметры
// ApplicationID и AuthenticationToken
// их можно получить в Центре разработчиков Windows Phone
private void sampleMap_Loaded(object sender, RoutedEventArgs e)
{
MapsSettings.ApplicationContext.ApplicationId = "<applicationid>";
MapsSettings.ApplicationContext.AuthenticationToken = "<authenticationtoken>";
}
#region Обаботчики событий для кнопок и команд меню панели приложения
void ToggleLocation(object sender, EventArgs e)
{
switch (locationToggleStatus)
{
case ToggleStatus.ToggledOff:
ShowLocation();
CenterMapOnLocation();
locationToggleStatus = ToggleStatus.ToggledOn;
break;
case ToggleStatus.ToggledOn:
sampleMap.Layers.Remove(locationLayer);
locationLayer = null;
locationToggleStatus = ToggleStatus.ToggledOff;
break;
}
}
void ToggleLandmarks(object sender, EventArgs e)
{
switch (landmarksToggleStatus)
{
case ToggleStatus.ToggledOff:
sampleMap.LandmarksEnabled = true;
if (sampleMap.ZoomLevel < MIN_ZOOMLEVEL_FOR_LANDMARKS)
{
sampleMap.ZoomLevel = MIN_ZOOMLEVEL_FOR_LANDMARKS;
}
landmarksToggleStatus = ToggleStatus.ToggledOn;
break;
case ToggleStatus.ToggledOn:
sampleMap.LandmarksEnabled = false;
landmarksToggleStatus = ToggleStatus.ToggledOff;
break;
}
}
void ZoomIn(object sender, EventArgs e)
{
if (sampleMap.ZoomLevel < MAX_ZOOM_LEVEL)
{
sampleMap.ZoomLevel++;
}
}
void ZoomOut(object sender, EventArgs e)
{
if (sampleMap.ZoomLevel > MIN_ZOOM_LEVEL)
{
sampleMap.ZoomLevel--;
}
}
#endregion
#region Вспомогательные функции для обработчиов событий кнопок и
команд меню панели приложения
private void ShowLocation()
{
// Создание окружности, которая будт использована в качестве метки текущего расположения.
Ellipse myCircle = new Ellipse();
myCircle.Fill = new SolidColorBrush(Colors.Blue);
myCircle.Height = 20;
myCircle.Width = 20;
myCircle.Opacity = 50;
// Создания объекта MapOverlay на котором будет расположена окружность.
MapOverlay myLocationOverlay = new MapOverlay();
myLocationOverlay.Content = myCircle;
myLocationOverlay.PositionOrigin = new Point(0.5, 0.5);
myLocationOverlay.GeoCoordinate = currentLocation;
// Создания слоя карты, MapLayer, на котором будет размещен объект MapOverlay.
locationLayer = new MapLayer();
locationLayer.Add(myLocationOverlay);
// Добавлениее слоя MapLayer к карте.
sampleMap.Layers.Add(locationLayer);
}
private async void GetLocation()
{
// Получить текущее расположение.
Geolocator myGeolocator = new Geolocator();
Geoposition myGeoposition = await myGeolocator.GetGeopositionAsync();
Geocoordinate myGeocoordinate = myGeoposition.Coordinate;
//Вызов вспомогательного метода для конверсии координат
currentLocation = CoordinateConverter.ConvertGeocoordinate(myGeocoordinate);
}
//Центровка карты по текущему расположению
private void CenterMapOnLocation()
{
sampleMap.Center = currentLocation;
}
#endregion
// Создание локализованной панели приложения.
private void BuildLocalizedApplicationBar()
{
// Установка панели приложения на новый объект ApplicationBar.
ApplicationBar = new ApplicationBar();
ApplicationBar.Opacity = 0.5;
// Создание кнопок с локализованными надписями из AppResources.
// Переключатель включения определения местоположения.
ApplicationBarIconButton appBarButton = new ApplicationBarIconButton(new Uri("/Assets/AppBar/location.png", UriKind.Relative));
appBarButton.Text = AppResources.AppBarToggleLocationButtonText;
appBarButton.Click += ToggleLocation;
ApplicationBar.Buttons.Add(appBarButton);
// Переключатель для вывода дополнительных сведений на карте.
appBarButton = new ApplicationBarIconButton(new Uri("/Assets/AppBar/landmarks.png", UriKind.Relative));
appBarButton.Text = AppResources.AppBarToggleLandmarksButtonText;
appBarButton.Click += ToggleLandmarks;
ApplicationBar.Buttons.Add(appBarButton);
// Кнопка увеличения масштаба.
appBarButton = new ApplicationBarIconButton(new Uri("/Assets/AppBar/zoomin.png", UriKind.Relative));
appBarButton.Text = AppResources.AppBarZoomInButtonText;
appBarButton.Click += ZoomIn;
ApplicationBar.Buttons.Add(appBarButton);
// Кнопка уменьшения масштаба.
appBarButton = new ApplicationBarIconButton(new Uri("/Assets/AppBar/zoomout.png", UriKind.Relative));
appBarButton.Text = AppResources.AppBarZoomOutButtonText;
appBarButton.Click += ZoomOut;
ApplicationBar.Buttons.Add(appBarButton);
// Создание элементов меню с локализованными надписями из AppResources.
// Элемент-переключатель для определения местоположения.
ApplicationBarMenuItem appBarMenuItem = new ApplicationBarMenuItem(AppResources.AppBarToggleLocationMenuItemText);
appBarMenuItem.Click += ToggleLocation;
ApplicationBar.MenuItems.Add(appBarMenuItem);
// Элемент-переключатель для вывода меток на карте.
appBarMenuItem = new ApplicationBarMenuItem(AppResources.AppBarToggleLandmarksMenuItemText);
appBarMenuItem.Click += ToggleLandmarks;
ApplicationBar.MenuItems.Add(appBarMenuItem);
// Элемент для увеличения масштаба.
appBarMenuItem = new ApplicationBarMenuItem(AppResources.AppBarZoomInMenuItemText);
appBarMenuItem.Click += ZoomIn;
ApplicationBar.MenuItems.Add(appBarMenuItem);
// Элемент для уменьшения масштаба.
appBarMenuItem = new ApplicationBarMenuItem(AppResources.AppBarZoomOutMenuItemText);
appBarMenuItem.Click += ZoomOut;
ApplicationBar.MenuItems.Add(appBarMenuItem);
}
private enum ToggleStatus
{
ToggledOff,
ToggledOn
}
}
}
При отладке приложения в эмуляторе, как в случае с акселерометром, так и при работе с картами и системой определения местоположения, можно воспользоваться его дополнительными инструментами, рис. 47.2.
(рис 47.2) Отладка в эмуляторе приложения, использующего карты и средства определения местоположения
В этой лабораторной работе мы рассмотрели работу с акселерометром и системной определения местоположения в Windows Phone. Использование акселерометра позволяет организовать управление приложениями путём перемещения телефона в пространстве. Использование системы определения местоположение позволяет узнавать географические координаты пользователя.
Подумайте, как использование встроенных датчиков устройства может расширить возможности пользователя по управлению приложением, которое вы разрабатываете. Кроме того, проанализируйте возможности использования в приложении сервиса определения местоположения. Подготовьте отчет о проделанной работе.
К данной лекции подготовлено видеоприложение и демонстрационный программный проект.
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.