Post invitado: App Services en la Universal Windows Platform

En el artículo Creando una red de apps con la Universal Windows Platform comentamos diversas maneras para que nuestras apps puedan compartir información entre sí y con otras apps en Windows 10. Nos quedó pendiente hablar en detalle de los App Services. Hoy os compartimos un post invitado de Javier Suárez Ruiz, MVP Windows Platform Development, que nos habla de los Apps Services en detalle.

 

Introducción

Desde anteriores versiones de plataformas Windows como desarrolladores teníamos la posibilidad de interactuar entre aplicaciones. Se puede interactuar con aplicaciones del sistema, como el correo o los contactos. Además, se podían crear asociaciones entre diferentes aplicaciones creando asociaciones de archivos entre otras opciones.

Estas posibilidades permitían la posibilidad de crear grandes aplicaciones concentradas en un subconjunto de funcionalidad de forma excelente, permitiendo que ante otras opciones la aplicación interactuase con otra para hacer otra función. Pongamos un ejemplo, podíamos crear la mejor aplicación posible para trabajar con PDF sin la necesidad de implementar todas las opciones posibles para compartir documentos. Se puede enviar el documento a una segunda aplicación excelente compartiendo, permitiendo compartir en infinidad de opciones locales y en la nube.

A pesar de las posibilidades, siempre hay opciones no posibles para los desarrolladores que son deseadas.

¿Y si pudiésemos crear “web services” por aplicaciones que permitan su uso por otras aplicaciones?

Abriría un abanico inmenso de posibilidades. Con Windows 10, entre el enorme conjunto de controles, APIs y herramientas nuevas disponibles destaca con luz propia los App Services.

App Services

Hasta ahora la comunicación entre aplicaciones estaba limitada a las siguientes opciones:

· Utilizando opciones de compartir.

· Mediante extensiones de fichero.

· Utilizando protocolos que permiten pasar información a la aplicación (limitado en caracteres).

Aunque lo anterior aportaba puntos de comunicación que cubrían ciertas necesidades, era limitado; no hay comunicación de retorno a la aplicación inicial, etc.

App Services llega para aportar una nueva forma de comunicación. Resumido en una frase, podemos decir que, aportan un tipo de servicio local hosteado por una aplicación Windows que permite su utilización por otras aplicaciones Windows.

clip_image002

Podemos utilizar el servicio para infinidad de oportunidades. Veamos un ejemplo simple:

clip_image004

Tenemos una aplicación destinada a leer código de barras en diferentes formatos. En lugar de contar con esa lógica incluida en la aplicación, la incluye en un servicio. Esto permitirá a otras aplicaciones poder utilizar el servicio promoviendo la comunicación e integración entre aplicaciones. De esta forma, además, se consigue que las aplicaciones sean excelentes en su funcionalidad, aportando funcionalidad extra basándose en otras grandes aplicaciones ofreciendo servicios.

Creando un servicio de Aplicación

Vamos a probar las posibilidades de los servicios de aplicación creando un servicio, una aplicación proveedora del mismo y una aplicación cliente que utilice el servicio.

Comenzamos creando la parte más importante, el servicio. Para centrarnos en las posibilidades, configuración, ciclo de vida y características exclusivas del servicio, este será simple. Nuestro servicio será una calculadora simple permitiendo realizar las operaciones básicas.

Abrimos Visual Studio y dentro del apartado Universal en Windows, elegimos la creación de un componente Windows en tiempo de ejecución.

clip_image006

Añadimos la lógica de nuestra calculadora.

clip_image008

Nada especial en ella. Una clase sencilla con tres métodos:

· Add: Suma dos enteros.

· Substract: Resta un entero al de mayor tamaño.

· Multiply: Multiplica dos enteros.

Nos centramos ya en nuestro servicio. App Services utilizan la misma infraestructura que las BackgroundTasks. Por lo tanto la implementación es bastante similar y podemos deducir que, cuando se produce una llamada al servicio, esta corriendo el servicio no toda la aplicación.

Creamos una clase CalculatorTask derivada de IBackgroundTask:

clip_image010

NOTA : El nombre la clase es siempre importante pero en este caso cobra un peso especial ya que será importante al asociar la aplicación con el servicio vía Entry Point.

Definimos una clase sealed que implementa la interfaz IBackgroundTask que nos exigirá implementar el método Run(IBackgroundTaskInstance taskInstance) encargado de ejecutar nuestro servicio en background.

clip_image011

Comenzamos accediendo al BackgroundDeferralTask utilizando el método taskInstance.GetDeferral(). Este notifica al sistema que nuestro proceso en segundo plano continuara trabajando tras finalizar el método Run. Bastará con recordar utilizar el método BackgroundTaskDeferral.Complete() una vez finalizado el trabajo.

