APL Standard Commands

See also: APL Commands and APL Media Commands.

Common Properties

A single command is encoded as a JSON object. All commands contain the following properties.

Property Type Required Description
type String Yes Type of the command
description String No Optional documentation for this command
delay Integer No Delay time in milliseconds before this command executes. Must be non-negative. Defaults to 0.
when Boolean No Conditional expression. If this evaluates to false, the command is skipped. Defaults to true.

type

Specifies the particular command to execute. This may be a pre-defined primitive command types or a user-defined command.

delay

The delay value is the amount of time in milliseconds inserted before executing this command. The delay value must be a non-negative integer, which if not specified, defaults to 0. The delay value is ignored if the when property resolves to false, or if the command is executed from within an event handler.

when

If when is set to true, execute the command. If false, ignore the command.

AutoPage command

The AutoPage command automatically progresses through a series of pages displayed in a Pager component. The AutoPage command finishes after the last page has been displayed for the requested time period.

The AutoPage command has the following known issue. Keep an eye on APL Known Issues and Bugs for updates on known issues.

  • In the Alexa simulator in the developer console, using the SpeakItem or SpeakList command with the AutoPage command does not work reliably, although this combination does work on Alexa devices.

The AutoPage command has the following properties in addition to the regular command properties.

Property Type Required Description
componentId String Yes The id of the component to read.
count Integer No The number of pages to display. Defaults to all of them.
duration Integer No Time to wait between pages (in milliseconds). Defaults to 0.

For example, to auto-page through a sports pager:

  {
    "type": "AutoPage",
    "componentId": "mySportsPager",
    "duration": 1000
  }

The AutoPage command has no effect if the count is non-positive.

When terminated, the AutoPage command:

  • Moves the display ahead to the target page if the AutoPage command sequence is at least 50% complete.
  • Returns the display to the previous page if it is not at least 50% complete.

The onPageChange command is run once with the new page if the page has changed.

componentId

The identifier of the Pager component. If omitted, the component issuing the AutoPage command is used.

count

The number of pages to display. If not specified, this defaults to the number of pages remaining. Wrapping is not supported; the count is internally clipped to fall in the range [0, pager.children.length - pager.currentIndex - 1].

duration

The amount of time to wait and display each page, including the first one. Any animated transition between pages will add to the total amount of time.

Idle command

The Idle command does nothing. It may be a placeholder or used to insert a calculated delay in a longer series of commands. For example, consider this command.

  {
    "type": "Parallel",
    "commands": [
      {
        "type": "Idle",
        "delay": 3000
      },
      {
        "type": "SpeakItem",
        "componentId": "item7"
      }
    ]
  }

This command sequence speaks "item7". The use of the Idle command guarantees that the overall command will last at least 3000 milliseconds even if the speech ends earlier.

The type of the Idle command is Idle.

Parallel command

Execute a series of commands in parallel. The Parallel command starts executing all child commands simultaneously. The Parallel command is considered finished when all of its child commands have finished. When the Parallel command is terminated early, all currently executing commands are terminated.

The type of the Parallel command is Parallel. The Parallel command has the following properties in addition to the common command properties.

Property Type Required Description
commands Array of commands Yes An unordered list of command to execute in parallel

commands

An un-ordered array of commands to execute in parallel. Once all commands have finished executing, the Parallel command finishes. The delay value set for the Parallel command is added to the delay value set for each of the commands in the array. In the following example, the first SendEvent command executes at 1500 milliseconds, and the second SendEvent command at 750 milliseconds, which means the second SendEvent command begins to execute before the first.

{
  "type": "Parallel",
  "delay": 500,
  "commands": [
    {
      "type": "SendEvent",
      "delay": 1000
    },
    {
      "type": "SendEvent",
      "delay": 250
    }
  ]
}

Scroll command

The Scroll command scrolls a ScrollView or Sequence forward or backward by a set number of pages. The Scroll command has the following properties in addition to the regular command properties.

Property Type Required Description
componentId String Yes The id of the component to read.
distance Number No The number of pages to scroll. Defaults to 1.

The distance sets how far to scroll, in pages. For example, to scroll a list forward a single page:

  {
    "type": "Scroll",
    "componentId": "myScrollingList",
    "distance": 1
  }

