Returning APL-A Responses

Up until this point, anytime we want Alexa to speak anything to the user in response to a request, we have used the speak() function on the response builder, like this:

 return​ handlerInput.responseBuilder
  .speak(​"Hello world!"​)
  .getResponse();

But now we’re going to ask Alexa to send back audio rendered from an APL-A template, so we’ll need to do something a little different. Instead of calling speak(), we’ll return a directive that tells Alexa to send audio from a given template. The code to build your response builder will change to look something like this:

 return​ handlerInput.responseBuilder
  .addDirective({
 "type"​: ​"Alexa.Presentation.APLA.RenderDocument"​,
 "document"​: {
 // APL-A document goes here ...
  },
  })
  .getResponse();

The addDirective() function sends a directive, given as a function parameter, to the user’s device. A directive can be thought of as a lower-level API for interacting with an Alexa-enabled device in order to control the device in some way or request state from the device. In this case, the directive sent is Alexa.Presentation.APLA.RenderDocument, which causes an APL-A template to be rendered as audio.

When sending APL-A via addDirective(), the audio produced from the APL-A template plays immediately in response to the handled intent. But you can also send APL-A as a reprompt to be played if the user doesn’t respond to a question asked by Alexa. To send APL-A as a reprompt, sent it via addDirectiveToReprompt() like this:

 return​ handlerInput.responseBuilder
  .addDirective({
 "type"​: ​"Alexa.Presentation.APLA.RenderDocument"​,
 "document"​: {
 // APL-A document goes here ...
  },
  })
  .addDirectiveToReprompt({
 "type"​: ​"Alexa.Presentation.APLA.RenderDocument"​,
 "document"​: {
 // Reprompt APL-A document goes here ...
  },
  })
  .getResponse();

The document property of the directive specifies the APL-A template you want rendered. How you fill in that property will vary slightly based on where you want the APL-A template to reside.

As you were working in the APL-A editor, you no doubt noticed the floppy-disc and download icons in the upper right corner. These icons offer two ways of saving your APL-A template:

  • The floppy-disc icon saves the template in the APL-A editor. This is known as a “saved template”. This allows you to come back and work on the same template later. But it also makes it possible to reference your template when returning a response from the skill’s request handler.

  • The download icon downloads the APL-A document to your local filesystem. From there, you can copy the JSON file into your skill project and reference it from there when returning a response from the skill’s request handler.

Either option is valid and offers its own set of benefits. As you make your decision, consider the following pros and cons of each option:

  • If you save the template in the APL-A editor using the floppy-disc icon, then you’ll enjoy a more streamlined way of editing and deploying the template directly in the editor. But you’ll be sacrificing the ability to manage it in a version control system.

  • If you choose to download the template to your local filesystem, you’ll be able to save the template and manage it in the same version control system alongside the rest of your skill’s code. But every time you edit the template, you’ll need to download the freshest version and copy it over the previous version before deploying your skill.

Once you’ve decided which option you’ll use to save your APL-A template, you’ll need to edit the request handler in your skill to return the directive that references that skill. We’ll start by seeing how to return a saved template from a request handler.

Returning Saved Templates

If you chose to use a saved template (for example, by clicking the floppy-disc icon in the editor), then filling in the directive’s document property is as simple as adding two sub-properties: type to tell the directive that you’ll be referencing the APL-A template as a link, and src to give the document URL for the template.

For example, suppose you want to use the welcome template we created in section Mixing Sounds in the response for a launch request. And, suppose that you had saved that template in the APL-A editor with the name “welcome”. In that case, the launch request handler would return the directive as shown here:

 return​ responseBuilder
      ​ .addDirective({
           ​​"type"​: ​"Alexa.Presentation.APLA.RenderDocument"​,
           ​​"document"​: {
             ​​"type"​: ​"Link"​,
             ​​"src"​: ​"doc://alexa/apla/documents/welcome"
           ​}
         ​})
  .getResponse();

When referencing saved templates, the type property should always be “Link”. As for the src property, it always takes the form of doc://alexa/apla/documents/_TEMPLATE NAME_. If the template was saved with the name “welcome”, then the complete URL is doc://alexa/apla/documents/welcome.

If you need to send model data to the template as parameters, then you’ll need to specify a datasources property in the directive. For example, let’s say that you want to return one of the templates we created in section Conditionally Selecting Sounds to tell the user to enjoy their trip. Those templates referenced the trip’s destination with the “${payload.trip.destination}” expression.

