Utilizando o Giroscópio no Windows Phone

Você precisa estar logado para dar um feedback. Clique aqui para efetuar o login
Para efetuar o download você precisa estar logado. Clique aqui para efetuar o login
Confirmar voto
0
 (2)  (0)

Veja neste artigo como utilizar o recurso de giroscópio no Windows Phone através de um exemplo prático em uma aplicação.

Em diversas situações o dispositivo é utilizado como entrada de dados para os aplicativos, como em jogos que utilizam movimentos como controles, e o Windows Phone suporta vários tipos de sensores que permitem que a aplicação capte a orientação e o movimento do aparelho.

A função do giroscópio é medir a velocidade nos eixos X, Y e Z, e possui uma sensibilidade a ponto de indicar a rotação até mesmo com o aparelho parado, porém o giroscópio é opcional nos aparelhos.

Smartphone da HTC com Windows Phone

Figura 1: Smartphone da HTC com Windows Phone

Observação: por ser opcional, é essencial que as aplicações verifiquem se o aparelho possui o giroscópio e caso não possua, adaptem o aplicativo para o uso sem o mesmo. No Windows Phone existem recursos para verificar e decidir a melhor maneira de utilizá-los.

Infelizmente para testar o exemplo a ser mostrado neste artigo você necessitará de um device real, portanto fique avisado que caso vá testar o aplicativo no emulador, será mostrado no estado da aplicação que o device não possui giroscópio.

Abra o Visual Studio e crie um projeto do tipo Windows Phone Application chamado GiroscopioApplication, conforme a Figura 2.

Criação do projeto GiroscopioApplication no Visual Studio

Figura 2: Criação do projeto GiroscopioApplication no Visual Studio

Ao criar o projeto é exibida uma caixa com a opção de escolha da versão do Windows Phone, escolha a 7.1, pois assim o seu aplicativo funcionará em todas as versões de Windows Phone disponíveis.

Agora você deve adicionar uma nova referência, para isso vá ao Solution Explorer e clique com o botão direito em Reference, e depois Add Reference. Será exibida uma janela com diversas opções e você deverá selecionar o Microsoft.XNA.Framework e o Microsoft.Devices.Sensors, conforme a Figura 3.

Adicionando referência ao projeto

Figura 3: Adicionando referência ao projeto

Agora você deverá alterar o layout da página principal, para isso abra a MainPage.xaml e no ContentPanel adicione os controles necessários para a visualização dos dados. Você terá um label para informar o estado da aplicação, linhas que mostrarão os valores de X, Y e Z e etc. Veja como ficará a MainPage.xaml com os controles adicionados na Listagem 1.

Listagem 1: Arquivo MainPage.xaml