Scrolling stops when:

  • The destination is reached.
  • The end of the scrollable content is reached.
  • The user touches the screen.
  • A new command is received from Alexa. Termination stops scrolling immediately.

To smoothly scroll through all available content, set the distance to a large number. For example, to smoothly scroll back to the beginning of a list:

  {
    "type": "Scroll",
    "componentId": "myScrollingList",
    "distance": -10000
  }

componentId

The ID of the ScrollView or Sequence. If omitted, the component issuing the ScrollPage command is used.

distance

The scrolling distance, measured in pages. One "page" is the width or height of the ScrollView or Sequence component. Negative numbers scroll backwards. Setting distance to 0 does not scroll.

ScrollToIndex command

Scroll forward or backward through a ScrollView or Sequence to ensure that a particular child component is in view. The ScrollToIndex command has the following properties in addition to the regular command properties.

Property Type Required Description
align first | last | \center | visible No The alignment of the item after scrolling. Defaults to "visible".
componentId String Yes The id of the component to read.
index Integer Yes The 0-based index of the child to display.

For example, to scroll to show the fifth step in a recipe displayed in a list, set index to 4.

  {
    "type": "ScrollToIndex",
    "componentId": "recipeSteps",
    "index": 4,
    "align": "center"
  }

The componentId does not have to be a Sequence or ScrollView component. The ScrollToIndex command looks for the first Sequence or ScrollView at or above the componentId and scrolls that one.

Scrolling terminates if the user touches the screen. Termination stops scrolling immediately.

align

The alignment of the item on the screen after scrolling and before speech. Alignment is an enumerated value with the following options.

Alignment Description
first The top/left side of the item will be placed at the top/left side of the scrolling container.
center The center of the item will be placed in the center of the container.
last The bottom/right side of the item will be placed at the bottom/right side of the scrolling container.
visible The item will be moved the minimal distance necessary to bring it fully into view.

componentId

The identifier of the parent container. If omitted, the component issuing the ScrollToIndex command is used.

index

The 0-based index of the child item in the parent container to scroll into view. Negative values are measured from the end of the parent container. For example, to show the second-to-last item in a list:

  {
    "type": "ScrollToIndex",
    "index": -2,
  }

The algorithm for finding the item to display can be described loosely as follows:

  let itemIndex = index < 0 ? index + children.length : index;
  if (itemIndex >= 0 && itemIndex < children.length) {
    let child = children[itemIndex];
    scrollIntoView(child);
  }

SendEvent command

Use the SendEvent command to generate and send an event to Alexa. Here is an example of a SendEvent command::

{
  "type": "TouchWrapper",
  "id": "buyButton",
  "onPress": {
    "type": "SendEvent",
    "arguments": [
      "he bought it"
    ]
  },
  "item": {
    "type": "Text",
    "text": "Buy it now!"
  }
}

With SendEvent, set the following properties in addition to the regular command properties.

Property Type Required Description
arguments Array of arguments No An array of argument data to pass to Alexa.
components Array of strings No An array of components to extract value data from and provide to Alexa.

arguments

The arguments property is an array passed to Alexa. Each element in the array has data-binding applied at execution time. This allows an argument to contain data about the event itself, such as ${event.source.value}. Thus, the skill developer can send arbitrary data to Alexa.

components

The components property is an array of component ids. The value of each of these components will be reported in the event. This allows the skill author to construct a form where the contents of the form are sent directly to the server.

UserEvent

The SendEvent message is packaged into a TemplateRuntime.UserEvent message sent to the skill. The TemplateRuntime.UserEvent message takes the following approximate form.

{
  "namespace": "TemplateRuntime",
  "name": "UserEvent",
  "payload": {
    "skillID": "XYZZY",
    "directiveID": "PDQBACH",
    "arguments": [
      ARGUMENT1,
      ARGUMENT2,
      :
    ],
    "components": {
      ID1: VALUE1,
      ID2: VALUE2,
      :
    },
    "source": {
      "type": "Button",
      "handler": "Press",
      "id": "buyButton",
      "value": false
    }
  }
}

The APL runtime is responsible for passing the argument data in the larger payload structure, along with source information about the type of component that created the event, the handler called, and the id of the component.

Sequential command

