Статьи

Доступ к акселерометру из HTML5 и Javascript с помощью Windows Phone 7


В моем
предыдущем посте  я обсуждал, как заставить код Javascript, размещенный в элементе управления WebBrowser, выполнять код .NET в хост-приложении и наоборот. Я также продемонстрировал, как получать и отображать информацию о состоянии устройства с помощью HTML5, размещенного в элементе управления WebBrowser.

Для этого примера я хотел бы продемонстрировать, как получить доступ к
 датчику
акселерометра из HTML5 и Javascript. Чтобы сделать вещи более интересными, данные чтения акселерометра будут постоянно обновляться каждые 100 миллисекунд, а код .NET будет неоднократно вызывать метод Javascript по мере обновления данных чтения акселерометра

 А вот код …

Default.html (HTML5 + Javascript)

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

<!DOCTYPE html>

<html>

<head>

    <meta name="viewport" content="width=480, height=800, user-scalable=no" />

    <meta name="MobileOptimized" content="width" />

    <meta name="HandheldFriendly" content="true" />

    <title>HTML5 and Windows Phone 7</title>

    <style>

        body

        {

            color: White;

            background-color: Black;

            font-family: 'Segoe WP Semibold';

            text-align: left;

        }

        h3

        {

            font-size: 20pt;

        }

        input

        {

            color: #ffffff;

            background-color: #000000;

            border: 2px solid white;

            vertical-align: baseline;

            font-size: 17pt;

            min-width: 40px;

            min-height: 40px;

            margin: 5;

        }

    </style>

</head>

<body onload="onLoad()">

    <div>

        <h3>

            X:</h3>

        <input id="x" type="text" value="0" />

        <h3>

            Y:</h3>

        <input id="y" type="text" value="0" />

        <h3>

            Z:</h3>

        <input id="z" type="text" value="0" />

    </div>

    <script type="text/javascript">

        function onLoad() {

            window.external.notify("startAccelerometer");

        }

 

        function accelerometerCallback(x, y, z) {

            document.getElementById("x").value = x;

            document.getElementById("y").value = y;

            document.getElementById("z").value = z;

        }

    </script>

</body>

</html>

 

MainPage.xaml

The code below is the main page of the Silverlight application that will host the HTML content

<phone:PhoneApplicationPage x:Class="PhoneApp.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"
                           Loaded="PhoneApplicationPage_Loaded">
    <Grid x:Name="LayoutRoot"
         Background="Transparent">
        <phone:WebBrowser Name="browser"
                         IsScriptEnabled="True"
                         Source="HTML/Default.html"
                         ScriptNotify="browser_ScriptNotify" />
    </Grid>
</phone:PhoneApplicationPage>

MainPage.xaml.cs

А вот код файла xaml

public partial class MainPage : PhoneApplicationPage

{

    private Microsoft.Devices.Sensors.Accelerometer accelerometer;

 

    public MainPage()

    {

        InitializeComponent();

    }

 

    private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)

    {

        using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication())

        {

            if (!store.DirectoryExists("HTML")) store.CreateDirectory("HTML");

            CopyToIsolatedStorage("HTML\\Default.html", store);

        }

    }

 

    private static void CopyToIsolatedStorage(string file, IsolatedStorageFile store, bool overwrite = true)

    {

        if (store.FileExists(file) && !overwrite)

            return;

 

        using (Stream resourceStream = Application.GetResourceStream(new Uri(file, UriKind.Relative)).Stream)

        using (IsolatedStorageFileStream fileStream = store.OpenFile(file, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite))

        {

            int bytesRead;

            var buffer = new byte[resourceStream.Length];

            while ((bytesRead = resourceStream.Read(buffer, 0, buffer.Length)) > 0)

                fileStream.Write(buffer, 0, bytesRead);

        }

    }

 

    private void browser_ScriptNotify(object sender, NotifyEventArgs e)

    {

        if (e.Value == "startAccelerometer")

        {

            if (accelerometer == null)

            {

                accelerometer = new Microsoft.Devices.Sensors.Accelerometer { TimeBetweenUpdates = TimeSpan.FromMilliseconds(100) };

                accelerometer.CurrentValueChanged += (o, args) => Dispatcher.BeginInvoke(() =>

                {

                    var x = args.SensorReading.Acceleration.X.ToString("0.000");

                    var y = args.SensorReading.Acceleration.Y.ToString("0.000");

                    var z = args.SensorReading.Acceleration.Z.ToString("0.000");

 

                    browser.InvokeScript("eval", string.Format("accelerometerCallback({0},{1},{2})", x, y, z));

                });

                accelerometer.Start();

            }

        }

    }

}

В приведенном выше коде происходит то, что выполняется метод Javascript, который уведомляет хост-приложение о необходимости запустить акселерометр после загрузки HTML. Затем мы добавляем обработчик события в событие Accelerometers
CurrentValueChanged, который вызывает метод Javascript accelerometerCallback и передает в качестве аргументов данные чтения акселерометра. Обратите внимание, что я использую
eval в качестве метода Javascript для вызова и передачи вызова метода в качестве аргумента, это связано с тем, что данные чтения акселерометра извлекаются в рабочем потоке и по какой-то причине возникает неизвестная системная ошибка даже при выполнении кода в потоке пользовательского интерфейса. через метод Page Dispatcher.BeginInvoke (). Я понял, что с помощью
Evalбыл единственный способ выполнить код Javascript из рабочего потока .NET.

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