Utilizamos AppServiceTriggerDetails, que cuenta con información asociada al servicio de aplicación para registrarnos al evento RequestReceived. Este evento se lanzara cada vez que se realice una petición al servicio.

Visto el código básico del método Run, nos centramos en contemplar el necesario caso de cancelación. Utilizamos el método Complete del BackgroundTaskDeferral para dar por concluido las posibilidades de trabajo en segundo plano del servicio.

clip_image012

Cuando se realiza una petición al servicio como hemos mencionado previamente, se lanza el evento RequestReceived del servicio:

clip_image014

La comunicación con el servicio se realiza pasando parámetros utilizando ValueSet. Accedemos al argumento de tipo AppServiceRequestReceivedEventArgs para obtener la propiedad Message que contendrá todos los valores del ValueSet a los que podremos acceder mediante la clave utilizada.

En este momento capturaremos los mensajes para actuar en consecuencia.

En nuestro ejemplo accedemos al tipo de operación a ejecutar junto a los valores utilizados para utilizar nuestra clase Calculator de forma correcta.

Claro que si una aplicación hace uso de nuestro servicio, envía un par de valores para realizar por ejemplo una suma, espera…la respuesta con el valor calculado correcto.

Utilizamos de nuevo un ValueSet para devolver el valor utilizando el método SendResponseAsync. Como parámetro le indicamos el valor que deseamos devolver.

Aplicación que proporciona el servicio

Tenemos en este punto un servicio que permite realizar cáculos simples que una aplicación Windows permitirá utilizar a otras aplicaciones.

Continuamos con la aplicación q

ue proporcionara el servicio. Comenzamos asociando el servicio de aplicación con la aplicación en si. Para ello, nos dirigimos al archivo de manifiesto de la aplicación. En la pestaña de declaraciones añadimos una nueva declaración de tipo Servicio de aplicaciones.

clip_image016

A continuación especificamos un nombre del servicio y el punto de entrada al mismo. El nombre será necesario para otras aplicaciones para acceder al mismo. En cuanto al punto de entrada, es el namespace y nombre de la tarea en segundo plano donde definimos nuestro servicio.

En cuanto a nuestra aplicación proveedor hara poco más. Tan solo un único detalle. Para acceder al servicio asociada a esta aplicación, otras aplicaciones utilizaran:

· El nombre del servicio como mencionamos previamente.

· El nombre de la familia del paquete de la aplicación que provee el servicio.

Dado que será necesario, creamos un servicio que nos permita acceder a la información requerida. Podemos acceder a una gran variedad de propiedades del paquete de la aplicación utilizando la clase Package disponible en el namespace Windows.ApplicationModel.

clip_image017

Sencillo. Utilizaremos el servicio creado desde la ViewModel de la vista principal (y única) de nuestra aplicación:

clip_image018

La vista mostrará el nombre de la familia del paquete:

clip_image020

Si ejecutamos la aplicación, vemos lo indicado.

clip_image022

Nada aparentemente especial. Sin embargo, recordad que la aplicación ya cuenta con el servicio asociado.

Aplicación que utiliza el servicio

Llegamos a parte vital y esperada, vamos a crear una segunda aplicación universal Windows desde la que accederemos y utilizaremos el servicio.

Comenzamos conectando con el mismo. Crearemos una instancia de la clase AppServiceConnection utilizando como parámetros el nombre del servicio (definido previamente) y el nombre de la familia del paquete de la aplicación que proporciona el servicio.

clip_image024

Una vez creada la conexión con el punto de entrada del servicio de aplicación, estableceremos la conexión con el mismo. Para ello, utilizamos el método OpenAsync().

clip_image025

Como nos indica el propio nombre, abre una conexión con el punto de entrada. Este método nos devolverá un valor de la enumeración AppServiceConnectionStatus.

clip_image027

Esta enumeración cuenta con los siguientes valores:

· Success: La conexión con el servicio de aplicación se ha establecido con éxito.

· AppNotInstalled: No se puede conectar con el servicio porque la aplicación que provee el mismo no esta instalada.

· AppUnavalaible: De forma temporal la aplicación que facilita el servicio no esta disponible.

· AppServiceUnavalaible: La aplicación con el nombre de familia de paquete utilizado esta instalada pero no cuenta con un servicio con el nombre del que estamos intentando acceder.

· Unknown: Error no determinado inesperado.

De esta forma conectamos con el servicio. De igual forma, y aunque profundizaremos más en el ciclo de vida del servicio a continuación, debemos preocuparnos por cerrar la conexión con el mismo.

clip_image029

Hacemos un Dispose de la conexión y es suficiente. Si no necesitamos acceso al servicio es una buena práctica para evitar que el servicio utilice CPU y memoria de manera innecesaria.