The Sequential command executes a series of commands in order, waiting for the previous command to finish before executing the next. The Sequential command is finished when all of its child commands have finished. When the Sequential command is terminated early, the currently executing command is terminated and no further commands are executed.

The type of the Sequential command is Sequential. The Sequential command has the following properties in addition to the common command properties.

Property Type Required Description
commands Array of commands Yes An ordered list of command to execute in series.
repeatCount Integer No Defaults to 0.

commands

An array of commands to execute. The array of commands execute in order, and each command must finish before the next one can begin. The delay value of the Sequential command and the delay value of the first command in the sequence are additive. In the following example, the first SendEvent command executes after 3000 milliseconds.

{
  "type": "Sequential",
  "delay": 1000,
  "repeatCount": 2,
  "commands": [
    {
      "type": "SendEvent",
      "delay": 2000
    },
    {
      "type": "SendEvent",
      "delay": 2000
    }
  ]
}

repeatCount

The number of times to repeat this series of commands. Defaults to 0. Negative values will be ignored.

SetPage command

The SetPage command changes the page displayed in a Pager component. The SetPage command finishes when the item is fully in view. The SetPage command has the following properties in addition to the regular command properties.

Property Type Required Description
componentId String Yes The id of the component to read.
position relative | absolute No Whether the value is a relative or absolute offset. Defaults to absolute.
value Integer Yes The distance to move. May be an absolute or relative value.

When there are N pages in the Pager component, the first is index 0 and the last has index N-1. A relative position offsets from the current page. For example, to move one page forward:

  {
    "type": "SetPage",
    "componentId": "myWeatherPager",
    "position": "relative",
    "value": 1
  }

An absolute position sets the index of the current page. A negative absolute position is an offset from the end of the list. For example, to go to the last page:

  {
    "type": "SetPage",
    "componentId": "myWeatherPager",
    "position": "absolute",
    "value": -1
  }

No intermediate pages display when switching between two pages (unlike a Sequence). For example, if the current page is 13 and SetPage is executed with "position"="relative","value": 2, the current page will transition out and page 11 will transition in without showing page 12.

The SetPage command can set any page for display. It does not respect the allowed navigation direction in the Pager component. However, wrapping behavior affects page switch calculations, as shown in approximate algorithm.

Termination of a SetPage command jumps ahead to the target page if the SetPage command sequence is at least 50% complete, and it returns to the previous page if it is not at least 50% complete. The onPageChange command is run once on termination if the page has changed from the last page.

componentId

The identifier of the Pager component. If omitted, the component issuing the SetPage command is used.

position

If the position is relative, the value is a relative distance to move from the current page. If the position is absolute, the value is the absolute page number to which the display will move.

value

The value is either the distance to move or the absolute page number to move to.

The algorithm to calculate final position and direction can be approximated with this pseudo-code.

  if (command.position == 'absolute') {  // Absolute motion
    let index = command.value < 0 ? pager.children.length + command.value : command.value;
    index = Math.max(0, Math.min(pager.children.length - 1, index));  // Clamp range

    // Return the final index and the direction of motion
    if (index == pager.currentIndex)
      return NO_MOVE

    return (index, index < pager.currentIndex ? "LEFT" : "RIGHT");
  }
  else {  // Relative motion
    let index = pager.currentIndex + command.value;

    // If relative motion goes out of bounds and we don't support wrapping, ignore the command
    if (pager.navigation != "wrap" && (index < 0 || index >= pager.children.length))
      return NO_MOVE;

    // Wrap appropriately
    index = ((index % pager.children.length) + pager.children.length) % pager.children.length;
    if (index == pager.currentIndex)
       return NO_MOVE;

    return (index, command.value < 0 ? "LEFT" : "RIGHT");
  }

The pager animation is driven by the returned direction.

This algorithm has these characteristics:

  • Absolute values clamp within the valid range of pages. The direction is relative to the current page.

  • Relative values on a wrapping pager will wrap arbitrarily. The direction is based on the commanded value, and wrapping doesn't change the direction.

  • Relative values on a non-wrapping pager that go out of range are ignored.

SetState Command

Each component has a state used to evaluate styles and displaying the component. The SetState command changes one of the component's state settings.

The SetState command can be used to change the checked, disabled, and focused states. The focused state may only be set, and it can't be cleared.

The karaoke and pressed states canot be directly set, but you can use the SpeakItem command to change those states.

