Hosted Web Apps: creando aplicaciones universales a partir de una web

Picture1

Con la llegada de Windows 10 se nos presenta un nuevo modelo de desarrollo de aplicaciones: las Universal Windows Platform apps. La principal ventaja de estas aplicaciones es que sólo tendremos que escribir el código, tanto de la lógica como de la interfaz de usuario una sola vez, y el mismo paquete será el que se ejecute en cualquier dispositivo con Windows 10 (desde una Raspberry Pi 2 hasta la Surface Hub de 84”, pasando por toda la gama de móviles, PCs y tablets). Evidentemente, para el código de la interfaz gráfica habrá que hacer algunos ajustes para que la visualización sea la mejor posible en cada dispositivo, con distintos tamaños y resoluciones, algo similar al diseño responsive que se lleva haciendo tiempo en la web.

Aprovechando todo esto y uno de los bridges que también llegaron con la UWP, podemos utilizar nuestra web responsive como punto de partida para crear nuestra aplicación universal. El resultado de esto sería una Hosted Web App, lo que se nos presentó como Project Westminster cuando aparecieron estos bridges. Una de las grandes ventajas de las Hosted Web Apps es que el proceso de actualización es muy rápido, ya que los cambios se hacen en El proceso de creación de estas apps es muy simple, y vamos a verlo paso por paso. Nuestro sujeto de pruebas será la nueva web de Trackseries, en su versión más responsive Smile

Creando la base del proyecto

Empezamos creando un proyecto de aplicación universal con Javascript desde Visual Studio:

Picture2

En este proyecto, aunque sea en blanco, ya vendrán algunos archivos de contenido (css, html, javascript y la carpeta con las librerías de WinJS). Estos archivos no nos interesan, ya que el contenido va a venir desde nuestro website, y por tanto eliminamos estos archivos:

Picture3

Por último, tenemos que configurar el punto de entrada de la aplicación. Por defecto, el punto de entrada de estas aplicaciones es el archivo default.html que acabamos de borrar, y por tanto debemos modificar este valor en el manifiesto de la aplicación para indicar que nuestro punto de entrada será nuestro website en lugar de un fichero del paquete:

Picture4

Además, como estas aplicaciones podrán hacer uso de las APIs de Windows desde el código de la web, debemos añadir los dominios desde donde vendrán esas peticiones a los permitidos por el sistema para llamar a sus APIs, algo que hacemos desde la pestaña de “Content URIs” de nuestro manifiesto:

Picture5

Después de todos estos cambios, el manifiesto de la aplicación tendría un aspecto parecido a este:

Picture6

Utilizando APIs de Windows desde el código de la web

Como decíamos, estas aplicaciones podrán llamar a APIs del sistema desde código que esté fuera del paquete de la aplicación. Esto quiere decir que desde el código de nuestra web, y utilizando feature detection para saber si podemos usar estas APIs, podremos hacer uso de características como toast notifications, live tiles, appointments, etc. El patrón a seguir sería siempre el mismo, desde código Javascript:

Picture7

Veamos cómo quedaría el código para cada uno de los escenarios que mencionaba antes

Toast notifications

En este caso, ya que la aplicación se basa en seguir las series que veas para que te diga cuándo son los próximos capítulos y puedas llevar registro de por dónde vas en cada serie, vamos a mandar una notificación toast para confirmarle al usuario que ha seguido una serie y que su petición se ha procesado correctamente. Para ello haremos uso de la API de notificaciones de Windows, como haríamos desde nuestra UWP:

if (Windows !== 'undefined' && Windows.UI !== 'undefined' && Windows.UI.Notifications !== 'undefined') {

var notifications = Windows.UI.Notifications;

// Cogemos el template de base para el XML de contenido de la notificación

var template = notifications.ToastTemplateType.toastImageAndText01;

var toastXml = notifications.ToastNotificationManager.getTemplateContent(template);

// Especificamos el texto del mensaje de la notificación

var toastTextElements = toastXml.getElementsByTagName("text");

toastTextElements[0].appendChild(toastXml.createTextNode(serie.name + " is now on your following series list!"));

// Especificamos la imagen para el logo de la notificación

var toastImageElements = toastXml.getElementsByTagName("image");

toastImageElements[0].setAttribute("src", "https://trackseries.blob.core.windows.net/images/50x50.png");

toastImageElements[0].setAttribute("alt", "TS logo");

// Especificamos la duración de la notificación (larga)

var toastNode = toastXml.selectSingleNode("/toast");

toastNode.setAttribute("duration", "long");

// Especificamos el audio de la notificación

var audio = toastXml.createElement("audio");

audio.setAttribute("src", "ms-winsoundevent:Notification.IM");

// Especificamos el parámetro de activación

toastNode.setAttribute("launch", '{"type":"toast","param1":' + serie.id + '}');

// Crear la notificación con el XML de contenido que hemos definido

var toast = new notifications.ToastNotification(toastXml);

// Enviar la notifiación toast

var toastNotifier = notifications.ToastNotificationManager.createToastNotifier();

toastNotifier.show(toast);

}