<phone:PhoneApplicationPage 
    x:Class="GiroscopioApplication.MainPage"
    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"
    mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768"
    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 x:Name="ApplicationTitle" Text="APLICATIVO SENSOR"
 Style="{StaticResource PhoneTextNormalStyle}"/>
            <TextBlock x:Name="PageTitle" Text="giroscópio" 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">
            <StackPanel Orientation="Vertical">
                <StackPanel Orientation="Vertical">
                    <TextBlock Height="30" Name="lblStatus" Text="Estado: "
 VerticalAlignment="Top" />
                    <TextBlock Height="30" Name="lblAtualizacoes"
 Text="Intervalo de atualizações: " VerticalAlignment="Top" />
                </StackPanel>
                <TextBlock Text="Velocidade Rotacional:" />
                <Grid>
                    <TextBlock Height="30" HorizontalAlignment="Left"
 Name="lblXAtual" Text="X: 1.0" VerticalAlignment="Top"
 Foreground="Red" FontSize="28" FontWeight="Bold" />
                    <TextBlock Height="30" HorizontalAlignment="Center"
 Name="lblYAtual" Text="Y: 1.0" VerticalAlignment="Top" Foreground="LightGreen"
 FontSize="28" FontWeight="Bold" />
                    <TextBlock Height="30" HorizontalAlignment="Right"
 Name="lblZAtual" Text="Z: 1.0" VerticalAlignment="Top" Foreground="LightBlue"
 FontSize="28" FontWeight="Bold" />
                </Grid>
                <Grid Height="140">
                    <Line x:Name="currentXLine" X1="240" Y1="40" X2="240"
 Y2="40" Stroke="Red" StrokeThickness="14" />
                    <Line x:Name="currentYLine" X1="240" Y1="40" X2="240"
 Y2="40" Stroke="LightGreen" StrokeThickness="14" />
                    <Line x:Name="currentZLine" X1="240" Y1="40" X2="240"
 Y2="40" Stroke="Blue" StrokeThickness="14" />                    
                </Grid>
                <TextBlock Text="cumulative rotation (degrees)"/>
                <Grid>
                    <TextBlock Height="30" HorizontalAlignment="Left"
 Name="lblXAcumulado" Text="X: 1.0" VerticalAlignment="Top" Foreground="Red"
 FontSize="28" FontWeight="Bold" />
                    <TextBlock Height="30" HorizontalAlignment="Center"
 Name="lblYAcumulado" Text="Y: 1.0" VerticalAlignment="Top" Foreground="LightGreen"
 FontSize="28" FontWeight="Bold" />
                    <TextBlock Height="30" HorizontalAlignment="Right"
 Name="lblZAcumulado" Text="Z: 1.0" VerticalAlignment="Top" Foreground="LightBlue"
 FontSize="28" FontWeight="Bold" />
                </Grid>
                <Grid Height="200" Name="grdAcumulo">
                    <Line x:Name="lnX" X1="240" Y1="100" X2="240" Y2="0"
 Stroke="Red" StrokeThickness="14" />
                    <Line x:Name="lnY" X1="240" Y1="100" X2="240" Y2="0"
 Stroke="LightGreen" StrokeThickness="14" />
                    <Line x:Name="lnZ" X1="240" Y1="100" X2="240" Y2="0"
 Stroke="LightBlue" StrokeThickness="14" />
                </Grid>
                <Button Content="Start" Height="72" Name="btnStart"
 Click="btnStart_Click" />
            </StackPanel>
        </Grid>
    </Grid>

</phone:PhoneApplicationPage>

Sua aplicação deverá estar conforme a Figura 4.

Layout da página principal, após alteração da MainPage.xaml

Figura 4: Layout da página principal, após alteração da MainPage.xaml

Agora você deverá tratar o método do evento de click do botão Start e adicionar mais dois métodos na classe, um para ser chamado a certo intervalo de tempo e alterar as informações e um outro método para exibir as informações após a coleta. Verifique como ficará a classe MainPage.xaml.cs na Listagem 2.

Você também deve adicionar a referência no topo para System.Windows.Threading, Microsoft.XNA.Framework, e Microsoft.Devices.Sensors.

Lembrando que como alguns devices não possuem giroscópio, então no construtor é feita a verificação e caso não possua, impossibilita o teste pelo click do botão.

Listagem 2: Código da classe MainPage.xaml.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;
using System.Windows.Threading;
using Microsoft.Xna.Framework;
using Microsoft.Devices.Sensors;

namespace GiroscopioApplication
{
    public partial class MainPage : PhoneApplicationPage
    {

        Gyroscope giroscopio;
        DispatcherTimer timer;

        Vector3 taxaRotacao = Vector3.Zero;
        Vector3 rotacaoAcumulada = Vector3.Zero;
        DateTimeOffset ultimaAtualizacao = DateTimeOffset.MinValue;
        bool isDataValid;

        // Constructor
        public MainPage()
        {
            InitializeComponent();
            if (!Gyroscope.IsSupported)
            {
                lblStatus.Text = "Não há suporte de giroscópio para o aparelho";
                btnStart.IsEnabled = false;
            }
            else
            {
                timer = new DispatcherTimer();
                timer.Interval = TimeSpan.FromMilliseconds(60);
                timer.Tick += timer_Tick;
            }
        }