The SetState command has the following properties in addition to the regular command properties.

Property Type Required Description
componentId String No The id of the component whose value should be set.
state String Yes The name of the state to set. Must be one of checked, disabled, or focused.
value Boolean Yes The value to set on the state.

This example sets a TouchWrapper to the checked state.

{
  "type": "SetState",
  "componentId": "myButton",
  "state": "checked",
  "value": true
}

componentId

The identifier of the component whose state will change. If this property is omitted, then the component that issues the SetState command is the recipient.

state

The name of the state to change. Currently restricted to checked, disabled, and focused.

value

The value is evaluated at command execution time, so it can take advantage of existing component properties. For example, this command toggles the checked state of the current component.

{
  "type": "SetState"
  "state": "checked",
  "value": "${!event.source.value}"
}

SetValue Command

The SetValue command changes a dynamic property of a component. Refer to the specifies of each component for the values that may be set. With SetValue, the specified property of the component changes, but the screen is not redrawn. See Command evaluation.

The SetValue command has the following properties in addition to the regular command properties.

Property Type Required Description
componentId String No The id of the component whose value should be set.
property String Yes The name of the property to set.
value Boolean Yes The value to set on the property.

This example sets a value so that the punchline for a joke appears, because an opacity value of 1 means the component is fully visible.

{
  "type": "SetValue"
  "componentId": "jokePunchline",
  "property": "opacity",
  "value": 1
}

The SetValue command can be used to change the value of various properties, on a per-component basis. The specific properties that are mutable are documented for each component.

componentId

The identifier of the component whose value will change. If this property is omitted, then the component that issues the SetValue command is the recipient.

property

The name of the property to change.

value

The value is evaluated at command execution time, so it can take advantage of existing component properties. In this example, the SetValue command sets the opacity of the target component to 50% of its actual value.

{
  "type": "SetValue"
  "property": "opacity",
  "value": "${event.target.opacity * 0.5}"
}

SpeakItem command

The SpeakItem command reads the contents of a single item on the screen. The item will scroll into view if it is not currently visible. The item should have a speech property.

The SpeakItem command has the current known issues. See APL Known Issues and Bugs for updates on known issues.

  • If a SpeakItem command and either a PlayMedia or ControlMedia command are used in a Sequential command, both the video playback will interrupt speech. When this bug is fixed, the two commands will run one after the other.
  • In the Alexa simulator in the developer console, using the SpeakItem command with the AutoPage command does not work reliably, although this combination does work on Alexa devices.

The SpeakItem command has the following properties in addition to the regular command properties.

Property Type Required Description
align first | last | center | visible No The alignment of the item after scrolling. Defaults to "visible".
componentId String Yes The id of the component to read.
highlightMode line | block No How karaoke is applied: on a line-by-line basis, or to the entire block. Defaults to "block".

For example, to read the contents of a single text component and ensure it is aligned in the center of the screen:

  {
    "type": "SpeakItem",
    "componentId": "myJokeSetup",
    "highlightMode": "line",
    "align": "center"
  }

The karaoke state of the component is set to true during the speech and reset to false after the speech completes. The highlightMode only applies to Text components. When a Text component is read in "highlightMode": "line" mode, individual lines of text are set to the karaoke state during speech and reset to false after speech completes.

Note these restrictions:

  • The SpeakItem command does not scroll the content during speech in block mode. For example, if the component is larger than the scrolling container of the component, those parts of the component that are not visible after scrolling will remain hidden.

  • Components on round screens should use center alignment, or much of the content will not be visible.

  • SpeakItem does not highlight individual words or lines of text during speech.

  • The algorithm used to scroll the item into view assumes there is only a single scrolling component. Nested scrolling components are not supported.

  • Components without a speech property will still scroll into view.

When a SpeakItem command is terminated early, it clears any visual changes and stops speech immediately.

align

The alignment of the item on the screen after scrolling and before speech. Alignment is an enumerated value with the following options.

Alignment Description
first The top/left side of the item will be placed at the top/left side of the scrolling container.
center The center of the item will be placed in the center of the container.
last The bottom/right side of the item will be placed at the bottom/right side of the scrolling container.
visible The item will be moved the minimal distance necessary to bring it fully into view.

componentId

The ID of the spoken component. If omitted, the component issuing the SpeakItem command is used.