Nuestro servicio se activa bajo demanda. Se utiliza un trigger de tipo AppServiceTrigger que activa la tarea en segundo plano. La terminación del servicio puede venir dada o bien haciendo un Dispose de la conexión, o bien, enviando un mensaje al servicio con instrucciones para terminar.

Ya contamos con servicio, aplicación proveedora y aplicación que hará uso del mismo con la conexión y desconexión. Antes de continuar vamos a centrarnos en las posibilidades buscadas en la aplicación.

En la ViewModel contaremos con las siguientes propiedades y comandos:

clip_image031

Contaremos con propiedades para especificar los valores de cada operación además del resultado devuelto por el servicio y una serie de comandos que permitirán ejecutar las acciones de suma, resta y multiplicación además de poder abrir y cerrar conexión con el servicio.

A nivel de interfaz:

clip_image033

Nada complejo. Dos cajas de texto para poder capturar los valores de la operación por parte del usuario y una serie de botones para poder realizar todas las acciones permitidas.

Todas las acciones que realizaran petición al servicio, es decir, suma, resta y multiplicación realizarán una serie de pasos similares.

Primero, si la conexión no esta abierta, realizaran la apertura de la misma.

clip_image035

A continuación, se capturaran los parámetros a enviar al servicio utilizando un ValueSet.

clip_image036

Como vemos, son los valores a enviar para utilizar en la operación además del tipo de operación en si.

Se envía la petición al servicio utilizando el método SendMessageAsync.

clip_image038

Revisamos el valor de la respuesta capturada en un objeto de tipo AppServiceResponse. Cuenta con propiedad Status de tipo AppServiceResponseStatus con las siguientes posibilidades:

· Success: El servicio ha recibido y procesado los parámetros correctamente.

· Failure: El servicio fallo recibiendo y/o procesando parámetros.

· ResourceLimitsExceeded: No se completo con éxito la operación por falta de recursos. Insuficientes recursos en el sistema pueden provocar errores.

· Unknown: Error no determinado.

En base el estado podemos actuar en consecuencia:

clip_image040

Si ejecutamos la aplicación, establecemos dos valores y pulsamos sobre un botón de acción que realice llamada al servicio:

clip_image042

Se establece la conexión, se envían los parámetros correspondientes y se produce el retorno del valor calculado correspondiente.

Como hemos podido verificar la comunicación con un servicio de aplicación puede ser bidireccional.

Depurando App Services

A la hora de desarrollar el servicio probablemente necesitaremos depurar en algún momento.

El procedimiento normal realizado será establecer puntos de ruptura en el servicio y ejecutar la aplicación que hace uso del servicio. Sin embargo, realizando estos pasos…

clip_image044

La aplicación nunca se detiene en nuestros puntos de ruptura.

Depurando App Services

Para depurar App Services realizaremos los siguientes pasos:

1. Establecemos los puntos de ruptura deseados en el código del servicio.

2. Marcamos la casilla “Do no launch, but debug my code when it starts” en la pestaña Debug de las propiedades del proyecto.

clip_image046

3. Ejecutamos el servicio. No pasara nada. Tranquilo, es lo esperado.

4. Ejecutamos la aplicación cliente que conectara y utilizara el servicio.

5. Nuestros puntos de ruptura saltaran y podremos depurar el servicio.

Practicas recomendadas

Cuando trabajamos con servicios de aplicación existen una serie de recomendaciones y detalles a tener en cuenta.

Versionado de App Services

Al igual que en servicios web, podemos necesitar distintas versiones del servicio de aplicación.

Si necesitamos un cambio importante en el servicio y deseamos versionar, podemos exponer un nuevo punto de entrada (endpoint), por supuesto, siempre manteniendo compatibilidad hacia atrás.

Distribución y reutilización

Se puede envolver el servicio de aplicación en un SDK con el objetivo de poder distribuirlo utilizando NuGet. Es una opción muy recomendada si quieres que tu servicio sea utilizado con facilidad en otros proyectos o por otros desarrolladores.

Conclusiones

Tenéis disponible el ejemplo completo de nuestro servicio calculadora en el siguiente enlace. Os animamos a bajarlo, probarlo y modificarlo todo lo necesario para “jugar” con las posibilidades de servicios de aplicaciones.

Los servicios de aplicaciones nos parece una de las novedades más flexibles e interesantes de las incluidas con la llegada de Windows 10. Las posibilidades de comunicación entre aplicaciones se incrementan. Y a vosotros, ¿qué os parecen?, ¿qué posibilidades se os pasan por la cabeza? .

Más información

· Sesión muy recomendable del //BUILD 2015 donde se repasa paso a paso las características principales de App Services: App-to-App Communication: Building a Web of Apps

· Artículo donde se repasan las posibilidades de comunicación App to App en Windows 10: Using cross-app communication to make apps work together (10 by 10)

 

 

Javier Suárez Ruiz, MVP Windows Platform Development