Обмен данными между приложениями Windows Store и Windows Phone Store

OSzone.net » Microsoft » Разработка приложений » Универсальные приложения » Обмен данными между приложениями Windows Store и Windows Phone Store
Автор: Тони Чэмпион
Иcточник: msdn.microsoft.com
Опубликована: 13.04.2015

Для нынешних приложений существует совершенно другой набор стандартов и ожиданий, чем это было для настольных приложений десятилетие назад. Одно из таких ожиданий — приложение способно работать на множестве устройств и обмениваться данными с другими устройствами. Если у пользователя одно и то же приложение установлено на настольном компьютере и на лэптопе, он ожидает, что оба экземпляра приложения поддерживают одинаковую конфигурацию и работают с одним и тем же набором данных. Более того, если одно и то же приложение доступно на множестве устройств, пользователи будут ожидать поддержки обмена данными между этими устройствами.

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

Приложения Windows Store и Windows Phone Store решают эту проблему на основе концепции перемещаемых данных (roaming data). Каждое приложение автоматически получает небольшой объем в облачном хранилище для каждого пользователя. Пользователь может сохранять в нем информацию о приложении и обмениваться ею между несколькими установленными экземплярами приложения. В приложениях Windows Phone Store и Windows Store делается еще один шаг вперед и дается возможность обмениваться данными между приложениями на разных устройствах. Здесь я буду рассматривать области применения перемещаемых данных в ваших приложениях и то, как эффективно использовать эти данные между устройствами.

Для демонстрации обмена перемещаемыми данными в этой статье используются универсальные приложения, однако эти же методы работают в отдельным приложениях Windows Phone Store и Windows Store. Перемещаемые данные также работают между приложениями на основе HTML и XAML.

Применение перемещаемых данных

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

Что перемещать Первый вопрос, задаваемый большинством разработчиков, — какой тип данных подходит в качестве перемещаемого. Сразу учтите, что на объем перемещаемых данных накладываются жесткие ограничения по размеру. А значит, надо заранее продумать, что вы будете перемещать.

Чаще всего перемещают, например, данные о пользовательских предпочтениях и параметры, такие как цвета, шрифты, настройки и т. д. Эти значения могут иметь другой смысл в приложении Windows Store и Windows Phone Store, но обеспечение примерно одинаковой среды на разных платформах будет большим плюсом для вашего приложения.

Текущая навигация в вашем приложении может быть мощным функционалом. Если пользователь извлекает отчет и помещает его в Windows Phone, а затем входит в настольную систему на работе, почему бы приложению в версии для Windows Store не увидеть тот же отчет? Или, если пользователь смотрит видео на настольном компьютере, то почему бы версия для Windows Phone не могла бы перейти к тому же видео?

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

Большие наборы данных не годятся в качестве перемещаемых. Однако вы могли бы поместить какой-то ключ к набору данных в перемещаемые данные и передать большой набор данных на новый клиент с помощью этого ключа.

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

Включение перемещаемых данных Для успешной синхронизации данных между устройствами к приложению предъявляются два требования. Во-первых, пользователи должны входить на устройство под учетной записью Microsoft. Перемещаемые настройки сопоставляются с приложением и учетной записью пользователя Microsoft. Если учетная запись Microsoft не используется, данных не достаточно.

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

Если перемещаемые данные отключены на устройстве, они по-прежнему доступны локально.

Чаще всего перемещают, например, данные о пользовательских предпочтениях и параметры, такие как цвета, шрифты, настройки и т. д.

Исследуем API

Вы найдете API для перемещаемых данных в объекте Windows.Storage.ApplicationData. Каждое приложение поддерживает один экземпляр ApplicationData, на который можно ссылаться с помощью статического свойства Current:

var appData = Windows.Storage.ApplicationData.Current;

Этот API не содержит механизм принудительной синхронизации перемещаемых данных. Управление таким процессом возлагается на само устройство.

Вы можете использовать два типа перемещаемых данных. Первый вы найдете в свойстве RoamingSettings объекта ApplicationData; это ApplicationDataContainer, который управляет парами «ключ-значение». Параметры управляются через свойство RoamingSettings.Values, и вы можете обращаться к ним как к массиву со строковой индексацией (string indexed array). Ключами могут быть любые алфавитно-цифровые строки длиной до 255 символов, а значениями — объекты, если только это тип данных, поддерживаемый Windows Runtime. То есть в перемещаемых настройках нельзя хранить пользовательские объекты.