Assuming that you saved the template with the name “enjoyYourTrip”, then you can pass the destination from the request handler to the APL-A template with a directive that looks like this:

 return​ handlerInput.responseBuilder
       ​.addDirective({
           ​​"type"​: ​"Alexa.Presentation.APLA.RenderDocument"​,
           ​​"document"​: {
             ​​"type"​: ​"Link"​,
             ​​"src"​: ​"doc://alexa/apla/documents/enjoyYourTrip"
           ​},
           ​​"datasources"​: {
             ​​"trip"​: {
               ​​"destination"​: destination
             ​}
           ​}
         ​})
  .getResponse();

Notice that payload doesn’t appear in the datasources property. That name is the template-local name for the object set to the datasources property.

One very important thing that you should know about using saved templates is that if you ever change your template, you’ll need to rebuild the interaction model after saving your changes. Until the interaction model is rebuilt, the APL-A changes won’t be picked up and the previous version will still be active.

Now let’s see how to send a directive for APL-A templates that you have downloaded from the APL-A editor.

Rendering Downloaded Templates

As it turns out, the document property of the directive is actually intended to hold the entire APL-A template. While linking to a saved template as shown in the previous section helps avoid a lengthy and messy copy-and-paste of APL-A into a skill’s request handlers, it is absolutely possible to include the entire APL-A template as the value of the document property. The following snippet shows how this might look:

 return​ responseBuilder
  .addDirective({
   ​ ​"type"​: ​"Alexa.Presentation.APLA.RenderDocument"​,
     ​​"document"​: {
 "type"​: ​"APLA"​,
 "version"​: ​"0.9"​,
 "mainTemplate"​: {
 "item"​: {
 "type"​: ​"Speech"​,
 "content"​: ​"Welcome to Star Port 75 Travel!"
  }
  }
  }
  })
  .getResponse();

This may not seem all that bad at first glance. But this is also using a very simple APL-A template. Imagine what this might look like if it were a richer and more interesting APL-A template. Suffice it to say that it would make the request handler code more difficult to read and would be essentially littering handler logic with presentation code.

Rather than hard-code the document directly in the request handler, a better way is to copy the downloaded APL-A template into your skill project somewhere under the lambda directory alongside the skill fulfillment code. To keep it separate from the rest of the fulfillment code, you could create a subdirectory under lambda named apl-a and place your APL-A templates there.

For example, had you downloaded the welcome template and placed it in lambda/apl-a/welcome.json, then you could use the require() function to insert it into the rendering directive like this:

 return​ responseBuilder
      ​ .addDirective({
           ​​"type"​: ​"Alexa.Presentation.APLA.RenderDocument"​,
           ​​"document"​: require(​'./apla/welcome.json'​)
         ​})
  .getResponse();

This way, the two concerns of request-handling and presentation remain separate. Moreover, the request handler code remains relatively clean and easy to read.

Passing model data as parameters to a downloaded template that is pulled in using require() is no different than if it were a saved template. Here’s how you’d use require() to reference a downloaded enjoyYourTrip.json template, passing in the destination as model data:

 return​ handlerInput.responseBuilder
       ​.addDirective({
           ​​"type"​: ​"Alexa.Presentation.APLA.RenderDocument"​,
           ​​"document"​: require(​'./apla/enjoyYourTrip.json'​),
           ​​"datasources"​: {
             ​​"trip"​: {
               ​​"destination"​: destination
             ​}
           ​}
         ​})
  .getResponse();

You may be wondering if it’s possible to use both the speak() function and return the Alexa.Presentation.APLA.RenderDocument directive in the same response. In short, yes you can, as shown in the following example:

 return​ handlerInput.responseBuilder
   ​.addDirective({
       ​​"type"​: ​"Alexa.Presentation.APLA.RenderDocument"​,
       ​​"document"​: require(​'./apla/enjoyYourTrip.json'​),
       ​​"datasources"​: {
         ​​"trip"​: {
           ​​"destination"​: destination
         ​}
       ​}
     ​})
  .speak(​"Thanks for planning your trip with Star Port 75 Travel!"​)
  .getResponse();

Although it doesn’t make much sense to mix speak() with APL-A, it does work. If you use both together, the text given to the speak() function will be spoken first. Then, the audio produced by the APL-A template will follow.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset