Windows en tiempo de ejecución

Datos móviles entre las aplicaciones de la Tienda Windows y las de la Tienda de Windows Phone

Tony Champion

Nos encontramos con un conjunto de estándares y expectativas completamente diferente para las aplicaciones de hoy en día de las de aplicaciones escritorio de hace una década. Una de esas expectativas es lograr que las aplicaciones funcionen y compartan datos entre varios dispositivos diferentes. Si un usuario tiene la misma aplicación instalada tanto en el equipo de escritorio como en el portátil, es lógico suponer que esperará que la aplicación mantenga la misma configuración y funcione con el mismo conjunto de datos en ambos dispositivos. Si vamos un poco más allá, y suponemos que la misma aplicación está disponible en diferentes dispositivos, los usuarios esperarán poder compartir sus datos entre esos dispositivos.

En un mundo de aplicaciones impulsadas por los datos, puede manejar estas expectativas principalmente con una base de datos de back-end. Una aplicación instalada en varios dispositivos puede consultar la misma base de datos remota y proporcionar al usuario acceso a esos mismos datos. De todas formas, mantener aplicaciones con bases de datos remotas supone una inversión tremenda en lo que a arquitectura, desarrollo y mantenimiento se refiere. Y sepa que esto no es necesario para todas las aplicaciones. Incluso puede que las aplicaciones que requieran bases de datos no quieran ser compatibles con la información específica para aplicaciones que se encuentre en una base de datos diseñada para varios fines.

Por ello, las aplicaciones de la Tienda Windows y la Tienda de Windows Phone abordan esta necesidad con el concepto de datos móviles. Toda aplicación recibe, por usuario y de forma automática, una pequeña capacidad de almacenamiento en la nube. El usuario puede usar esto para guardar información acerca de la aplicación y compartirla entre las múltiples instalaciones de la aplicación. Tanto las aplicaciones de la Tienda Windows como las de la Tienda de Windows Phone llevan esto más allá y permiten al usuario compartir sus datos entre las aplicaciones que tenga instaladas en diferentes dispositivos. En este artículo echaremos un vistazo a los usos de los datos móviles entre aplicaciones y cómo utilizar estos datos de forma eficaz entre dispositivos.

Para ello, utilizaré las aplicaciones universales para demostrar cómo compartir datos móviles entre dispositivos. Sin embargo, estas mismas técnicas funcionan en aplicaciones de la Tienda Windows y de la Tienda de Windows Phone independientes. Los datos móviles también funcionan entre aplicaciones basadas en HTML y XAML.

Uso de los datos móviles

Uno de los mejores aspectos de utilizar datos móviles en sus aplicaciones, es que están disponibles de manera automática y no necesita configurarlos de ninguna manera. Basta con usar la API de datos móviles disponible para que su aplicación pueda sacar provecho de los datos móviles.

Qué usar en la itinerancia La primera pregunta que la mayoría de los desarrolladores formulan es qué tipo de datos son los adecuados para la configuración de itinerancia. Recuerde que hay un estricto límite en el tamaño de la cantidad de datos que se pueden poner en itinerancia. Esto quiere decir que necesitará planificarlo todo al detalle.

Alguna de las cosas más comunes que se usan para la itinerancia son configuraciones y preferencias definidas por el usuario, como los colores, las fuentes, las opciones, etc. Si va a compartir datos entre aplicaciones de la Tienda Windows y aplicaciones de la Tienda de Windows Phone, puede que estos valores tomen diferentes significados, pero proporcionarán una experiencia similar y, entre plataformas, resultarán ser de lo más beneficiosos para su aplicación.

La navegación actual por su aplicación puede convertirse en una potente característica. Si un usuario sube un informe en un Windows Phone y luego inicia sesión en un equipo de su trabajo, ¿por qué no debería ir la versión de la aplicación de la Tienda Windows directamente a ese mismo informe? Si un usuario está viendo un vídeo en su equipo de escritorio, ¿por qué no debería ir la versión para Windows Phone ir al mismo vídeo?

Los datos temporales pueden ser otro buen candidato para la itinerancia. Si un usuario está escribiendo un correo electrónico en un portátil, debería poder continuar escribiendo ese mismo correo desde su equipo de escritorio.

Los grandes conjuntos de datos no suelen ser buenos candidatos para los datos móviles. Sin embargo, puede colocar una clave en el conjunto de datos en los datos móviles y bajar el conjunto de datos más grande al nuevo cliente según la clave que comparta.

La lista de candidatos sigue pero el objetivo es el mismo: hacer que el usuario sienta que puede conectar siempre que quiera a su aplicación gracias a los datos móviles.

Habilitar datos móviles: existen un par de requisitos previos que sus aplicaciones deben cumplir para sincronizar los datos entre dispositivos correctamente. En primer lugar, los usuarios tienen que iniciar sesión en el dispositivo mediante una cuenta de Microsoft. Esto se debe a que la configuración de la itinerancia está asociada a una aplicación y a una cuenta de usuario de Microsoft. Si el usuario no utiliza una cuenta de Microsoft, los datos no formarán parte de la clave. 

En segundo lugar, es importante que el usuario no haya deshabilitado las capacidades de datos móviles del dispositivo. El usuario puede asegurarse de esto manualmente o bien puede tener una directiva de dispositivo aplicada por los administradores del sistema. Si los datos móviles están deshabilitados, éstos no se sincronizarán.

De todos modos, aunque no tenga los datos móviles habilitados en un dispositivo, siempre puede acceder a ellos de forma local. Por lo tanto, su aplicación no se tiene que preocupar de si los datos móviles se están sincronizando y usando un flujo de trabajo diferente.

Explorar las API

Encontrará la API para los datos móviles en el objeto Windows.Storage.ApplicationData. Cada aplicación mantiene una única instancia de ApplicationData a la cual puede hacer referencia con la propiedad estática Current:

var appData = Windows.Storage.ApplicationData.Current;

La API no incluye un mecanismo para forzar la sincronización de los datos móviles. Del proceso de administración se encarga el propio dispositivo.

Puede utilizar dos tipos de datos móviles. Encontrará el primero en la propiedad RoamingSettings de ApplicationData, la cual es un ApplicationDataContainer que administra los pares de claves o valores. La configuración se administra en la propiedad RoamingSettings.Values y puede acceder a ella como una matriz indizada de cadena. Las claves pueden ser cualquier cadena alfanumérica de hasta 255 caracteres de longitud. El valor puede ser un objeto siempre y cuando sea un tipo de datos de Windows en tiempo de ejecución compatible. Esto quiere decir que no puede almacenar objetos personalizados en la configuración de itinerancia.

Puede acceder a la configuración de itinerancia a través de la propiedad indizada Values. Agregue o actualice una configuración cambiando la clave de la propiedad indizada Values al nuevo valor. Utilice el método Values.Remove para quitar una configuración. El código que se muestra a continuación es un ejemplo para crear, leer y quitar una configuración de itinerancia:

var roamingSettings = ApplicationData.Current.RoamingSettings;
// Create setting
roamingSettings.Values["setting1"] = "My First Setting";
// Read setting
var settings1 = roamingSettings.Values["setting1"];
// Remove setting
roamingSettings.Values.Remove("setting1");
// Clear all settings
roamingSettings.Values.Clear();

El almacenamiento de tipos de datos simples de Windows en tiempo de ejecución funcionará en algunas instancias. Sin embargo, hay veces en las que almacenar un objeto al competo puede tener su lógica. Hay un par de maneras de almacenar clases en datos móviles, pero puede usar un ApplicationDataCompositeValue para almacenar objetos más complejos en RoamingSettings.

Un ApplicationDataCompositeValue es una colección de pares de claves o valores almacenados juntos. Esta es una magnífica manera de agrupar elementos que permanecerán sincronizados como si fueran una sola unidad. El código siguiente es un ejemplo de la creación de un ApplicationDataCompositeValue y de su adición a RoamingSettings:

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

La única pega de este enfoque es que no existe un mecanismo para ir automáticamente a un objeto complejo o, desde allí, ir a un ApplicationDataCompositeValue. Un enfoque para resolver este problema es crear para sus clases funciones auxiliares que se encarguen de la conversión por usted. En la Ilustración 1 se muestra una clase Person con dos métodos estáticos: ToCompositeSetting y FromCompositeSetting. Estos métodos se encargan de convertir los datos almacenados en el ejemplo anterior en un objeto Person, que hará que trabajos como el enlace de datos sean menos complejos.

Ilustración 1. Conversión de ApplicationDataCompositeValue a una clase 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;
  }
}

En la Ilustración 2 se utiliza la nueva clase Person para obtener y almacenar la información personal de RoamingSettings.

Ilustración 2. Obtener y almacenar información personal en 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);
}

Hay una clave especial en la configuración de itinerancia que puede usar para aquellos datos que necesite sincronizar de forma inmediata. Si agrega HighPriority a cualquier valor, este se sincronizará lo más rápido posible. Esta opción es perfecta para elementos como la numeración de las páginas de un libro, un fotograma de un vídeo en pausa o cualquier otra cosa que le ayude a proporcionar una buena experiencia de conectividad entre dispositivos. Por ejemplo, si un usuario está viendo una película en su aplicación de la Tienda Windows, puede proporcionarle la aplicación correspondiente a la Tienda de Windows Phone con los datos de compatibilidad apropiados y que así el usuario pueda seguir viendo la película desde el punto en el que la dejó:

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

Los archivos forman parte del segundo tipo de datos móviles. El objeto ApplicationData contiene una propiedad RoamingFolder que devuelve una instancia StorageFolder en la cual su aplicación puede leer y escribir archivos para ser sincronizados.

Puede agregar prácticamente cualquier tipo de archivo a RoamingFolder. Sin embargo, tenga en cuenta que el nombre del archivo debe cumplir determinados requisitos. Primero, la longitud máxima del nombre del archivo tiene que ser de 256 caracteres. Además, el nombre del archivo no puede contener espacios iniciales y existe también un grupo de caracteres Unicode que no están permitidos.

Por otro lado, también hay varios tipos de archivos, como por ejemplo .zip o .cab, que no están permitidos ya que funcionan como si fueran carpetas. Si agrega un archivo a la RoamingFolder que no cumpla estos requisitos, el archivo no se sincronizará, pero lo tendrá disponible de forma local.

Uno de los usos de RoamingFolder es almacenar objetos complejos. A continuación, encontrará un ejemplo para serializar el mismo objeto Person y escribirlo en un archivo en RoamingFolder:

var roamingFolder = ApplicationData.Current.RoamingFolder;
// Create file and open a stream to write to
StorageFile personFile = await roamingFolder.CreateFileAsync(
  "personInfo.txt", CreationCollisionOption.ReplaceExisting);
var writeStream = await personFile.OpenStreamForWriteAsync();
// JSON serialize object
var serializer = new DataContractJsonSerializer(typeof(Person));
serializer.WriteObject(writeStream, person);
// Flush the stream
await writeStream.FlushAsync();

La serialización JSON se utiliza antes que la XML debido a restricciones de tamaño. Con este tipo de restricciones de los datos móviles, cada byte cuenta.

Puede usar la lógica inversa para recuperar un objeto de RoamingFolder. El código siguiente muestra la lectura de ese mismo archivo y la devolución de un objeto Person:

// Create file and open a stream to write to
var readStream = await 
  roamingFolder.OpenStreamForReadAsync("personInfo.txt");
// JSON deserialize object
var serializer = new DataContractJsonSerializer(typeof(Person));
var roamingPerson = (Person)serializer.ReadObject(readStream);

Ahora puede leer y escribir datos móviles para sincronizarlos entre dispositivos pero, ¿cómo sabrá cuándo se ha actualizado? Esta opción la gestiona el evento DataChanged en ApplicationData. Cada vez que un dispositivo recibe nuevos datos móviles, se desencadenará el evento DataChanged, pasando el objeto actualizado ApplicationData. Esto le permitirá realizar cualquier tipo de ajuste a su aplicación cuando los datos hayan cambiado. De cualquier manera, no existe ningún evento que le avise de que el dispositivo ya no dispone de los datos correspondientes. El siguiente código le ayudará a saber cómo funciona el evento DataChanged:

private void HandleEvents()
{
  ApplicationData.Current.DataChanged += Current_DataChanged;
}
void Current_DataChanged(ApplicationData sender, object args)
{
  // Update app with new settings
}