К перемещаемым настройкам можно обращаться через индексируемое свойство Values. Добавление или изменение параметра осуществляется изменением индексируемого по ключу свойства Values на новое значение. Для удаления параметра служит метод Values.Remove. В следующем коде показан пример создания, чтения и удаления перемещаемого параметра:

var roamingSettings = ApplicationData.Current.RoamingSettings;
// Создание параметра
roamingSettings.Values["setting1"] = "My First Setting";
// Чтение параметра
var settings1 = roamingSettings.Values["setting1"];
// Удаление параметра
roamingSettings.Values.Remove("setting1");
// Очистка всех параметров
roamingSettings.Values.Clear();

В некоторых случаях будет работать сохранение простых типов данных Windows Runtime. Однако бывают ситуации, когда имеет смысл хранить объект целиком. Есть пара способов хранения классов в перемещаемых данных, но вы можете использовать ApplicationDataCompositeValue для хранения более сложных объектов в RoamingSettings.

ApplicationDataCompositeValue — это набор пар «ключ-значение», хранящихся вместе. Это отличный способ группирования элементов, которые будут оставаться синхронизированными как единое целое. В следующем коде показан пример создания ApplicationDataCompositeValue и его добавления в RoamingSettings:

var compositeValue = new ApplicationDataCompositeValue();
compositeValue["firstName"] = "Tony";
compositeValue["lastName"] = "Champion";
compositeValue["age"] = 38;
roamingSettings.Values["personalInfo"] = compositeValue;

Один из недостатков этого подхода — отсутствие механизма автоматического преобразования сложного объекта в ApplicationDataCompositeValue и наоборот. Один из вариантов решения этой проблемы — создание вспомогательных функций для ваших классов, которые будут обрабатывать преобразования за вас. На рис. 1 показан класс Person с двумя статическими методами: ToCompositeSetting и FromCompositeSetting. Эти методы преобразуют данные, сохраненные в предыдущем примере, в объект Person, который значительно упростит такие вещи, как связывание с данными.

Рис. 1. Преобразование ApplicationDataCompositeValue в класс Person

public class Person
{
  public string FirstName { get; set; }
  public string LastName { get; set; }
  public int Age { get; set; }
  public static Person
    FromComposite(ApplicationDataCompositeValue composite)
  {
    return new Person()
    {
      FirstName = (string)composite["firstName"],
      LastName = (string)composite["lastName"],
      Age = (int)composite["age"]
    };
  }
  public static ApplicationDataCompositeValue
    ToComposite(Person person)
  {
    var composite = new ApplicationDataCompositeValue();
    composite["firstName"] = person.FirstName;
    composite["lastName"] = person.LastName;
    composite["age"] = person.Age;
    return composite;
  }
}

На рис. 2 новый класс Person используется для получения и сохранения личной информации в RoamingSettings.

Рис. 2. Получение и сохранение личной информации в RoamingSettings

var person = new Person()
{
  FirstName = "Tony",
  LastName = "Champion",
  Age = 38
};
roamingSettings.Values["personalInfo"]
  = Person.ToComposite(person);
if (roamingSettings.Values.ContainsKey("personalInfo"))
{
  var composite =
    (ApplicationDataCompositeValue)roamingSettings.Values["personalInfo"];
  var roamingPerson = Person.FromComposite(composite);
}

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

var roamingSettings = ApplicationData.Current.RoamingSettings;
var composite = new ApplicationDataCompositeValue();
composite["movieId"] = myVidPlayer.MovieId;
composite["position"] = myVidPlayer.CurrentTime;
roamingSettings.Values["HighPriority"] = composite;

Второй тип перемещаемых данных — файлы. Объект ApplicationData содержит свойство RoamingFolder, которое возвращает экземпляр StorageFolder, где ваше приложение может читать и записывать синхронизируемые файлы.

Вы можете добавить в RoamingFolder практически любой тип файла, кроме нескольких исключений (см. ниже). Но имя файла должно соответствовать определенным спецификациям. Прежде всего максимальная длина имени файла вместе с расширением составляет 256 символов. Кроме того, в имени файла не должно быть ведущих пробелов. Также запрещено применение группы Unicode-символов.

