Миграция приложения с Windows 8 на Windows 8.1

Источник: habrahabr
kichik

Миграция приложений на новую версию операционной системы - это всегда непростой вопрос. Ключевое значение имеет нахождение правильного баланса между внедрением новой функциональности, поддержкой кода и наличием целевой аудитории.

Все эти параметры индивидуальны для каждого проекта, и в определенном смысле зависят друг от друга.

Например, Windows Store позволяет размещать разные сборки приложения для Windows 8 и Windows 8.1: приложения, собранные под Windows 8 работают на Windows 8.1, но не наоборот. Вы можете вложить свои усилия в добавление необходимой новой функциональности в сборку под Windows 8, которая будет доступна как тем, кто обновился, так и тем, кто этого еще не сделал, получая сразу всю аудиторию и радуя ее всю новыми приятностями. Либо вы можете вложиться в добавление новых возможностей только под Windows 8.1, что может быть заметно проще (а значит, вы сможете сделать еще больше хорошего для пользователей), но при этом аудитория Windows 8 не будет получать никаких обновлений.

На картинке выше приведены эти две условные стратегии - обе в предположении, что у вас уже есть какое-то приложение под Windows 8. Во многих случаях правильной будет верхняя стратегия: заморозить версию под Windows 8 - и начать развивать версию под Windows 8.1.

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

Очевидно, что рано или поздно большинство пользователей перейдет с Windows 8 на Windows 8.1, но конкретная скорость перехода может зависеть от множества параметров: от доступности интернета в регионе до it-политик внутри организации. Соответственно, например, с точки зрения монетизации, вам нужно задаться вопросом: каков объем рынка внутри именно Windows 8 (без обновления), учитывая уменьшающуюся динамику.

И еще: в зависимости от конкретной функциональности приложения, возможно, вам с лихвой хватает возможностей Windows 8

Что важно учитывать

В разрезе перехода от Windows 8 к Windows 8.1 нужно учитывать также следующие "нюансы":

  • Работа с XAML и HTML в Windows 8.1 осуществляется быстрее и энергоэффективнее. Даже простая миграция без изменения кода (просто перенацеливание на новую платформу) может привести к улучшению отзывчивости приложения.
  • В Windows 8.1 добавились новые элементы управления, которые позволяют многие вещи делать проще. Например, тот же Hub, или готовые Flyout элементы в XAML. Иногда это может существенно сэкономить время разработки. (Я тут еще не говорю о многих новых API).
  • В магазине для Windows 8.1 есть новые возможности по монетизации, включая потребляемые ресурсы для встраиваемых платежей.
  • В Windows 8.1 обновилось поведение приложения на экране (новые режимы отображения) и также изменилось то, как работает поиск. Приложения, собранные под Windows 8, будут работать в режиме совместимости.

Как мигрировать приложение

Прежде всего, для миграции вам понадобятся Windows 8.1 и Visual Studio 2013. Как только вы запустите свой проект для Windows 8 в новой студии, вам будет автоматически предложено обновить приложение под Windows 8.1:

Здесь же вам предложат почитать про новые возможности в Windows 8.1 и узнать о тонкостях миграции кода. Рекомендую обратить внимание на то, что часть API помечена как устаревшая и может перестать работать.

Чтобы "ручками" перенацелить проекты вашего решения под Windows 8.1, достаточно выбрать соответствующий пункт в контекстном меню каждого из проектов:

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

Производительность

Для любопытствующих советую также провести эксперимент с тем, как приложение работает до и после перенацеливания. Для этого в VS2013 можно забраться в отладку и найти там пункт "Performance and Diagnostics", после чего можно выбрать подходящий тест:

Например, давайте сравним отзывчивость XAML-интерфейса. В качестве подопытного кролика я буду использовать приложение "Изучаем Windows 8".

Результаты Windows 8 приложения на Windows 8.1:

Здесь значительно время вначале занимает как парсинг appx.xaml, так и собственно обработка страниц приложения.

А вот результаты этого же приложения после перенацеливания на Windows 8.1 (и без изменения кода) в том же масштабе:

(На паузу между страницами можно не обращать внимания, кроме того, что небольшой всплеск в середине - это прокрутка GridView.)

Неплохое улучшение, не правда ли?

Отображение приложения на экране

Приложения на Windows 8 могли работать в трех режимах: Fill, Full и Snapped.

В Windows 8.1 у приложений (точнее у пользователя) появилось намного больше гибкости в расположении на экране - и они могут занимать любую ширину вплоть до 500px (по умолчанию) или 320 (опционально).

Однако, если приложение было собрано под Windows 8, при недостатке места оно будет отображаться в Snapped View с серыми полосками по бокам (режим совместимости):

Как только вы перенацелите приложение под Windows 8.1, оно сразу же начнет использовать общий (Full) вид отображения на ширине вплоть до 500px:

В этом месте вам стоит задуматься над тем, как ваше приложение ведет себя в таком достаточно узком пространстве! Обратите внимание, что оно должно оставаться полностью функциональным.

Шаг назад: что стало с нашим Snapped View? По умолчанию после миграции (и для новых проектов) для приложений выставляется минимальная поддерживаемая ширина в 500px. Вы можете в манифесте указать, что ваше приложение хорошо справляется и с 320px:

В этом случае в промежутке от 320 до 500px ваше приложение будет переключаться в то, что раньше называлось Snapped view:

Здесь вам надо еще раз задуматься, перечитать инструкцию по миграции и понять, что у вас в проекте теперь оказался устаревший (deprecated) код.

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

public virtual void InvalidateVisualState() { if (_layoutAwareControls != null) { string visualState = DetermineVisualState(ApplicationView.Value); /* Это нужно обновить */ foreach (Control layoutAwareControl in _layoutAwareControls) { VisualStateManager.GoToState(layoutAwareControl, visualState, false); } } }

Строчка с извлечением состояния из ApplicationView теперь устарела - внутри DetermineVisualState из поля Value бралось строковое значение. В Windows 8.1 вам нужно переключать состояние в зависимости от доступной ширины приложения:

protected virtual string DetermineVisualState() { var windowWidth = Window.Current.Bounds.Width; var windowHeight = Window.Current.Bounds.Height; string viewState; if (windowWidth < 500) { viewState = "Snapped"; } else if (windowWidth < windowHeight) { viewState = "FullScreenPortrait"; } else { viewState = "FullScreenLandscape"; } return viewState; }

Здесь я убрал параметры у функции DetermineVisualState, а внутри нее пришлось добавить явный выбор состояния в зависимости от ширины и высоты окна.

Кстати, так как обе функции виртуальные, возможно, где-то внутри вашего проекта, вы также дополнительно обновляли логику переключения режимов. Наверное, стоит воспользоваться поиском… либо прекрасной возможность VS2013 посмотреть, где еще в проекте используется конкретный метод:

Тестируем, убеждаемся, что все работает.

Поиск

Следующий важный пункт нашей программы миграции - поиск. В Windows 8.1 мы учли две вещи:

  • Трудности с обнаружением поиска пользователями
  • Потребность объединения поиска из разных мест в единый интерфейс

Поэтому у нас есть теперь красивый поиск "powered by Bing", сочетающий поиск по файлам, вебу, магазину и приложениям:

… и рекомендация внедрять поиск внутрь приложения с использованием SearchBox.

Возможно, вы как и мы, обновляя приложения, волнуетесь, что же стало с контрактом Поиска? Он по-прежнему присутствует и работает для вашего приложения, когда оно запущено:

Однако, как вы можете заметить на скриншоте выше, по умолчанию ищет везде, а не в вашем конкретном приложении. Из выпадающего списка можно переключиться на приложение:

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

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