Si su aplicación ya se está beneficiando del evento DataChanged, el método SignalDataChanged de ApplicationData le será de utilidad. Cada vez que actualice datos móviles de forma local, podrá llamar a este método y así desencadenar el evento DataChanged que permitirá cualquier controlador de actualización que necesite ejecutar:

// Update settings locally and raise DataChanged event
roamingSettings.Values["favoriteColor"] = "Black";
ApplicationData.Current.SignalDataChanged();

Es importante que tenga en cuenta la cantidad de datos que quiere poner en itinerancia. Cada dispositivo tiene una cantidad máxima de datos (actualmente unos 100 Kb) que puede sincronizar entre dispositivos. El problema que se presenta aquí es una situación de todo o nada. Si el total de datos que está intentando sincronizar supera el límite establecido, no se sincronizará absolutamente nada entre los dispositivos. La clase ApplicationData contiene una propiedad RoamingStorageQuota que devuelve el tamaño total de datos permitidos para sincronizar en kilobytes. Sin embargo, ApplicationData no contiene ningún mecanismo para determinar la cantidad de datos actual que se están utilizando, así que por ahora tiene que estar atento.

En cuanto a las nuevas versiones de su aplicación, esto significará una configuración nueva o con cambios, así como datos de versiones anteriores que ya no son necesarios. Para hacerse cargo de esta cuestión, Windows en tiempo de ejecución le permite actualizar la versión de sus datos móviles. Podrá encontrar la versión actualizada de datos móviles para los cuales se ajustó la aplicación en ApplicationData.Current.Version. El número de versión aquí es totalmente independiente del número de versión de la aplicación y, por defecto, se establece en cero. La aplicación sincronizará aquellos datos que coincidan con su número de versión, lo que le permitirá crear nuevas estructuras de datos sin temor a desbaratar versiones anteriores.

Puede cambiar la versión de la aplicación con el método ApplicationData.Set­VersionAsync. Este método consta de dos parámetros: el nuevo número de versión y un ApplicationDataSetVersionHandler, los cuales le permitirán escribir cualquier código necesario para poder realizar cambios en la aplicación basados en la nueva versión.

El controlador contiene un solo parámetro SetVersionRequest. Este proporciona la versión actual a través de la propiedad CurrentVersion, así como la nueva versión en la propiedad DesiredVersion. Su aplicación puede utilizar estos dos valores para gestionar cualquier migración en un enfoque iterativo. También contiene un GetDeferralMethod que le permitirá mantener el subproceso abierto hasta que pueda completar la migración. De ese modo, si tiene llamadas asíncronas tales como la lectura o escritura de archivos, podrá realizar esas funciones antes de que se complete el proceso de cambio de versión. En la Ilustración 3 se muestra cómo migrar a una nueva versión.

Ilustración 3. Actualización de la versión de datos móviles

void SetVersionHandler(SetVersionRequest request)
{
  SetVersionDeferral deferral = request.GetDeferral();
  if (request.CurrentVersion < 1)
  {
    // Handle upgrade from 0 to 1
  }
  if (request.CurrentVersion < 2)
  {
    // Handle upgrade from 1 to 2
  }
  deferral.Complete();
}
async void SetVersion()
{
  var appData = ApplicationData.Current;
  if (appData.Version < 2)
  {
    await appData.SetVersionAsync(
      2, new ApplicationDataSetVersionHandler(SetVersionHandler));
  }
}

Compartir entre aplicaciones de la Tienda Windows y aplicaciones de la Tienda de Windows Phone

Ahora que ha implementado la configuración de itinerancia en las aplicaciones de la Tienda Windows y las de la Tienda de Windows Phone, el siguiente paso lógico es lograr que las dos aplicaciones complementarias puedan compartir sus datos móviles.

En términos técnicos, para que una aplicación de la Tienda Windows comparta datos móviles con otra aplicación de la Tienda de Windows Phone, ambas deben tener el mismo Nombre de familia de paquete. Este área se crea genera basándose en el Nombre del paquete y, por tanto, ambas aplicaciones deben tener el mismo Nombre de paquete. Puede encontrar estos valores asociando las aplicaciones con los nombres en sus respectivas tiendas.