Несколько типов файлов не разрешено, так как они действуют как папки, например .zip и .cab. Если вы добавите в RoamingFolder файл, не отвечающий этим требованиям, этот файл не будет синхронизироваться, но будет доступен для локального доступа.

API не содержит механизм принудительной синхронизации перемещаемых данных. Управление таким процессом возлагается на само устройство.

Одно из применений RoamingFolder — хранение сложных объектов. Например, все тот же объект Person сериализуется, а затем записывается в файл в RoamingFolder:

var roamingFolder = ApplicationData.Current.RoamingFolder;
// Создаем файл и открываем поток для записи
StorageFile personFile = await roamingFolder.CreateFileAsync(
  "personInfo.txt", CreationCollisionOption.ReplaceExisting);
var writeStream = await personFile.OpenStreamForWriteAsync();
// Сериализация объекта в JSON
var serializer = new DataContractJsonSerializer(typeof(Person));
serializer.WriteObject(writeStream, person);
// Сбрасываем поток в файл
await writeStream.FlushAsync();

JSON-сериализация используется вместо XML-сериализации по соображениям размера. Из-за ограничений на объем перемещаемых данных на счету каждый байт.

Для получения объекта из RoamingFolder можно задействовать обратную логику. Следующий код демонстрирует чтение того же файла и возврат объекта Person:

// Создаем файл и открываем поток для чтения в него
var readStream = await
  roamingFolder.OpenStreamForReadAsync("personInfo.txt");
// JSON-десериализация в объект
var serializer = new DataContractJsonSerializer(typeof(Person));
var roamingPerson = (Person)serializer.ReadObject(readStream);

Теперь вы можете читать и писать перемещаемые данные для синхронизации между устройствами, но как узнать, что они были обновлены? Это обрабатывается событием DataChanged в ApplicationData. Всякий раз, когда устройство получает новые перемещаемые данные, срабатывает событие DataChanged, передавая обновленный объект ApplicationData. Это позволяет вам выполнять любую подстройку приложения при изменении данных. Соответствующего события, позволяющего узнать, когда с устройства были переданы данные, нет. Следующий код демонстрирует, как прослушивать событие DataChanged:

private void HandleEvents()
{
  ApplicationData.Current.DataChanged += Current_DataChanged;
}
void Current_DataChanged(ApplicationData sender, object args)
{
  // Обновляем приложение новыми настройками
}

Если ваше приложение использует событие DataChanged, полезно задействовать метод SignalDataChanged в ApplicationData. Всякий раз, когда вы локально обновляете любые перемещаемые данные, вы можете вызывать этот метод, который будет генерировать событие DataChanged и позволит запускать любые нужные вам обработчики обновлений:

// Локально обновляем настройки
// и генерируем событие DataChanged
roamingSettings.Values["favoriteColor"] = "Black";
ApplicationData.Current.SignalDataChanged();

В перемещаемых настройках есть специальный ключ, который можно использовать для данных, подлежащих немедленной синхронизации.

Важно отслеживать объем данных, которые вы пытаетесь переместить. Каждое устройство накладывает ограничение на максимальный объем данных, которые можно синхронизировать между устройствами, и в настоящее время он равен 100 Кб. Потенциальная проблема в том, что здесь применяется подход «все или ничего». Если общее количество данных, подлежащих синхронизации, превышает лимит, никакой синхронизации между устройствами не происходит. Класс ApplicationData содержит свойство RoamingStorageQuota, которое возвращает общий размер данных в килобайтах, поддерживаемых для синхронизации. Однако в ApplicationData нет никакого механизма для определения текущего используемого вами объема данных, так что на данный момент отслеживать размер данных вам придется самостоятельно.

В новых версиях вашего приложения какие-то данные и настройки предыдущих версий могут оказаться ненужными. Чтобы решить эту проблему, Windows Runtime позволяет вам контролировать версию перемещаемых данных. Текущую версию перемещаемых данных вы найдете в ApplicationData.Current.Version. Этот номер версии не зависит от номера версии приложения и по умолчанию задан как нулевой. Приложение будет синхронизировать данные, которые совпадают с нужным вам номером версии. Это дает возможность создавать новые структуры данных, не боясь навредить старым версиям.

