Hosted Web Apps: creando aplicaciones universales a partir de una web
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:
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:
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:
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:
Después de todos estos cambios, el manifiesto de la aplicación tendría un aspecto parecido a este:
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:
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);
}
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" );
}
});
}
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