Наша кнопка выглядит как значок поиска в кружочке:

Это обычная кнопка (Button) с нужным символом внутри (), правильным шрифтом (Segoe UI Symbol) и подобранными стилями.

<UserControl x:Class="EventsApp.UserControls.SearchButton" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:EventsApp.UserControls" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"> <Grid> <Button x:Name="searchButton" Content="searchIconCodeHere" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" FontFamily="Segoe UI Symbol" Margin="0" FontSize="24" Tapped="searchButton_Tapped" FontWeight="Normal"> ... </Button> </Grid> </UserControl>

По нажатию на кнопку срабатывает соответствующее событие:

private void searchButton_Tapped(object sender, Windows.UI.Xaml.Input.TappedRoutedEventArgs e) { Windows.ApplicationModel.Search.SearchPane.GetForCurrentView().Show(); }

Осталось вставить кнопку на страницы приложения. Теперь при активации поиска из приложения SearchPane показывается с правильными настройками.

Кстати, рекомендую добавить такую кнопку даже для приложений, собранных под Windows 8 -> она продолжить правильно работать у пользователей под Windows 8.1, если вы им не предоставляете отдельную сборку.

SearchBox

Естественно, вы можете сделать поиск еще ближе к пользователю. Для этого в приложение можно добавить элемент управления SearchBox, который будет позволять искать сразу внутри приложения, не переключаясь на дополнительную панель. Надо отметить, что API работы с SearchBox очень похоже на таковое для работы с SearchPane.

Также, как и в случае с кнопкой для вызова панели поиска, проще всего будет, если вы обернете SearchBox внутрь собственного UserControl - в этом случае вы сможете легко интегрировать в него всю логику, а на страницы вставлять только элемент управления.

<UserControl x:Class="EventsApp.UserControls.LearnSearchBox" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:EventsApp.UserControls" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" > <Grid> <SearchBox x:Name="searchBox" Width="300" Height="48" QuerySubmitted="searchBox_QuerySubmitted" /> </Grid> </UserControl>

И далее в коде:

private void searchBox_QuerySubmitted(SearchBox sender, SearchBoxQuerySubmittedEventArgs args) { var frame = Window.Current.Content as Frame; frame.Navigate(typeof(SearchPage), args.QueryText); }

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

Следующим шагом остается только вставить наш новый элемент управления во всех нужных местах:

Здесь ваш может подстерегать ошибка, в которой сходу трудно разобраться (особенно, если не читать документацию):

Все дело в том, что вы не можете одновременно использовать SearchPane и SearchBox. Вам нужно будет выбрать что-то одно. В моем случае я комментирую все строчки обращения к SearchPane.

Одной из причин такого конфликта является безусловно дублирование функциональности, еще одной - то, что оба механизма поиска завязаны на один и тот же системный механизм подсказок (управляется в настройках ОС):

Аналогично работе с SearchPane, вы можете добавить свои собственные подсказки. Также вы легко можете добавить активацию поиска по началу набора с клавиатуры на экране:

<SearchBox x:Name="searchBox" Width="300" Height="48" QuerySubmitted="searchBox_QuerySubmitted" FocusOnKeyboardInput="True" /> 

Пример использования можно найти на code.msdn.microsoft.com.

Живые плитки

Еще один момент, которому стоит уделить немного внимания, это живые плитки. В Windows 8 приложение могло реализовывать плитки двух размеров: квадратную 150x150px и широкую 310x150px. В Windows 8.1 к ним добавилось еще два квадратных размера: маленькая 70x70px и большая 310x310px.

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

1. Подготовить статичные изображения:

и указать их в манифесте приложения:

Также, как и для Windows 8, при желании вы можете предоставить приложению изображения плиток для разных режимов масштабирования (в зависимости от DPI).

2. Обновить код генерации живых плиток, чтобы он включал новые шаблоны. Остановимся на этом немного более подробно.