Вы можете изменить версию приложения методом ApplicationData.SetVersionAsync. Этот метод принимает два параметра: номер новой версии и ApplicationDataSetVersionHandler, который позволяет записывать любой код, необходимый для внесения изменений в приложение на основе новой версии.

Обработчик включает единственный параметр — SetVersionRequest. Благодаря этому текущая версия предоставляется через свойство CurrentVersion, а новая версия — через свойство DesiredVersion. Ваше приложение может использовать эти два значения для обработки любых миграций на основе итеративного подхода. Он также содержит GetDeferralMethod, который позволяет поддерживать поток открытым, пока вы не получите возможность выполнить миграцию. Таким образом, если у вас есть любые асинхронные вызовы, например, для чтения или записи файлов, то вы можете выполнить соответствующие функции до выполнения процесса изменения версии. На рис. 3 показано, как мигрировать на новую версию.

Рис. 3. Обновление версии перемещаемых данных

void SetVersionHandler(SetVersionRequest request)
{
  SetVersionDeferral deferral = request.GetDeferral();
  if (request.CurrentVersion < 1)
  {
    // Обрабатываем обновление с версии 0 на 1
  }
  if (request.CurrentVersion < 2)
  {
    // Обрабатываем обновление с версии 1 на 2
  }
  deferral.Complete();
}
async void SetVersion()
{
  var appData = ApplicationData.Current;
  if (appData.Version < 2)
  {
    await appData.SetVersionAsync(
      2, new ApplicationDataSetVersionHandler(SetVersionHandler));
  }
}

Обмен между приложениями Windows Store и Windows Phone Store

Теперь, когда вы реализовали перемещаемые настройки в приложениях Windows Store и Windows Phone Store, следующий логичный шаг — подготовить два приложения к обмену перемещаемыми данными.

С технической точки зрения, чтобы приложения Windows Phone Store и Windows Store могли совместно использовать перемещаемые данные, у них должен быть одинаковый Package Family Name. Это поле генерируется на основе Package Name. Следовательно, у двух приложений должен быть одинаковый Package Name. Эти значения вы найдете, сопоставив приложения с именами в их магазинах.

Первый шаг в передаче приложения в любой из магазинов — назначение приложению имени. Вы можете либо создать новое имя, либо сопоставить приложение с существующим именем. Список существующих имен является комбинацией зарезервированных имен для магазина, который вы используете, и списка приложений, которые вы имеете в другом магазине. Выбор приложения в любом магазине даст ссылку на ваше приложение, присваивая ему одно и то же имя и позволяя приложениям обмениваться перемещаемыми данными. Узнать больше о связывании приложений Windows Store и Windows Phone Store можно по ссылке bit.ly/10Pl2Xi.

Поскольку магазины все равно раздельные, связывание приложений немного отличается. Если у вас есть существующее приложение Windows Store, вы можете связать его с приложением Windows Phone Store, выбрав приложение Windows Store в разделе App Info, как показано на рис. 4. Вы также можете связать приложение Windows Store с существующим приложением Windows Phone Store в разделе App Name (рис. 5).

*

Рис. 4. Связывание приложения Windows Phone Store с приложением Windows Store

*

Рис. 5. Связывание приложения Windows Store с приложением Windows Phone Store

Создав и связав приложения в магазинах, остается лишь сопоставить каждое приложение в Visual Studio с их именами. Щелкните правой кнопкой мыши ваше основное решение Windows Store и Windows Phone Store и выберите Store | Associate App with the Store. Затем следуйте указаниям мастера и выберите правильное имя. Это приведет к обновлению вашего Package.appxmanifest информацией, введенной в магазине.

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

Отладка перемещаемых данных

Тестирование перемещаемых настроек выполняется достаточно прямолинейно. И вновь это ситуация «все или ничего». Либо ваши перемещаемые данных синхронизируются между устройствами, либо нет. При тестировании процесса синхронизации блокировка устройства заставит приложение попытаться синхронизировать свои данные. Если этого не происходит, нужно подумать о двух вещах.

Заключение

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


Ссылка: http://www.oszone.net/26956/