Usando APL en una Alexa Skill

Una de las cosas que tenía pendiente de añadir a mi Alexa Skill de "Estrenos de Cine" era APL, es decir, ofrecer una respuesta que pudieran aprovechar los dispositivos con Alexa que tienen pantalla.

Alexa Presentation Language, a.k.a. APL, nace con el propósito de ofrecer a los desarrolladores de skills la creación de experiencias visuales que acompañen a la skill de voz. Mezcla conceptos de HTML y CSS, como es el marcado de contenido y los estilos, pero en una estructura nueva definida en JSON.

¿Cómo funciona APL?

Una custom skill con APL no dista de funcionar igual que cualquier otra. Lo que cambia es la respuesta que ofrece la parte server de la skill ya que no será sólo de "modo texto/speech" sino que irá acompañada de información de representación para una pantalla. Es lo que se llama un documento APL, una estructura que define cómo mostrar el contenido y una fuente de datos con la información a mostrar.

Con APL el usuario se puede beneficiar de usar una interacción con la skill no sólo con la voz sino también con la pantalla. En mi skill no he creado elementos visuales, como botones, que un usuario podría tocar. En este post voy a hablar solo de cómo añadir una representación visual a una skill como complemento de la voz. No cubriré temas como "triggers" táctiles ya que no los conozco.

El funcionamiento detallado de APL da para mucho más de un post y ya existen recursos en castellanos, como el curso de Germán, que ha sido mi referencia. Os dejo aquí en enlace. También os recomiendo la documentación oficial (en inglés). Por mi parte voy a comentar los pasos que seguí para añadir APL a una skill que no lo soportaba y señalaré conceptos básicos sobre el documento que acabaremos teniendo.

Añadiendo APL a Estrenos de Cine

Activando la interfaz de APL

Lo primero que tenemos que hacer es habilitar la interfaz de APL desde la consola Web. Para ellos nos vamos a la pestaña Build y luego, en el menú de la izquierda, clickamos en Interfaces.

Una de las opciones que tendremos desmarcadas será la de Alexa Presentation Language. Por defecto tenemos que dar soporte a un listado de dispositivos, a.k.a. Viewports, que se corresponde con una serie de tamaños y formas. Estos equivalen a los Echo Show de 1ª y 2ª generación, Echo Spot y Fire TV. La opción de dar soporte al último modelo Echo Show 5 es opcional pero yo recomiendo que lo marquéis. En mi opinión es uno de los dispositivos más chulos que tiene ahora Amazon para Alexa.

Creando el documento APL

El documento APL se puede crear directamente a mano, no es más que un fichero JSON al igual que el interaction model. Podéis partir del mío o usar alguno que ya estén publicados como el que tiene Germán del curso.

Otra buena opción es usar la herramienta que incluye la consola Web de Alexa. Desde la pestaña de Build clickamos en la opción de Display del menú a la izquierda. Eso abrirá una nueva ventana con la APL Authoring Tool.

En la ventana inicial tenemos varias opciones a nuestra disposición. Mi recomendación es empezar con un ejemplo ya existente para estudiar las partes del documento APL e irlo aprendiendo. En mi caso, estuve jugando con algunos de los ejemplos que creía que se podían adaptar a mi skill y, además, usé también como base el documento APL del curso de Germán.

Desde la propia herramienta podremos ver un resultado final de nuestro documento. Le podemos añadir datos de pruebas como si fueran el resultado de nuestra API. La siguiente imagen es el resultado de mi documento con un listado de películas de pruebas:

Es adaptable a los distintos tipos de dispositivos que teníamos seleccionados en la parte de la interfaz y se puede hacer scroll en la lista de los estrenos. De momento sólo muestro el nombre y la fecha de estreno. Además si el dispositivo es redondo (como el Echo Spot), cambio el header para que solo tenga el icono pero no el nombre de la skill.

Todas esas variantes de salida así como el documento APL separado por partes lo podéis visualizar en la herramienta. Yo en realidad no usé nada del típico "arrastrar y soltar" elementos en la pantalla y me limité a partir de un APL ya existente e irlo retocando.

Estudiando el documento APL de Estrenos de Cine

Vamos a ver cada una de las partes del documento APL final. Voy a empezar por el final del documento porque me parece más claro:

  • Una plantilla principal o mainTemplate, es la sección donde se instancian en pantalla los elementos en base a lo definido en el resto del documento. Puede aceptar unos parámetros (payload) de donde podremos referenciar cosas como el fondo de pantalla, iconos, la información a mostrar, etc. Y a la cual se le indica el layout que va a representar:

Antes de pasar a comentar el layout vamos a ver otras partes que serán referenciadas desde el mismo:

  • La primera parte del documento define que estamos usando APL y la versión del mismo
  • Además podemos importar estilos, layouts, recursos, gráficos, etc
  • En la zona de recursos podemos indicar cosas que luego usaríamos en el resto del documento. Este caso de ejemplo, que no sería necesario, enseña cómo indicar ciertos valores en campos que podemos usar luego en los estilos.
  • Los estilos, al igual que pasa con CSS, nos permiten indicar valores de representación como colores, tamaños de fuentes a usar, y combinarlos en estructuras para hacer referencia luego en el layout.
  • Para mi skill he definido dos layouts: mainLayout y moviesListLayout. El primero define la estructura principal a primer nivel: fondo, header y la lista de películas. Esta lista está realmente representada en el segundo layout, me parece mejor poder separar ambas cosas, donde además podemos indicar distintas visualizaciones para los tipos de pantalla.
  • Cada layout puede tomar parámetros. Los parámetros del mainLayout se pasan directamente desde el mainTemplate.
  • A continuación definidos el listado de items que forman parte del layout. Voy a resumir lo que se puede ver en el código. Tenemos un contenedor que ocupa toda la pantalla. Ese contenedor lleva el fondo, la cabecera y el listado de películas. Todo ese contenido lo podemos justificar y alinear.
  • Cada uno de esos items tienen un tipo que determinará las propiedades del mismo. En este caso son bastantes simples y básicos para cualquier skill. Sobre todo la parte de Image para el background y el AlexaHeader para la cabecera. Algunos ofrecen ya representaciones condicionales en base a ciertas características del viewport, como el AlexaHeader que para un dispositivo redondo sólo muestra el icono.
  • Por último tenemos un Sequence que usará el listado de películas pasado por parámetros y le aplicará su propio layout moviesListLayout.
  • El layout para las películas recibe el título y la fecha de estrenos para cada una. Es la información que mostraremos luego en los items.
  • En este layout podemos ver el uso de condicionales en APL. En este caso puse un condicional asociado al tipo de viewport ya que la representación será diferente. Concretamente en una pantalla redonda los textos tienen estilos distintos y así la información encaja bien.
  • Aparte de eso, representamos básicamente lo mismo, dos textos dentro de un contenedor. Uno para el título de la película y otro para la fecha de estreno.

Por último, una vez vista la estructura, vamos a echar un vistazo a la parte de los datos que inyectaremos a la plantilla.

  • Aquí en realidad no hay una estructura JSON predefinida sino que se tiene que corresponder con los parámetros que hemos ido pasando al template y los layouts. En mi caso es bastante simple: los datos para el layout principal (fondo, logo y título) y el listado películas con la información necesaria.
  • La parte de movies es un ejemplo que uso en la herramienta APL pero que luego no formará parte del fichero que use el backend. Ese listado se generará en server con la salida de la API.

Añadiendo la respuesta APL al back de la skill

Una vez que tenemos nuestro documento APL ya podemos pasar a modificar el backend para hacerlo compatible con este tipo de respuesta.

Antes de ponernos a escribir código debemos añadir el documento APL, el fichero JSON, a nuestro backend. En mi caso lo puse en la carpeta de resources bajo main. En realidad son dos ficheros, uno sería el documento APL con la estructura y otro el fichero con metadatos como las url de título e icono entre otros.

En cuanto al código, lo primero que tenemos que hacer es saber si el dispositivo Alexa que está usando el usuario soporta APL o no. Sabiendo eso podremos elaborar una respuesta de voz o de voz y pantalla. Podrías hacerla sólo de pantalla pero, en asistentes de voz, la pantalla se considera un complemento a la salida de voz, no un sustituto. Más sobre el tema de experiencia multi-modal en la doc oficial.

Con el SDK de Java podemos mirar esto con la siguiente línea:

Una vez podemos detectar los viewport compatibles, pasamos a añadir este tipo de respuesta a los handlers que sea necesario. En el caso de mi skill son dos: el handler que muestra los estrenos del periodo de tiempo que pregunte el usuario, y el handler que muestra la cartelera actual en el caso de que no se conozcan estrenos para la fecha indicada.

Veamos el código que construye la respuesta para uno de ellos, NewReleasesIntentHandler que se encarga de manejar la request de los próximos estrenos.

  • El código de la parte del else es el mismo que ya teníamos antes de añadir APL a nuestra skill. Simplemente genera una respuesta en modo texto.
  • El código nuevo, que se ejecuta bajo la condición de que el dispositivo sea compatible con APL y de que haya estrenos conocidos, contiene la parte interesante para este post. En resumen, lo que hacemos es crear una respuesta similar a la de voz pero añadiendo una directiva para redendizar el documento APL. Hay que pasarle el documento en cuestión, la fuente de datos y la información que hemos sacado de la API.

El código en el resto de handlers es muy similar. Podéis verlo en el repo del backend de la skill en GitHub. Se decide entre si crear la directiva para el documento APL y pasarla o crear simplemente una salida de voz.

El código es mejorable y se puede quitar duplicidad. Al final la respuesta que se genera es la misma excepto por añadir la directiva o no. Si hubiera hecho eso cuando añadí APL me hubiera ahorrado algunos problemas en certificación porque me olvidé de indicar que no se debería cerrar la sesión y tuve que repetir el proceso un par de veces. Tened eso muy en cuenta.

Además hay que vigilar casos, como en el listado que se hace scroll, de que todos los títulos se ven bien, incluso el último. En mi caso había veces que se cortaba y eso también fue detectado en la certificación. Tuve que adaptar los márgenes y fuentes para que eso no pasara.


Aún me quedan muchas cosas por pulir en el APL y lo quiero enriquecer con gráficos, como poner los posters de las películas, un rating con estrellas, etc. Además me gustaría añadir un segundo nivel de navegación para que el usuario pudiera preguntar más detalles para una de las películas y ofrecerle una segunda pantalla con los actores, duración y una pequeña descripción.

Desde luego nunca pensé que un caso de uso "tan simple" como pedir los estrenos de cine me iba a dar tanto juego :)