Как вы, возможно, знаете, для задания живых плиток используются готовые XML-шаблоны, доступные через соответствующие API. В некоторых случаях может быть сподручнее работать с ними как с текстом, особенно, когда нужно обновлять сразу шаблоны для нескольких размеров плиток как в нашем случае.

Наше обновление плиток выглядит примерно вот так:

public void UpdateImageTile() { var xml = new XmlDocument(); xml.LoadXml( string.Format( @"<?xml version=""1.0"" encoding=""utf-8"" ?> <tile> <visual branding=""none""> <binding template=""TileSquareImage""> <image id=""1"" src=""{0}"" alt=""{1}""/> </binding> <binding template=""TileWidePeekImage03""> <image id=""1"" src=""{0}"" alt=""{1}""/> <text id=""1"">{1}</text> </binding> </visual> </tile>", Entity.Thumbnails.OrderByDescending(x => x.Width).FirstOrDefault().Url, Entity.Title)); TileUpdateManager.CreateTileUpdaterForApplication().Update(new TileNotification(xml)); }

В данном случае мы просто показываем на живой плитке превью-картинку одного из докладов. В случае широкой плитки мы используем шаблон с анимацией. Шаблоны для квадратной и широкой плиток собраны в одной строке.

Чтобы добавить большую квадратную плитку, нам нужно:

  • Обновить версию шаблона до 2
  • Изменить названия шаблонов с учетом новых размеров
  • "Прилепить" снизу еще один шаблон

В результате должно получиться примерно так:

public void UpdateImageTile() { var xml = new XmlDocument(); xml.LoadXml( string.Format( @"<?xml version=""1.0"" encoding=""utf-8"" ?> <tile> <visual branding=""none"" version=""2""> <binding template=""TileSquare150x150Image"" fallback=""TileSquareImage""> <image id=""1"" src=""{0}"" alt=""{1}""/> </binding> <binding template=""TileWide310x150PeekImage03"" fallback=""TileWidePeekImage03""> <image id=""1"" src=""{0}"" alt=""{1}""/> <text id=""1"">{1}</text> </binding> <binding template=""TileSquare310x310ImageAndText01""> <image id=""1"" src=""{0}"" alt=""{1}""/> <text id=""1"">{1}</text> </binding> </visual> </tile>" , Entity.Thumbnails.OrderByDescending(x => x.Width).FirstOrDefault().Url, Entity.Title)); TileUpdateManager.CreateTileUpdaterForApplication().Update(new TileNotification(xml)); }

Готово!

Кстати, в Windows 8.1 вы можете добавить отображение живых плиток также через манифест:

Подводим итоги

Итак, почему стоит обновлять приложение под Windows 8.1? Во-первых, это повышение производительности даже без обновления кода просто за счет того, что многие элементы управления были оптимизированы в Windows 8.1. Во-вторых, это все новые возможности, включая новые размеры плиток, новые элементы управления и новые API. В-третьих, это учет изменений в самой операционной системе: в особенности режимов отображения приложений на экране и поведения поиска.

Что нужно сделать для обновления:

  1. Перенацелить проект в VS2013 c Windows 8 на Windows 8.1
  2. Обновить логику переключения режимов отображения приложения с тем, чтобы она зависела от размеров "окна" и соотношения ширины и высоты, а не конкретных состояний (full, fill, snapped) и ориентации устройства.
  3. Обновить активацию поиска:
    • a. Если использовался контракт поиска, как минимум добавить кнопку активации внутри приложения.
    • b. Попробовать внести поиск внутрь приложения с помощью SearchBox
  4. Добавить новые размеры плиток
    • a. Нарисовать еще два размера статичных плиток
    • b. Обновить код генерации живых плиток.

Дальнейшие улучшения - на ваше усмотрение. Успешной миграции!


Страница сайта http://test.interface.ru
Оригинал находится по адресу http://test.interface.ru/home.asp?artId=35231