        void timer_Tick(object sender, EventArgs e)
        {
            if (isDataValid)
            {
                lblStatus.Text = "Recebendo informações....";           
            }

            lblXAtual.Text = taxaRotacao.X.ToString("0.000");
            lblYAtual.Text = taxaRotacao.Y.ToString("0.000");
            lblZAtual.Text = taxaRotacao.Z.ToString("0.000");

            lblXAcumulado.Text =
 MathHelper.ToDegrees(rotacaoAcumulada.X).ToString("0.00");
            lblYAcumulado.Text =
 MathHelper.ToDegrees(rotacaoAcumulada.Y).ToString("0.00");
            lblZAcumulado.Text =
 MathHelper.ToDegrees(rotacaoAcumulada.Z).ToString("0.00");

            double centerX = grdAcumulo.ActualWidth / 2.0;
            double centerY = grdAcumulo.ActualHeight / 2.0;

            currentXLine.X2 = centerX + taxaRotacao.X * 100;
            currentYLine.X2 = centerX + taxaRotacao.Y * 100;
            currentZLine.X2 = centerX + taxaRotacao.Z * 100;

            lnX.X2 = centerX - centerY * Math.Sin(rotacaoAcumulada.X);
            lnX.Y2 = centerY - centerY * Math.Cos(rotacaoAcumulada.X);

            lnY.X2 = centerX - centerY * Math.Sin(rotacaoAcumulada.Y);
            lnY.Y2 = centerY - centerY * Math.Sin(rotacaoAcumulada.X);

            lnZ.X2 = centerX - centerY * Math.Cos(rotacaoAcumulada.X);
            lnZ.Y2 = centerY - centerY * Math.Sin(rotacaoAcumulada.Y);
        }

        void giroscopio_CurrentValueChanged(object sender,
 SensorReadingEventArgs<GyroscopeReading> e)
        {
            isDataValid = giroscopio.IsDataValid;
            if (ultimaAtualizacao.Equals(DateTimeOffset.MinValue))
            {
                ultimaAtualizacao = e.SensorReading.Timestamp;
            }
            else
            {
                taxaRotacao = e.SensorReading.RotationRate;
                TimeSpan timeSinceLastUpdate =
 e.SensorReading.Timestamp - ultimaAtualizacao;
                rotacaoAcumulada +=
 taxaRotacao * (float)(timeSinceLastUpdate.TotalSeconds);
                ultimaAtualizacao = e.SensorReading.Timestamp;
            }
        }

        private void btnStart_Click(object sender, RoutedEventArgs e)
        {
            if (giroscopio != null && giroscopio.IsDataValid)
            {
                giroscopio.Stop();
                timer.Stop();
                lblStatus.Text = "Giroscópio parado";
            }
            else
            {
                if (giroscopio == null)
                {
                    giroscopio = new Gyroscope();
                    giroscopio.TimeBetweenUpdates = TimeSpan.FromMilliseconds(20);
                    lblAtualizacoes.Text = "Intervalo de atualizações: " +
 giroscopio.TimeBetweenUpdates.TotalMilliseconds + " ms";

                    giroscopio.CurrentValueChanged += giroscopio_CurrentValueChanged;
                }
            }
            try
            {
                lblStatus.Text = "Iniciando o giroscópio";
                giroscopio.Start();
                timer.Start();
            }
            catch (Exception)
            {
                lblStatus.Text = "Não é possível iniciar o giroscópio";
            }
        }
    }
}

Basta agora conectar seu dispositivo, alterar o modo de debug para device, conforme a Figura 5, pressionar F5 e testar a aplicação.

Alterando o modo de debug para Device

Figura 5: Alterando o modo de debug para Device

Um abraço e até o próximo artigo.

Conheça nosso curso de Introdução ao Windows Phone.

Leia também

 
Você precisa estar logado para dar um feedback. Clique aqui para efetuar o login
Receba nossas novidades
Ficou com alguma dúvida?