Мы продолжаем цикл статей, посвященных обновлению Windows Phone 8.0 приложений до версии 8.1. Сегодня мы рассмотрим новые возможности Silverlight 8.1 и процесс обновления приложений Windows Phone Silverlight 8.0 до версии 8.1.
Краткий обзор
Новая версия Windows Phone Silverlight 8.1 предоставляет разработчикам мобильных приложений доступ к функциям Windows Phone 8.1 WinRT без значительного изменения кода существующего Silverlight приложения.
Silverlight 8.1 является продолжением технологии для разработчиков Silverlight.
Обновить приложение до Silverlight 8.1 очень просто, используя встроенный инструмент в Visual Studio 2013:
Необходимо учесть, что Silverlight 8.1 приложения работают только на Windows Phone 8.1 устройствах. Если требуется поддерживать работоспособность приложения на прошлых версиях операционных систем, то в магазине рекомендуется распространять так же и старую версию приложения на Silverlight 8.0.
Если вы только начинаете разработку под Windows Phone и хотели бы иметь версию приложения и для ПК, то рекомендуется начать разработку на новом Windows Phone 8.1 (WinRT или WinJS), которые предоставляют возможности создания универсальных приложений для телефонов, планшетов и ПК. К сожалению, приложение на Silverlight 8.1 не удастся расширить до универсального.
Как выбрать подходящую технологию для разработки своего мобильного приложения, можно прочитать здесь.
Новые возможности Windows Phone Silverlight 8.1
Множество инструментов и API, доступных для Silverlight 8.0 приложений, так же будут доступны для Silverlight 8.1. О некоторых различиях в использовании описано в следующей статье.
Ниже перечислены некоторые новые возможности, доступные для Silverlight 8.1 приложений:
- Расширение API, т.е. помимо доступных в Silverlight 8.0 WinRT APIs при переходе на Silverlight 8.1 так же станут доступны и XAML 8.1 WinRT APIs;
- Бонусы для графики, текста и т.д. с D2D/DWrite/WIC/…;
- Приложение на Silverlight 8.1 при необходимости сможет выступать в качестве фото-провайдера;
- Обновленная «бесшовная» интеграция VoIP сервиса для ауди-видео звонков через интернет;
Возможности, доступные только для Windows Phone 8.1 приложений, но так же поддерживаемые и для приложений Silverlight 8.1:
- Новые инструменты для тестирования приложения;
- Работа с файлами;
- Расширение возможностей хранения, резервного копирования, восстановления данных;
- Поддержка карт SD;
- Совместное использование данных между приложениями;
- Плитки, индикаторы событий, Push- уведомления с помощью нового сервиса Windows Push Notification Service (WNS);
- Выполенение задач и передача данных в фоновом режиме;
- Создание сетевых приложений и возможность единой авторизации на разных сервисах для пользователей, с использованием новой возможности хранения аутентификационных данных пользователя;
- Поддержка Bluetooth и WiFi Direct сервисов, обнаружение устройств;
- Обновление платежных инструментов NFC;
- Интеллектуальная панель ввода;
- Отправка писем и вложений;
- Доступ к контактам и календарю;
- Датчики положения устройства в пространстве;
- Географическое положение и геолокация;
- Возможности работы с фото, видео, аудио материалами, сохранение, редактирование медиа контента;
Более подробный список и информация о новых возможностях в Silverlight 8.1 расположены на MSDN.
Как обновить приложение с Windows Phone Silverlight 8.0 до Silverlight 8.1
Рассмотрим процесс обновления приложения Windows Phone Silverlight 8.0 до 8.1 на следующем примере. Возьмем контентное приложение – «Кулинарая книга». В ней по странам рассортированы рецепты, каждый рецепт состоит из нескольких страниц: описание, ингредиенты, фото. Приложение, помимо отображения рецептов, позволяет добавлять фото собственных блюд и закрепить понравившийся рецепт на стартовом экране телефона.
Что нужно для разработки:
- Операционная система Windows Phone 8.1
- Microsoft Visual Studio 2013 Update 2;
- Windows Phone Silverlight 8.0 приложение.
Процесс обновления Silverlight 8.0 приложения до 8.1:
- Не забудьте сделать бекап портируемого приложения;
- Открываем решение (файл расширения .sln) в Visual Studio 2013;
- Правой кнопкой мыши вызваем контекстное меню:
- Дальше нажимаем Yes:
- Получаем в обзревателе Windows Phone Silverlight 8.1 решение:
Главная иконка на месте, но похоже что изображений для комфортной работы обновленного приложения теперь требуется гораздо больше.
Подробнее о требованиях к изображениям Windows Phone Silverlight 8.1 приложений написано в этой статье.
Решаем эту проблему просто – создаем необходимые изображения и помещаем их в папку Assets текущего приложения:
Тестируем портированное приложение Windows Phone Silverlight 8.1
Запускаем эмулятор и открываем приложение:
- Список стран — Список рецептов для каждой страны — Рецепт:
- Моделируем ситуацию переключения на другое приложение с текущего рецепта, например на «Сообщения»:
- Возвращаемся к приложению через меню:
- Получаем ошибку в поведении приложения.
Приложение не открыло новую копию ранее запущенного приложения, как это происходило в Silverlight 8.0, в случае c возвращением к работе с приложением произошло следующее: экран моргнул, приложение перекинуло пользователя на стартовую страницу и перестало отображать какие-либо данные, а ожидался запуск текущей копии приложения, на том же месте на котором оно было прервано.
Такое поведение связано с изменением жизненного цикла Windows Phone приложения. Попробуем это исправить.
Исправляем недочеты в портированном приложении
- В обозревателе решений открываем app.xaml.cs файл:
Проверим FAR — Fast app resume (быстрое возобновление работы) возможность, которая позволяет открыть ту копию приложения, которая находится в памяти.
Здесь в области Phone Application Initialization видим, что шаблоный код FAR обработки доступен и все должно работать корректно:
#region Phone application initialization // Avoid double-initialization private bool phoneApplicationInitialized = false; // Do not add any additional code to this method private void InitializePhoneApplication() { if (phoneApplicationInitialized) return; // Create the frame but don't set it as RootVisual yet; this allows the splash // screen to remain active until the application is ready to render. RootFrame = new TransitionFrame(); RootFrame.Navigated += CompleteInitializePhoneApplication; // Handle navigation failures RootFrame.NavigationFailed += RootFrame_NavigationFailed; // Handle reset requests for clearing the backstack RootFrame.Navigated += CheckForResetNavigation; // Ensure we don't initialize again phoneApplicationInitialized = true; } // Do not add any additional code to this method private void CompleteInitializePhoneApplication(object sender, NavigationEventArgs e) { // Set the root visual to allow the application to render if (RootVisual != RootFrame) RootVisual = RootFrame; // Remove this handler since it is no longer needed RootFrame.Navigated -= CompleteInitializePhoneApplication; } private void CheckForResetNavigation(object sender, NavigationEventArgs e) { // If the app has received a 'reset' navigation, then we need to check // on the next navigation to see if the page stack should be reset if (e.NavigationMode == NavigationMode.Reset) RootFrame.Navigated += ClearBackStackAfterReset; } private void ClearBackStackAfterReset(object sender, NavigationEventArgs e) { // Unregister the event so it doesn't get called again RootFrame.Navigated -= ClearBackStackAfterReset; // Only clear the stack for 'new' (forward) and 'refresh' navigations if (e.NavigationMode != NavigationMode.New && e.NavigationMode != NavigationMode.Refresh) return; // For UI consistency, clear the entire page stack while (RootFrame.RemoveBackEntry() != null) { ; // do nothing } } #endregion
Проверим, что происходит с отображением данных.
- Открываем MainPage.xaml.cs и наблюдаем следующее:
В методе OnNavigatedTo проверяется условие загружен ли список рецептов сейчас:protected override void OnNavigatedTo(…) { if (!App.Recipes.IsLoaded) { pi = new Microsoft.Phone.Shell.ProgressIndicator(); pi.IsIndeterminate = true; pi.Text = "Loading data, please wait..."; pi.IsVisible = true; Microsoft.Phone.Shell.SystemTray.SetIsVisible(this, true); Microsoft.Phone.Shell.SystemTray.SetProgressIndicator(this, pi); App.Recipes.RecipesLoaded += Recipes_RecipesLoaded; App.Recipes.LoadLocalDataAsync(); } base.OnNavigatedTo(e); }
При повторном вызове того же приложения метод определяет список рецептов как уже загруженный и не выполняет действий, заданных по этому условию.
Добавим альтернативный вариант обработки условия:else if (e.NavigationMode == NavigationMode.New) { lstGroups.DataContext = App.Recipes; }
Проверяем, для того чтобы убедиться, что все работает верно.
- Обнаружились ошибки при открытии файлов, отвечающих за интерфейс приложения.
Откроем любой файл, например MainPage.xaml, и получаем отсутствие отображения элементов в дизайнере:
Чтобы решить проблему с дизайнером формы, необходимо обратить внимание на следующую ошибку:
The member «Instance» is not recognized or is not accessible.
Ошибка означает что свойство больше не поддерживается.Далее в тексте файла находим строку:
<Grid x:Name="LayoutRoot" Background="Transparent" d:DataContext="{d:DesignData /SampleData/RecipeDataSourceSampleData.xaml, Instance={x:Null}}">
Приводим ее к такому виду:
<Grid x:Name="LayoutRoot" Background="Transparent" d:DataContext="{d:DesignData /SampleData/RecipeDataSourceSampleData.xaml}">
Визуальный конструктор в порядке:
Так же компилятор сообщает об ошибках, связанных с остуствием toolkit элментов:
Новая платформа WinRT включает как старые элементы управления, так и множество новых. Поэтому библиотека Windows Phone Toolkit больше не нужна для мобильных приложений. Закомментируем или заменим их на новые аналоги.
Обратите внимание, при обновлении приложения на отличия в namespace и классах.
Например, в данном приложении использовался класс ListView, которого больше не существует в Windows Phone Silverlight 8.1 и его в приложении мы заменили на ListBox.
Класс LongListSelector так же больше не поддерживается, и мы используем вариант его замены:
Было:
<phone:LongListSelector x:Name="IngredientsListBox" ItemsSource="{Binding Ingredients}"/>
Стало:
<ListBox x:Name="IngredientsListBox" ItemsSource="{Binding Ingredients}" >
<StackPanel Margin="12,0,0,0">
<TextBlock Text="{Binding Mode=OneWay}" Margin="0,0,0,12"/>
</StackPanel>
</ListBox>
Добавляем новые возможности
Одна из новых возможностей для Silverlight 8.1 — это способность обмениваться данными с другими приложениями, в том числе изображениями.
Наше приложение может создавать и хранить фотографии приготовленного блюда, попробуем научить его «делиться», используя новые возможности API:
- В обозревателе решений откроем RecipeDetailPage.xaml файл:
- Для элемента Application Bar добавим новую кнопку «Share»:
- Используя окно свойств (Properties) для ApplicationBar, найдем коллекцию кнопок Buttons, добавим кнопку AppBarButton, выберем стандартную иконку icon=share.png и укажем ее название text=”share”:
- Создадим и напишем обработчик для кнопки «Share»:
private void ShareButton_Click(object sender, EventArgs e)</li> { if (item.UserImages == null || item.UserImages.Count == 0) { MessageBox.Show("You must take a picture first!"); } else { DataTransferManager.ShowShareUI(); } }
- Используя окно свойств (Properties) для ApplicationBar, найдем коллекцию кнопок Buttons, добавим кнопку AppBarButton, выберем стандартную иконку icon=share.png и укажем ее название text=”share”:
- В методе OnNavigatedTo, добавим событие DataRequested:
protected async override void OnNavigatedTo(NavigationEventArgs e) { ... DataTransferManager.GetForCurrentView().DataRequested += RecipeDetailPage_DataRequested; base.OnNavigatedTo(e); }
Создадим функцию для обработки этого события:
async void RecipeDetailPage_DataRequested (DataTransferManager sender, DataRequestedEventArgs args)
- Создадим и переопределим метод OnNavigatedFrom:
protected override void OnNavigatedFrom(NavigationEventArgs e) { DataTransferManager.GetForCurrentView().DataRequested -= RecipeDetailPage_DataRequested; }
- Добавим код в функцию RecipeDetailPage_DataRequested для обработки события DataRequested:
{ DataRequest request = args.Request; var deferral = args.Request.GetDeferral(); try { Uri photoFileUri = new Uri("ms-appdata:///local/" + item.UserImages[0]); var photoFile = await StorageFile.GetFileFromApplicationUriAsync(photoFileUri); request.Data.Properties.Title = "I've been baking!"; request.Data.Properties.Description = "This was my attempt at making " + item.ShortTitle; // It's recommended to use both SetBitmap and SetStorageItems for sharing a single image // since the target app may only support one or the other. List<IStorageItem> imageItems = new List<IStorageItem>(); imageItems.Add(photoFile); request.Data.SetStorageItems(imageItems); RandomAccessStreamReference imageStreamRef = RandomAccessStreamReference.CreateFromFile(photoFile); // It is recommended that you always add a thumbnail image any time you're sharing an image request.Data.Properties.Thumbnail = imageStreamRef; request.Data.SetBitmap(imageStreamRef); // Set Text to share for those targets that can't accept images request.Data.SetText("I just made " + item.ShortTitle + " from Contoso Cookbook!"); } finally { deferral.Complete(); }
Чтобы в коде работали все используемые функции, подключим:
using Windows.ApplicationModel.DataTransfer; using Windows.Storage; using Windows.Storage.Streams;
- Проверяем наши нововведения. Открываем приложение. Воспроизводим процесс создания фотографии и нажимаем кнопку «Share»:
Открываются сервисы, в которых можно поделиться фотографией.
Заключение
Silverlight 8.1 является не только продолжением предыдущей версии Silverlight 8.0, но так же сочетает в себе новые возможности, которые предлагает технология Windows Phone 8.1 и WinRT. А переход на Silverlight 8.1 с приложений предыдущей версии не является долгим и трудоёмким процессом.
Полезные ссылки
Tutorial: Building Apps for windows Phone 8.1
MSDN Library: Supported features for Windows Phone Silverlight 8.1 apps
Обучающие курсы виртуальной академии Microsoft (MVA)
Загрузить бесплатную или пробную Visual Studio 2013
Стать разработчиком приложений Windows Phone
Скачать пример приложения на Silverlight 8.1 из этой статьи
Скачать примеры кода с основными возможностями Windows Phone 8.1 (c#, c++, javascript)
Автор: maria_gore