APL Extensions

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:

Requesting extensions

You must explicitly request the extensions you want to use in the APL document or in an imported APL package. Then, before you use an extension in the document, verify whether it is available on the user's device.

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 specific uri is defined by the extension. 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": "1.4",
  "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": "1.4",
  "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": "1.4",
  "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": "1.4", "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": "1.4",
  "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".