El primer paso para enviar una aplicación en cualquiera de las tiendas es asignarle un nombre. Para ello, puede crear un nombre nuevo o asociar la aplicación a un nombre ya existente. La lista de nombres existentes es una combinación de nombres reservados para la tienda en la que se encuentra y la lista de aplicaciones que tenga en la otra tienda. Si selecciona una aplicación que esté en la otra tienda, esta se vinculará a su aplicación dándole el mismo nombre y permitiendo que ambas compartan datos móviles. Puede leer más información acerca de cómo vincular aplicaciones de la Tienda Windows con aplicaciones de la Tienda de Windows Phone en bit.ly/10Pl2Xi.

Como ambas tiendas están diferenciadas, la experiencia que tenga al vincular sus aplicaciones puede ser algo diferente. Si ya tiene una aplicación de la Tienda Windows, puede vincularla con una aplicación de la Tienda de Windows Phone seleccionando esta última en la sección Información de aplicaciones, tal y como se muestra en la Ilustración 4. Además, puede vincular en la sección Nombre de aplicación una aplicación de la Tienda Windows con una aplicación de la Tienda de Windows Phone ya existente tal y como se muestra en la Ilustración 5.

Vincular una aplicación de la Tienda de Windows Phone con una aplicación de la Tienda Windows
Ilustración 4. Vincular una aplicación de la Tienda de Windows Phone con una aplicación de la Tienda Windows

Vincular una aplicación de la Tienda Windows a una aplicación de la Tienda de Windows Phone
Ilustración 5. Vincular una aplicación de la Tienda Windows a una aplicación de la Tienda de Windows Phone

Una vez ha creado las aplicaciones vinculadas en las tiendas, el paso final es asociar cada aplicación en Visual Studio a los nombres que haya decidido. Haga clic con el botón secundario en la solución principal de la Tienda Windows y la Tienda de Windows Phone y seleccione Tienda | Asociar aplicación con la tienda. A continuación, siga el asistente y seleccione el nombre correcto. Al hacerlo, actualizará su Package.appxmanifest con la información que haya introducido en la tienda.

En este punto, sus aplicaciones podrán compartir datos móviles. No se olvide de la importancia de realizar un seguimiento del tamaño de los datos que tenga en itinerancia. Si las cuotas de almacenamiento son diferentes entre plataformas, ponga como límite de almacenamiento la más pequeña de ellas.

Depurar datos móviles

La tarea de probar la configuración de itinerancia es sencilla. Tenga en cuenta que, de nuevo, esta es una situación de todo o nada. O sus datos móviles se sincronizan al completo entre dispositivos o no se sincroniza nada. Cuando esté probando el proceso de sincronización, si bloquea el dispositivo forzará a la aplicación a intentar sincronizar los datos. Si la aplicación no hace nada, tendrá que examinar un par de cosas:

  • La causa más común para que no se sincronicen los datos es que la aplicación haya superado la cuota de almacenamiento de itinerancia. Si el tamaño total supera el límite, la aplicación no tratará de sincronizar sus datos móviles.
  • Si está almacenando sus datos en archivos, asegúrese de que tiene cerrados todos los controladores de archivos. Si deja los archivos abiertos, los tendrá bloqueados y no podrá realizar la sincronización.

Resumen

Al utilizar datos móviles en sus aplicaciones, podrá ofrecer a sus usuarios una experiencia de conectividad coherente y duradera. Como pueden compartir entre dispositivos sus configuraciones, preferencias y el estado actual de la aplicación, percibirán que, sin importar el tipo de dispositivo, siempre están utilizando la misma aplicación. Es más, si agrega la capacidad de compartir datos entre aplicaciones de la Tienda Windows y las de la Tienda de Windows Phone, incrementará la experiencia de sus usuarios y podrá ofrecerles un amplio abanico de oportunidades.


Tony ChampionMVP de Microsoft, es el presidente de Champion DS además de miembro activo de la comunidad como orador, bloguero y autor. Posee un blog en tonychampion.net. Puede ponerse en contacto con él en tony@tonychampion.net.

Gracias al siguiente experto técnico de Microsoft por revisar este artículo: Robert Green