highlightMode

Controls how contents of a Text component are styled during speech. If set to "block", the entire Text component has the karaoke state set to true during speech. If highlightMode is set to "line", the individual lines of the Text component are treated separately. Each line will scroll to match the align property and be styled separately. In line-by-line karaoke mode, the only styling change accept is the color property; other properties are ignored.

SpeakList Command

Read the contents of a range of items inside a common container. Each item will scroll into view before speech. Each item should have a speech property.

The SpeakList command has the current known issues. See APL Known Issues and Bugs for updates on known issues.

  • If a SpeakList command and either a PlayMedia or ControlMedia command are used in a Sequential command, both the video playback will interrupt speech. When this bug is fixed, the two commands will run one after the other.
  • In the Alexa simulator in the developer console, using the SpeakList command with the AutoPage command does not work reliably, although this combination does work on Alexa devices.

The SpeakList command has the following properties in addition to the regular command properties.

Property Type Required Description
align Enum. One of: first | center | last | visible No The alignment of the item. Defaults to visible.
componentId String Yes The id of the [Sequence][apml-sequence or Container (or any other hosting component).
count integer Yes The number of children to read.
minimumDwellTime number No The minimum number of milliseconds that an item will be highlighted for. Defaults to 0.
start integer Yes The index of the item to start reading.

The minimumDwellTime prevents items with short titles from being read too quickly. For example, a series of movie titles like "Venom", "Fences", and "Dear Zachary: A Letter to a Son About His Father" needs some dwell time for the first two items.

This example reads three components out of the middle of a list and ensures that each aligns in the center of the screen:

{
  "type": "SpeakList",
  "componentId": "movieList",
  "start": 3,
  "count": 3,
  "minimumDwellTime": 700,
  "align": "center"
}

The karaoke state of the component is set to true during the speech of each component and reset to false after that speech completes.

Note these characteristics of the SpeakList command:

  • The SpeakList command does not scroll the content during speech. For example, if the component is larger than the scrolling container of the component, those parts of the component that are not visible after scrolling will remain hidden.
  • Components on round screens should use center alignment, or much of the content will not be visible.
  • SpeakList does not highlight individual words or lines of text during speech.
  • To scroll the item into view, the component hierarchy is searched upwards to find the first ancestor that can be scrolled.
  • The algorithm that used to scroll the item into view assumes there is only a single scrolling component. SpeakList does not support nested scrolling components.
  • Components without a speech property will still scroll into view.
  • Components without a speech property, but with a positive minimumDwellTime, will have karaoke set for that time.
  • Components without a speech property and no minimumDwellTime will not have karaoke set.

align

The alignment of the item on the screen after scrolling and before speech. Alignment is an enumerated value with the following options:

Alignment Description
first The top/left side of the item will be placed at the top/left side of the scrolling container.
center The center of the item will be placed in the center of the container.
last The bottom/right side of the item will be placed at the bottom/right side of the scrolling container.
visible The item will be moved the minimal distance necessary to bring it fully into view.

componentId

The ID of the parent component. If omitted, the component issuing the SpeakList command is used.

count

The number of items to speak. The command does not execute if the count is less than 1 (no scrolling, no speech). If the count is larger than the number of remaining items in the container, it is trimmed to the maximum number of items that can be spoken from the starting point.

minimumDwellTime

The minimum amount of time in milliseconds that an item will be highlighted (that is, have the karaoke state set to true). This defaults to 0.

start

The 0-based index of the first child item in the parent container to scroll into view and speak. Negative values are measured from the end of the parent container. This example the last three items in a list:

{
  "type": "SpeakList",
  "start": -3,
  "count": 3
}

The following algorithm approximates how the reading is done.

let first = start < 0 ? start + children.length : start;
   let last = Math.min(first + count, children.length  1);

first = Math.max(0, first);

for (let index = first ; index <= last ; index++) {
  let child = children[index];
  scrollIntoView(child);

  if (child.speech) {
    child.setState("karaoke", true);
    speakChildWithMinimumDwell(child, minimumDwellTime);
    child.setState("karaoke", false);
  }
  else if (minimumDwellTime > 0) {
    child.setState("karaoke", true);
    waitForTimeout(minimumDwellTime);
    child.setState("karaoke", false);
  }
}