Статьи

Как создавать приложения HTML5 на Windows Phone с PhoneGap

Сначала мы увидим в этой статье, каковы дополнительные значения PhoneGap для приложений HTML5. Затем мы узнаем, как создать наш самый первый проект, в котором мы получим значения акселерометра из нашего кода JavaScript. Наконец, мы рассмотрим полный пример игрового HTML5, почти полностью перенесенный в PhoneGap, чтобы использовать акселерометр, доступный на телефонах Windows.

  1. Вступление
  2. PhoneGap: рамки, заполняющие пробел
  3. Давайте создадим наш первый проект PhoneGap
  4. Получение значений акселерометра из JavaScript
  5. Обзор полного примера с игрой HTML5 Platformer
  • Форсировать альбомную ориентацию
  • Обработка различных разрешений
  • Загрузка уровней с вызовами в файловую систему вместо использования XHR
  • Модификация игрового процесса для использования акселерометра
  • Скриншоты результата и FPS на некоторых телефонах
  • Полное решение Visual Studio для загрузки
  • Вывод
  • Вступление

    Обновление Mango для Windows Phone пришло с поддержкой HTML5 благодаря встроенному браузеру IE9 . Как и настольная версия, мобильная версия IE9 обеспечивает аппаратное ускорение с помощью графического процессора вашего Windows Phone. Таким образом, в сочетании с JavaScript IE9 теперь может служить основой для интересного пользовательского опыта, обычно зарезервированного для «собственного кода».

    HTML5 logo Преимущества использования HTML5 в качестве платформы разработки — это относительное обещание легко повторно использовать части кода на других совместимых платформах, таких как Android или iOS. В последние месяцы HTML5 вызвал много интереса в экосистеме разработчиков мобильных устройств.

    Тем не менее, даже если спецификации HTML5 / CSS3 / SVG и JavaScript сильно изменились за последние месяцы, им все еще не хватает некоторых основных функций для создания мобильных приложений . Действительно, телефон или планшет обладает такими специфическими возможностями, как: GPS, акселерометр, камера, отправка SMS, доступ к контактам и т. Д.

    Чтобы получить доступ к этим возможностям из кода JavaScript, W3C уже некоторое время работает над тем, что мы называем « Device APIs » или DAP . К сожалению, мы можем считать, что в настоящее время не существует реализации этих спецификаций, так как этот документ, кажется, подтверждает: Стандарты для веб-приложений на мобильных устройствах: текущее состояние в ноябре 2011 года и план действий . Mozilla начала интересную работу с более или менее разветвления этих спецификаций через то, что они называют веб-API для поддержки своего проекта Boot To Gecko . Тогда это хорошая новость, так как форма реализации, кажется, начинается с продолжающихся дискуссий с W3C. Однако, даже если дела начнут развиваться медленно, нам, вероятно, придется подождать несколько лет, прежде чем стабильная официальная спецификация W3C будет широко внедрена на всех платформах.

    Итак, вопрос в том, что мы должны делать в это время? Может ли HTML5 действительно удовлетворить эти сценарии?

    PhoneGap: рамки, заполняющие пробел

    Illustration of how PhoneGap works В ожидании реальных стандартизированных спецификаций у нас нет выбора: нам нужно создать мосты между JavaScript и нативным кодом целевой платформы, чтобы иметь доступ к ее возможностям. Идея заключается в следующем: взять родные языки каждой платформы (C #, Objective-C и Java) и создать платформу с этими языками, которая предоставит интерфейсы разработчику JavaScript.

    Это именно то, что делает PhoneGap . Давайте возьмем случай с Windows Phone, который является основной темой этой статьи. Проект PhoneGap в Windows Phone — это просто приложение Silverlight, содержащее элемент управления WebBrowser (и, следовательно, IE9), а также сборку Silverlight, написанную на C #, которая выполняет работу по доступу к акселерометру, GPS, контактам, камере и т. Д. Таким образом, как разработчик JavaScript, вы будете использовать DLL с именем WP7GapClassLib.dll (время выполнения ядра PhoneGap), даже не зная об этом, используя код, встроенный в файл phonegap-1.3.0.js . Эта DLL содержит некоторый код C #, который выполняет вызовы среды выполнения Silverlight, доступной на телефоне. Поскольку среда выполнения имеет доступ ко всем возможностям телефона, JavaScript также подойдет. В этом случае библиотека JavaScript будет действовать в качестве шлюза между обоими мирами. Кроме того, хорошая польза от использования этой библиотеки заключается в том, что ваш код будет работать в большинстве случаев как есть на версиях PhoneGap для Android или iOS. PhoneGap предлагает интересную форму переносимости.

    Обратите внимание на то, что поддержка PhoneGap для Windows Phone теперь полностью завершена с последней версии 1.3.0:

    Windows Phone support for PhoneGap

    Наконец, PhoneGap предлагает еще один интересный сервис. Он встраивает ваши ресурсы .js, .css, .html, .png в свои проекты, чтобы упаковать его как классическое приложение. Таким образом, вы можете использовать PhoneGap для упаковки вашего приложения HTML5 для магазинов различных приложений. Это, например, случай приложения SujiQ для Windows Phone, созданного с использованием этого подхода.

    Давайте создадим наш первый проект PhoneGap

    Предпосылки

    Вот самые первые шаги, которые вы должны выполнить:

    1. Загрузить Windows Phone SDK: Windows Phone SDK
    2. Загрузите последнюю версию телефона (1.3.0 сегодня) на их сайте: http://phonegap.com/
    3. Распакуйте загруженный файл
    4. Скопируйте файлы PhoneGapStarter.zip и PhoneGapCustom.zip в DocumentsVisual Studio 2010TemplatesProjectTemplates

    Файл-> Новый проект

    Как только предыдущие шаги будут выполнены, вы сможете создать свой первый проект PhoneGap. Запустите Visual Studio 2010, выберите шаблоны «Visual C #» и отфильтруйте их с помощью ключевого слова «Gap». Затем вы должны увидеть новый тип проекта с именем PhoneGapStarter :

    PhoneGap Starter

    Назовите свой проект « MyFirstPhoneGapProject ». После этого вы найдете файлы, о которых я говорил ранее, в обозревателе решений:

    solution explorer

    Вам только сейчас нужно вставить свое приложение HTML5 в каталог «www».

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

    никогда не трогайте файл phonegap-1.3.0.js, если вы хотите сохранить переносимый код в других версиях PhoneGap
    — все файлы, которые вы добавите в каталог «www», должны быть установлены как « Content » в окне свойств
    — вместо двоичного файла WP7GapClassLib.dll вы можете добавить ссылку на проект C7 WP7GapClassLib.csproj, доступный в каталоге Windows Phoneframework загруженного архива PhoneGap. Это поможет вам отладить или обнаружить собственный код библиотеки PhoneGap, если это необходимо.

    Хорошо, теперь давайте начнем с того, что обычно делаем по умолчанию с IE9 Mango: доступ к значениям акселерометра из JavaScript.

    Получение значений акселерометра из JavaScript

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

    Откройте страницу index.html и измените ее тело по умолчанию следующим образом:

      <Тело>
    
         <h1> Образец акселерометра </ h1>
    
         <div id = "valueX"> </ div>
    
        <div id = "valueY"> </ div>
    
         <div id = "valueZ"> </ div>
    
     </ Body> 

    Мы просто будем использовать 3 <div> для отображения текущих значений X, Y и Z акселерометра.

    Следующим шагом является замена последнего блока <script> по умолчанию на этот:

      <script type = "text / javascript">
    
         document.addEventListener ("deviceready", onDeviceReady, false);
    
         // переменная для вывода текущих значений x, y & z акселерометра
    
         var valueX;
    
         var valueY;
    
         var valueZ;
    
         // когда PhoneGap сообщает нам, что все готово, начинаем смотреть на акселерометр
    
         function onDeviceReady () {
    
             valueX = document.getElementById ("valueX");
    
             valueY = document.getElementById ("valueY");
    
             valueZ = document.getElementById ("valueZ");
    
             startWatch ();
    
     }
    
             // начать мониторинг состояния акселерометра
    
         function startWatch () {
    
             var options = {частота: 500};
    
             navigator.accelerometer.watchAcceleration (onSuccess, onError, параметры);
    
         }
    
         // если ось z вышла за пределы порога чувствительности, переместите головку аардварка в соответствующем направлении
    
         функция onSuccess (ускорение) {
    
             valueX.innerHTML = "X:" + acceleration.x;
    
             valueY.innerHTML = "Y:" + acceleration.y;
    
             valueZ.innerHTML = "Z:" + acceleration.z;
    
         }
    
         function onError () {
    
             предупреждение ( 'OnError!');
    
         }
    
     </ Скрипт> 

    Ну, код, по-моему, достаточно самоочевиден. Первое, на что следует обратить внимание, это то, что вам нужно подождать, пока событие deviceready , вызванное PhoneGap, обязательно будет в стабильном состоянии. Затем вам нужно подписаться на это событие. В нашем случае мы будем вызываться в OnDeviceReady() . Эта функция получает ссылки на 3 <div> а затем запрашивает уведомление о любых изменениях внутри акселерометра каждые 500 мс с помощью функции startWatch() . Уведомления будут отправлены в onSuccess() которая будет иметь доступ к объекту acceleration содержащему значения x, y & z. Вы найдете полную документацию на сайте PhoneGap: Документация PhoneGap — Справочник по API — Акселерометр .

    Это все, что вам нужно сделать на стороне JavaScript. Однако, чтобы это работало, вам нужно указать в свойствах проекта, что вы хотите запросить доступ к датчику устройства . Возможности, необходимые для правильного выполнения нашего приложения, перечислены в файле WMAppManifest.xml доступном в каталоге Properties . По умолчанию, начиная с 1.3.0, PhoneGap перечисляет строгие минимальные возможности:

      <Возможность>
    
         <Capability Name = "ID_CAP_IDENTITY_DEVICE" />
    
         <Capability Name = "ID_CAP_IDENTITY_USER" />
    
         <Capability Name = "ID_CAP_LOCATION" />
    
         <Capability Name = "ID_CAP_NETWORKING" />
    
         <Capability Name = "ID_CAP_WEBBROWSERCOMPONENT" />
    
     </ Возможности> 

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

      <Capability Name = "ID_CAP_SENSORS" /> 

    Чтобы получить доступ к акселерометру, вы можете найти полный список всех доступных возможностей здесь: Файл манифеста приложения для Windows Phone

    Хорошо, мы логически готовы проверить это внутри эмулятора на первом этапе. Нажмите на волшебную клавишу «F5» и давайте посмотрим на результат:

    emulator

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

    Вы можете скачать полный исходный код этого первого решения здесь : http://david.blob.core.windows.net/html5/MyFirstPhoneGapProject.zip

    Проблемы с телефонами, использующими французский язык

    Если вы тестируете тот же код на своем телефоне, настроенном для использования французского языка (как, например, мой!), У вас будет ощущение, что приложение вообще не работает… что действительно так. Я потратил некоторое время на отладку кода и обнаружил следующее исключение в phonegap-1.3.0.js :

    «Ошибка при успешном обратном вызове: акселерометр = синтаксическая ошибка»

    После сброса значений я увидел, что ошибка произошла из-за предварительной десериализации следующей плохо отформатированной строки JSON:

    «{« X »: 0,00472,« y »: — 0,19879,« z »: — 0,98115}», тогда как правильный EN-US следующий: «{« x »: 0,00472,» y «: -0,19879,» г»: — 0,98115}»

    Да, мы используем запятую во Франции в качестве разделителя чисел.

    2 решения для решения этой проблемы:

    1 — Ленивый: переключите свой телефон на EN-US (я знаю, это не решение!)
    2 — Исправить проблему, которая исходит из кода C #. Для этого замените следующий код из файла WP7GalClassLib библиотеки WP7GalClassLib :

      /// <summary>
    
     /// Форматирует текущие координаты в формат JSON
    
     /// </ summary>
    
     /// <Return> Координаты в формате JSON </ Return>
    
     приватная строка GetCurrentAccelerationFormatted ()
    
     {
    
         string resultCoordinates = String.Format ("" x ": {0}," y ": {1}," z ": {2}",
    
     accelerometer.CurrentValue.Acceleration.X.ToString ( "0.00000"),
    
     accelerometer.CurrentValue.Acceleration.Y.ToString ( "0.00000"),
    
     accelerometer.CurrentValue.Acceleration.Z.ToString ( "0.00000"));
    
         resultCoordinates = "{" + resultCoordinates + "}";
    
         вернуть resultCoordinates;
    
     } 

    Этим:

      приватная строка GetCurrentAccelerationFormatted ()
    
     {
    
         string resultCoordinates = String.Format ("" x ": {0}," y ": {1}," z ": {2}",
    
             accelerometer.CurrentValue.Acceleration.X.ToString ("0.00000", CultureInfo.InvariantCulture),
    
             accelerometer.CurrentValue.Acceleration.Y.ToString ("0.00000", CultureInfo.InvariantCulture),
    
             accelerometer.CurrentValue.Acceleration.Z.ToString ("0.00000", CultureInfo.InvariantCulture));
    
         resultCoordinates = "{" + resultCoordinates + "}";
    
         вернуть resultCoordinates;
    
     } 

    И образец теперь будет работать со всеми локалями. Я подал ошибку по этой теме здесь: https://issues.apache.org/jira/browse/CB-141, предлагая то же решение, которое обычно будет поставляться в следующей версии (2.0.0).

    Кстати, вы, возможно, задаетесь вопросом, как мне удалось отладить часть JavaScript моего проекта PhoneGap? Ну, вы можете просто использовать замечательный проект jsConsole . Если вы хотите узнать больше об этом, прочитайте одну из статей моего коллеги: удаленная отладка jsConsole в IE9 в Windows Phone Mango

    Обзор полного примера с игрой HTML5 Platformer

    Давайте теперь рассмотрим более сложный образец. Моя идея состояла в том, чтобы начать с игры, которую я написал раньше. Он представлен в этой статье: HTML5 Platformer: полный порт игры XNA для <canvas> с EaselJS . Я хотел посмотреть, что я должен сделать, чтобы это работало на телефоне.

    Первый шаг — просто скопировать / вставить разные файлы .js, .png, .css в каталог «www» и пометить их как « Content ». Вот другие шаги, чтобы следовать.

    Форсировать альбомную ориентацию

    В игру нужно играть в ландшафтном режиме. Я тогда заставил эту ориентацию. Я также удалил информационную панель сбоку (системный трей). Для этого вам нужно открыть файл MainPage.xaml и изменить эти свойства:

      SupportedOrientations = "Landscape" Orientation = "Landscape" shell: SystemTray.IsVisible = "False" 

    Обработка различных разрешений

    Поскольку моей главной целью было создание игры, которая могла бы работать на наибольшем количестве устройств, мне нужно обрабатывать множество разных разрешений.

    Для этого я немного изменил исходный код Platformer, который вы можете скачать в другой статье . Теперь игра может работать при любом разрешении, применяя коэффициент масштабирования к изображениям и спрайтам для рисования. Все перерисовывается на основе определенного соотношения, полученного от Windows Phone (800 × 480), что составляет соотношение 100%. Вы можете протестировать эту версию в вашем настольном браузере здесь: HTML5 Platformer ReScale и попытаться динамически изменить размер окна браузера. Более того, если ваше разрешение экрана имеет соотношение сторон 16/9, нажмите клавишу F11, чтобы играть в полноэкранном режиме! Опыт в этом режиме действительно крут, как вы можете видеть на этом скриншоте:

    fullscreen screenshot

    Мы позволяем браузеру позаботиться о сглаживании во время этой операции масштабирования. В зависимости от используемого вами браузера вы также заметите, что производительность может сильно зависеть от размера окна, которое у вас будет. На моей машине IE9 / IE10 кажется относительно безразличным к полноэкранному режиму или небольшим разрешениям, поддерживая стабильную частоту кадров 60 кадров в секунду.

    Загрузка уровней с вызовами в файловую систему вместо использования XHR

    В исходном коде файлы .TXT, связанные с каждым уровнем, сохранялись на веб-сервере и загружались с помощью вызовов XmlHttpRequest. Поскольку сейчас мы выполняем все на стороне клиента в автономном режиме, локальные вызовы XHR не очень подходят. Затем я заменил исходный код функции PlatformerGame.prototype.LoadNextLevel следующим:

      PlatformerGame.prototype.LoadNextLevel = function () {
    
         this.levelIndex = (this.levelIndex + 1)% numberOfLevels;
    
         // Поиск, где мы в настоящее время размещены
    
         var nextFileName = "app / www / assets / level /" + this.levelIndex + ".txt";
    
         пытаться {
    
             var instance = this;
    
             window.requestFileSystem (LocalFileSystem.PERSISTENT, 0, gotFS, fail);
    
             function gotFS (fileSystem) {
    
                 fileSystem.root.getFile (nextFileName, null, gotFileEntry, fail);
    
             }
    
             function gotFileEntry (fileEntry) {
    
                 fileEntry.file (gotFile, fail);
    
             }
    
             function gotFile (file) {
    
                 readAsText (файл);
    
             }
    
             function readAsText (file) {
    
                 var reader = new FileReader ();
    
                 reader.onloadend = function (evt) {
    
     instance.LoadThisTextLevel (evt.target.result.replace (/ [nrt] / g, ''));
    
                 };
    
                 reader.readAsText (файл);
    
             }
    
             сбой функции (evt) {
    
                 console.log (evt.target.error.code);
    
             }
    
         }
    
         поймать (е) {
    
             console.log («Ошибка загрузки уровня:» + e.message);
    
             // Возможно, доступ запрещен, если вы попытаетесь запустить из файла: // context
    
             // Загрузка уровня жестко запрограммированной ошибки, чтобы иметь хоть что-то для игры
    
             this.LoadThisTextLevel (hardcodedErrorTextLevel);
    
         }
    
     }; 

    Я только что повторно использовал код, доступный в документации PhoneGap: FileReader . Как видите, у вас есть полный доступ к файловой системе Windows Phone из JavaScript с PhoneGap.

    Полезный совет: чтобы помочь вам отладить то, что действительно хранится в изолированном хранилище телефона или нет, вы должны взглянуть на этот замечательный инструмент: IsoStoreSpy, написанный Сэмюэлем Бланшаром.

    Модификация игрового процесса для использования акселерометра

    Ну, а последняя часть — просто смешать все части этой статьи, чтобы получить окончательный результат. Для этого я добавил следующий код в конструктор объекта Player в файле Player.js :

      var options = {частота: 500};
    
     вар то = это;
    
     navigator.accelerometer.watchAcceleration (
    
           function (акселерометр) {that.moveDirectionAccel (акселерометр);  },
    
           function () {console.log ("Ошибка с акселерометром");  },
    
           параметры); 

    Вот функция, которая будет вызываться при изменениях акселерометра:

      Player.prototype.moveDirectionAccel = function (ускорение) {
    
         var accelValue = -acceleration.y;
    
         // Переместить игрока с акселерометром
    
         if (Math.abs (accelValue)> 0,15) {
    
              // устанавливаем скорость движения
    
              this.direction = Math.clamp (accelValue * this.AccelerometerScale, -1, 1);
    
         }
    
         еще {
    
             this.direction = 0;
    
         }
    
     }; 

    Я также добавил обработчик события onmousedown на холсте, чтобы переходить, когда пользователь нажимает на экран.

    Скриншоты результата и FPS на некоторых телефонах

    Сначала рассмотрим результат в эмуляторе Windows Phone:

    review the emulator

    У нас есть частота кадров от 54 до 60 кадров в секунду на моей машине. На реальном устройстве частота кадров логически отличается между моделями. Давайте возьмем первый игровой уровень. На LG E900 частота кадров составляет около 22 кадров в секунду . На HTC Radar скорость составляет около 31 кадра в секунду . На Nokia Lumia 800 он составляет около 42 кадров в секунду .

    framerates

    Игровой процесс может быть не очень убедительным в большинстве случаев. Действительно, я использую полноэкранный холст, чтобы нарисовать всю игру. Это не очень хорошая идея для мобильного процессора с ограниченной мощностью, даже если Nokia кажется достаточно мощной, чтобы справиться с этим подходом. Лучшая методология могла бы заключаться в том, чтобы разрезать экранную сцену на различные маленькие холсты, которые затем будут перемещены путем изменения свойств CSS на них. Это то, что было сделано для HTML5-версии Angry Birds, например. Некоторые игровые платформы JS начинают задумываться о том, как справиться с этой сложностью. Идея заключалась бы в том, чтобы один раз кодировать игру с помощью API высокого уровня, и среда могла переключаться между полнокадровым холстом или различным небольшим холстом, перемещаемым через CSS, на основе производительности.

    Что ж, вы поймете: игровые возможности HTML5 на мобильных устройствах только начинаются. Но его будущее выглядит очень многообещающе!

    Полное решение Visual Studio для загрузки

    Вы найдете полный исходный код HTML5 Platformer для PhoneGap здесь : HTML5GapPlatformer.zip

    Другие полезные ресурсы

    Вывод

    PhoneGap предлагает интересные перспективы, чтобы помочь вам писать приложения на телефоне. Это позволяет вам использовать ваши существующие навыки в JavaScript, HTML и CSS. PhoneGap не обязательно покрывает все сценарии, доступные в настоящее время с собственным стеком разработки (Silverlight или XNA). Но это может быть что-то, на что стоит обратить внимание, если вы хотите извлечь выгоду из навыков HTML одной из вашей команды. Вам нужно будет обратить внимание, чтобы правильно определить, над каким проектом работать.

    Вы также можете подумать о смешении обеих сред для создания гибридных приложений: основная ветка будет написана с использованием «HTML5», а некоторые конкретные части — в нативный код. Используя эту идею, были созданы некоторые плагины, чтобы немного продвинуть интеграцию в Metro UI: плагины PhoneGap для Windows Phone . Например, вы найдете один из них, позволяющий коду JavaScript обновлять тайлы.

    Наконец, PhoneGap и HTML5 могут позволить относительную переносимость на другие платформы … с некоторыми ограничениями. Но это обширная тема со страстными дебатами, которая потребует полной специальной статьи.

    Эта статья была первоначально опубликована в блоге автора MSDN . Переиздано с разрешения.