Picture8

Live tiles

De manera muy parecida, y utilizando la misma API, veamos como podríamos actualizar el live tile de nuestra Hosted Web App. En este caso estamos haciendo el live tile cuadrado, deberíamos hacer algo similar para cada tamaño que queramos actualizar:

if (Windows !== 'undefined' && Windows.UI !== 'undefined' && Windows.UI.Notifications !== 'undefined') {

// Creamos la notificación para el live tile desde un XML base

var notifications = Windows.UI.Notifications,

squareTile = notifications.TileTemplateType.tileSquare150x150PeekImageAndText01,

squareTileContent = notifications.TileUpdateManager.getTemplateContent(squareTile),

squareTileText = squareTileContent.getElementsByTagName('text'),

squareTileImage = squareTileContent.getElementsByTagName('image');

// Añadimos texto e imagen de la notificación

squareTileText[0].appendChild(squareTileContent.createTextNode('Unwatched episodes!'));

squareTileImage[0].setAttribute('src', highlighted.images.poster);

squareTileImage[0].setAttribute('alt', 'Notification poster image');

// Creamos la notificación a enviar usando el XML creado

var squareTileNotification = new notifications.TileNotification(squareTileContent);

var currentTime = new Date();

squareTileNotification.expirationTime = new Date(currentTime.getTime() + 600 * 1000);

// Enviamos la notificación al Live Tile con la notifiación creada y la duración establecida

notifications.TileUpdateManager.createTileUpdaterForApplication().update(squareTileNotification);

}

Creación de appointments en el calendario

Para terminar, y usando otro namespace distinto de las APIs de Windows, veamos como podemos añadir a nuestro calendario la fecha y hora de emisión de uno de los próximos capitulos de nuestras series seguidas, incluyendo todos los detalles de este capítulo en la información del appointment:

if (Windows && Windows.ApplicationModel && Windows.ApplicationModel.Appointments) {

// Creamos el appointment a añadir, con todos sus detalles (asunto, fecha, detalles, duración, ubicación…)

var appointment = new Windows.ApplicationModel.Appointments.Appointment();

appointment.subject = event.title + " - " + event.episode + " (" + event.seasonNumber + "x" + event.number +")";

appointment.startTime = event.date;

appointment.details = event.info;

appointment.duration = (45 * 60 * 1000); // 45min in 1-millisecond units

appointment.location = "TrackSeries";

// El método ShowAddAppointmentAsync devuelve el id del appointment si el usuario lo añadió a alguno de sus calendarios

// y una cadena vacía si el usuario cancela la operación antes de añadirlo al calendario

Windows.ApplicationModel.Appointments.AppointmentManager.showAddAppointmentAsync

(appointment, selectionRect, Windows.UI.Popups.Placement.default)

.done(function (appointmentId) {

if (appointmentId) {

console.log("Appointment Id: " + appointmentId);

} else {

console.log("Appointment not added" );

}

});

}

Picture9

En este caso, tenemos montada integración contínua para el código de nuestra web, de manera que en cuanto hagamos push con nuestros cambios en el código estos se publican en el site, y por tanto estarían también disponibles desde nuestra Hosted Web App al momento, facilitándonos mucho la actualización de estas características en cualquier momento ya que se producen inmediatamente. Solo quedaría generar los logos necesarios para el paquete de nuestra app, generar el appx y publicarlo en la Windows Store, y en apenas una hora tendremos una aplicación creada desde nuestra web y publicada para todos los dispositivos que tengan Windows 10, con todo lo que eso nos facilita la difusión de nuestra app.

 

Un saludo,

Gorka Madariaga (@Gk_8)

Technical Evangelist