APL Extensions (APL 1.5 to 2023.2)
(This is not the most recent version of APL. Use the Other Versions option to see the documentation for the most recent version of APL)
Extensions are optional enhancements to an APL runtime that provide additional sources of data, commands, and event handlers. Extensions provide additional functionality to APL, but a given extension might not be available on all devices.
Available extensions:
Request an extension
Before you can use an extension in an APL document, your skill must request it. For some extensions, you must do two steps:
- Request the extension in the skill manifest.
- Request the extension in the APL document.
Not all extensions must be included in the manifest. Refer to the documentation for the extension for the extension-specific requirements.
Request an extension in the skill manifest
For some extensions, you must declare the extension in the skill manifest before you can use it. In addition, some extensions have default behavior that you can turn on or off in the manifest.
Declare these extensions in the manifest in apis.custom.interfaces
, in the ALEXA_EXTENSION
interface. The ALEXA_EXTENSION
interface has the following properties.
Name | Type | Description |
---|---|---|
|
String |
Must be |
|
Array of objects |
Contains an array of extensions you want to use in your APL document. Each object in the array has the See the documentation for the extension to determine its |
|
Array of objects |
Contains an array of extensions that you can configure with default behavior. This lets you turn on "no code" behavior for extensions that support it. Each object has two properties:
For example, for the smart-motion extension, you can set a default |
The following example illustrates the manifest configured for the smart-motion and entity-sensing extensions. In this example, the smart-motion extension uses turnToWakeWord
as its default wake word response.
{
"apis": {
"custom": {
"interfaces": [
{
"type": "ALEXA_EXTENSION",
"requestedExtensions": [
{
"uri": "alexaext:smartmotion:10"
},
{
"uri": "alexaext:entitysensing:10"
}
],
"autoInitializedExtensions": [
{
"uri": "alexaext:smartmotion:10",
"settings": {
"wakeWordResponse": "turnToWakeWord"
}
}
]
}
]
}
}
}
For details about the settings you can configure for an extension, see the documentation for that extension. The smart-motion extension has settings you can configure in the skill manifest.
Request an extension in the APL document
To use the commands, properties, and event handlers from an extension, you must explicitly request the extension in your APL document or in an imported APL package. Then, before you use an extension in the document, verify whether the device supports the extension.
You request the set of extensions to load in the extensions
property. The extensions
property contains a list of objects, each with a name
property you use to refer to the extensions, and the uri
for the extension. The extension defines the specific uri
. You set the name
to the string value you want to use when referring to the extension.
For example, assume there is an extension that reads current weather information and has the URI "aplext:weather_info_deluxe:v10".
{
"type": "APL",
"version": "2024.2",
"extensions": [
{
"name": "Weather",
"uri": "aplext:weather_info_deluxe:v10"
}
]
}
The APL document can check the whether the weather extension exists on the user's device by reading ${environment.extension.Weather}
.
Each extension has a unique uri
. The URI is defined by the extension and is documented with the the extension. For example, the Backstack extension uses the uri
"aplext:backstack:10".
APL attempts to load all extensions requested by the document and associated packages. It is legal to load the same extension using two different names; both names will work for sending extension commands and registering extension event handlers. Using one name to request two different extensions will fail and prevent the document from loading.
The extensions
property in the data-binding context exposes the state of the requested and loaded extensions.
For more about how a document requests an extension, see the document extensions
property. For more about getting the global properties from an extension, see the environment.extensions
property.
Extension settings
The document settings
property can contain settings information for the requested extension. The requested extension retrieves settings information using the aliased name of the extension. Because APL loads the extension before processing and displaying the document, the settings
property can't access data-binding.
For example, consider a runtime extension that enables customized metric logging. The metric-logging extension could use settings
to configure core information about the client:
{
"type": "APL",
"version": "2024.2",
"extensions": [
{
"name": "ManyMetrics",
"uri": "aplext:many_metrics.somebigcompanyname.com:1.2"
}
],
"settings": {
"ManyMetrics": {
"applicationName": "MyMovieSearcher",
"applicationCategory": "Entertainment",
"applicationAuthor": "Generic Movie Corp"
}
}
}
In the above example, the document requests the extension under the alias "ManyMetrics". The runtime is responsible for checking for the presence of that extension and passing the "settings.ManyMetrics" object to it if it exists.
A single extension might be requested multiple times by a single document under different aliases. This can occur if the same extension is listed multiple times in the document extensions
property or if the same extension is requested by different packages. Each alias is represented in the "environment.extension
" environment property. Because a given extension can only be loaded once, any extension settings
are merged together before the extension is loaded. The settings
are merged in package order, so later packages (and the document) override settings defined in earlier packages.
It can be difficult to identify setting-merge errors, so it is recommended that extensions with settings should only requested by a single package or by the main document.
Extension commands
An "extension" command is a custom command defined by a registered extension
. Extension commands inherit all the base command properties, so they automatically support type
, description
, delay
, screenLock
, sequencer
, and when
. The registered extension
may specify additional required or optional properties in the extension command.
Extension commands are invoked in the same way as regular commands. The type
of the command should be set to the "EXTENSION_NAME:COMMAND_NAME", where EXTENSION_NAME is the name
property used when requesting the extension and COMMAND_NAME is the extension's defined command name. In other words the name
property defined when requesting an extension is used as a namespace
when invoking the extension command.
As an example, assume an APL-enabled fishtank with the FishFeeder
extension (URI="aplext:fishfeeder:10"). This extension provides a custom command named "Feed" that requires the "amount" property be set to a number between 1 and 100 (grams of fish food). The following examples show how an APL document can use this command:
{
"type": "APL",
"version": "2024.2",
"extensions": [
{
"name": "Fish",
"uri": "aplext:fishfeeder:10"
}
],
"mainTemplate": {
"items": [
{
"when": "${environment.extension.Fish}",
"type": "Container",
"data": [
10,
25,
100
],
"items": {
"type": "TouchWrapper",
"items": {
"type": "Text",
"text": "Feed my fish ${data} grams of food"
},
"onPress": {
"type": "Fish:Feed",
"amount": "${data}"
}
}
},
{
"description": "Fallback in case no FishFeeder extension",
"type": "Text",
"text": "No FishFeeder available"
}
]
}
}
The above example requests the "aplext:fishfeeder:10" extension. If the extension is installed, it creates a list of three buttons; if not installed it shows a warning message. Each button generates a Feed
custom event and specifies the amount of food to dispense.
Extension event handlers
APL extensions can send custom events to the document. These custom events are received in the document by extension event handlers. Each APL extension may define any number of custom events. Refer to the extension's documentation to find the names of the events and if they are invoked in normal or fast mode.
The event received in the event handler has the form:
"event": {
"source": {
"type": "Document",
"handler": NAME, // Name of the handler
"id": null, // No value reported
"uid": null, // No value reported
"value": null // No value reported
}
}
The extension event handler may report additional property values at the same level as the "event" property. For illustration we will assume an extension "aplext:remotebutton:13" supporting a wireless physical button. When the button is pushed, the extension sends an "OnPress" event containing the properties "buttonName" and "buttonColor" (we'll assume that the button has a name and randomly changes color). The data-binding context generated by this event is:
{
"buttonName": "BigRedButton", // or whatever value was passed from the button
"buttonColor": "red", // or whatever color was passed from the button
"event": {
"source": {
"type": "Document",
"handler": "OnPress",
"id": null, // No value reported
"uid": null, // No value reported
"value": null // No value reported
},
}
}
Named event handlers at the top-level of the document receive the extension events. The name of the event handler is "EXTENSION_NAME:EVENT_NAME", where the EXTENSION_NAME is the name
property used when loading the extension and the EVENT_NAME is defined by the extension. For example:
{
"type": "APL",
"version": "2024.2",
"extensions": [
{
"name": "Button",
"uri": "aplext:remotebutton:13"
}
],
"mainTemplate": {
"items": {
"type": "Text",
"id": "MyTextBox",
"text": "${environment.extension.Button ? 'No button has been pushed' : 'Buy a button!'}",
"color": "gray"
}
},
"Button:OnPress": [
{
"type": "SetValue",
"componentId": "MyTextBox",
"property": "text",
"value": "The ${buttonName} was pushed"
},
{
"type": "SetValue",
"componentId": "MyTextBox",
"property": "color",
"value": "${buttonColor}"
}
]
}
In the above example the "aplext:remotebutton13" handler has been assigned the name
"Button". The extension sends an event named "OnPress", so the document-level event handler is "Button:OnPress".
Extension live data
APL extensions may add custom live data objects to the global data-binding context for the document. Unlike the environment.extension
environment property, which only reports the static state of the extension on load of the document, these live data objects may change over the lifecycle of the document depending on the extension's use cases. Each APL extension may define any number of custom live data objects.
Live data objects implemented by the extension SHOULD be exposed to the document through the extension settings properties for indicating the document's intended name
for the data object in the global data-binding context.
If a document does not provide a valid settings property for any of the extension's available live data objects, then those objects should NOT be added to the data-binding context.
Refer to the extension's documentation to find information on the associated settings properties, format, and intended usage of any live data provided by the extension.
As an example, assume an APL-enabled fishtank with the FishFeeder
extension (URI="aplext:fishfeeder:10"). The FishFeeder extension has a live data object available to expose to the document's data-binding context with the following format:
{
"rayFinnedFish":[],
"lobeFinnedFish":[],
"lampreys":[]
}
The extension should also provide a settings property by which the document can define the name of the available live data object to use in data-binding. Here's an example of how the extension should document that data object.
Name | Type | Default | Description |
---|---|---|---|
fishTypeDataName |
String | null | Name to use when adding fishType live data object to the data-binding context. |
The extension's live data object can then be accessed in the APL document by providing a value for the extension's fishTypeDataName
settings property as defined above:
{
"type": "APL",
"version": "2024.2",
"extensions": [
{
"name": "Fish",
"uri": "aplext:fishfeeder:10"
}
],
"settings": {
"Fish": {
"fishTypeDataName": "fishType"
}
},
"mainTemplate": {
"items": [
{
"when": "${environment.extension.Fish}",
"type": "Container",
"items": [
{
"type": "Text",
"text": "There are ${fishType.rayFinnedFish.length} Ray Finned Fish in the tank right now."
}
]
},
{
"description": "Fallback in case no FishFeeder extension",
"type": "Text",
"text": "No FishFeeder available"
}
]
}
}
In the above example the data-binding name
"fishType" has been defined for the live data object exposed by the "aplext:fishfeeder:10" extension. The extension adds the live data object fishType
to the global data-binding context as "fishType".
Extension image filters
An APL extension can define custom image filters to modify images. Invoke an extension image filter the same way as a regular filter by including the filter in the filters
property of the Image
component. Set the type
of the filter to "EXTENSION_NAME:FILTER_NAME". The name
property defined when requesting an extension is used as a namespace
when invoking a filter provided by the extension.
For example, consider an extension that provides the "Canny" filter for running the Canny edge detection algorithm on an image. The algorithm takes two inputs: a lower threshold and an upper threshold, both normalized values from 0.0 to 1.0. The following table shows the properties used by this filter.
Property | Type | Default | Description |
---|---|---|---|
type |
Canny | REQUIRED | Defines the type of filter |
lower |
Number | 0.1 | Lower bound for edge detection |
upper |
Number | 0.9 | Upper bound for edge detection |
source |
Integer | -1 | Index of the source image |
The following example shows how an APL document could use this filter to show the edges with a yellow tint.
{
"type": "APL",
"version": "2024.2",
"extensions": [
{
"name": "Edges",
"uri": "aplext:edgedetectorfilters:11"
}
],
"mainTemplate": {
"items": {
"type": "Image",
"width": "100%",
"height": "100%",
"scale": "best-fit",
"source": "https://example.com/images/imageToProcess.png",
"filters": [
{
"type": "Color",
"color": "yellow"
},
{
"type": "Edges:Canny",
"lower": 0.2,
"upper": 0.7,
"source": -2
},
{
"type": "Blend",
"mode": "multiply"
}
]
}
}
}
Last updated: Nov 28, 2023