APLコマンド



APLコマンドの概要

コマンドは、画面上のコンテンツの視覚および音声の表現を変更するメッセージです。コマンドはAlexaから受け取ることも(通常は音声の発話に対する応答)、APLドキュメントでイベントハンドラーが生成することもあります(たとえば、ボタンが押されたことへの応答など)。コマンドはコンテンツの操作、ドキュメントのシーンの切り替え、音声と視覚表示の同期に使われます。

具体的なコマンドについては、APL標準コマンドAPLメディアコマンドを参照してください。

コマンドと画面アクション

コマンドがサポートするシーンでのアクションには、次のタイプがあります。

  • シーン内をナビゲートする
    • ScrollViewまたはSequenceをスクロールする
    • スクロールしてコンポーネントを表示する
    • Pagerで表示されるページを変更する
  • 既存シーン内でコンポーネントを変更する
  • 入力コントロールを更新して新しい状態を反映する
  • 既存コンポーネントの表示を変更する
  • 既存のシーン内でビデオクリップを再生/一時停止する
  • 音声
    • 単一コンポーネントのオーディオコンテンツを読む
    • 2つ以上のコンポーネントのオーディオコンテンツを読む

コマンドの評価

コマンドの個々のプロパティはデータバインディングをサポートします。コマンドは、そのコマンドの発行要因に関する情報を含むeventプロパティとコマンド受信者のターゲットプロパティが追加された、ソースデータのバインディングコンテキストの組み合わせで評価されます。

イベントの内容

コマンドはソースデータのバインディングコンテキストで評価を行います。Alexaから受け取ったコマンドは、最上位レベルのデータバインディングコンテキストで評価を行います。つまり、viewportと環境が定義されていて、名前付きのリソースにアクセスできるデータバインディングコンテキストです。画面タッチなどのAPLのイベントに応答して発行されたコマンドは、コマンドが定義されているローカルのデータバインディングコンテキストで評価を行います。次にTouchWrapperのサンプルを示します。

{
  "type": "TouchWrapper",
  "bind": [
    "name": "myRandomData",
    "value": 24.3
  ],
  "onPress": {
    "type": "SendEvent",
    "arguments": [ "値は${myRandomData}です" ]
  }
}

TouchWrapperを押すと、最初の引数は「値は24.3です」と設定されます。

イベントの定義

ソースデータのバインディングコンテキストは、コマンドが評価されるときにイベントデータによって拡張されます。すべてのイベントデータは、eventプロパティで利用可能です。eventプロパティにはsourceサブプロパティが含まれています。これは、イベントを発生させたコンポーネントに関してシステムから提供される情報です。

"event": {
  "source": {
    "type": COMPONENT_TYPE,
    "handler": EVENT_HANDLER,
    "id": SOURCE_COMPONENT_ID,  // If assigned
    "uid": RUNTIME_GENERATED_UNIQUE_ID,
    "value": SOURCE_COMPONENT_VALUE
  },
  "target": {
    PROP1: VALUE1,
    PROP2: VALUE2,
    ...
  }
}

Source

ペイロードのsourceセクションは、イベント発生要因に関するメタ情報です。このsourceセクションは、スキル開発者ではなくAPLランタイムによって生成されます。この情報はスキル開発者が使うこともできますが、分析目的で使用することも意図しています。sourceオブジェクトには、次の値が含まれます。

プロパティ 必須 説明
type 文字列 このメッセージを開始したコンポーネントの型です。
handler 文字列 このメッセージを開始したイベントハンドラーの名前です。たとえば、「Press」や「Checked」です。通常イベントハンドラーは頭にonを付けて「onXXXXX」と命名されます。このハンドラーは慣例的に「XXXX」としてレポートされます。
id 文字列 このメッセージを開始したコンポーネントのIDです。
uid 文字列 ランタイムで生成されたコンポーネントIDです。
value 任意 このメッセージを開始したコンポーネントの値です。

次の表では、標準的なsourceの値を示します。

コンポーネントのタイプ
TouchWrapper チェック済みの状態
Pager 現在のページインデックス
ScrollViewSequence 最上部からのスクロールビューの高さの割合

明示されるsource値については、個々のコンポーネントの定義を参照してください。

関連トピック: APL標準コマンドおよびAPLメディアコマンド

Target

targetプロパティは、イベントを受け取るコンポーネントについての状態情報を提供します。targetプロパティの値は、コンポーネントごとに定義されます。標準的なtarget値をいくつか以下に示しますが、この値はコンポーネントによって異なります。

プロパティ 説明 レポート元
color 現在の色 Text
currentTime 整数 現在の再生位置 Video
disabled ブール値 無効にされた状態 コンポーネント
height 数値 高さ(dp) コンポーネント
id 文字列 コンポーネントID コンポーネント
opacity 数値 不透明度 コンポーネント
page 整数 現在表示されているページ Pager
paused ブール値 ビデオが一時停止している場合はtrue Video
position 数値 スクロール距離の割合 Sequence、ScrollView
source 文字列 画像のソースURL Image、VectorGraphic、Video
text 文字列 表示されるテキスト Text
trackIndex 整数 現在のトラックのインデックス Video
uid 文字列 ランタイムで生成されたコンポーネントID コンポーネント
width 数値 幅(px) コンポーネント

式の評価

  • コマンドの中には、componentId値をtargetとするものがあります。ただし、コンポーネントがコマンドを発行し、そのコマンドが同じコンポーネントをターゲットにする場合、componentIdは省略できます。ExecuteCommandsディレクティブを使用する場合は、componentIdを指定する必要があります。

  • コマンドのデータバインディング式は、コマンドを定義するときではなく、コマンドを実行するときに評価されます。たとえば、ExecuteCommandsディレクティブが、グローバルデータバインディングコンテキストを参照するデータバインディング式を含んでいる場合があります。これらの式は、デバイスでコマンドが実行されたときに評価されます。コマンドがクラウドで作成されたときではありません。

  • イベントハンドラーとExecuteCommandsディレクティブの両方が、実行するコマンドの配列を取り出します。配列はrepeatCountが0であるSequentialコマンドと同様に扱われます。

コマンドのシークエンス実行

コマンドはAPLランタイム環境で実行されます。このランタイムにはコマンドシーケンサーが1つだけ組み込まれており、このシーケンサーがコマンドの実行を受け持ちます。

シーケンサーのルール

シーケンサーのルールは次のとおりです。

  • 画面をタッチすると、既存のシークエンスを直ちに中止します。実行中のコマンドはすべて中止されます。すべてのコマンドが破棄されます。
  • クラウドから受け取った ExecuteCommandsディレクティブは、現在実行中のシークエンスをすべて中止し、新しいコマンドに置き換えます。
  • コマンドの構成に誤りがあるか、存在しないコンポーネントを参照しているためにコマンドの実行に失敗した場合、コマンドをスキップします。コマンドに関連する遅延値は処理されます。
  • すべてのイベントハンドラー(onPressなど)は、1つ以上のコマンドと関連付けられている場合があります。イベントハンドラーに2つ以上のコマンドが割り当てられている場合、そのコマンドはSequentialコマンド内で暗黙的にラップされます。

たとえば次の例では、onPressイベントハンドラーにコマンド配列があります。この配列は、実行されるシーケンシャル配列として扱われます。ここでは、まずTextコンポーネントが読み上げられ、発話終了後にSendEventがディスパッチされます。

{
  "type": "TouchWrapper",
  "items": {
    "type": "Text",
    "id": "myText",
    "speech": VALUE
  },
  "onPress": [
    {
      "type": "SpeakItem",
      "componentId": "myText"
    },
    {
      "type": "SendEvent",
      "arguments": [ "ボタンが押されたので読み上げました" ]
    }
  ],
}

コマンドシークエンスの実行は、一度に1つのみサポートされます。新しいコマンドシークエンスが開始されると、古いコマンドシークエンスは途中で終了し、古いコマンドシシークエンス内の未実行のコマンドは実行されません。コマンドのソースは、コマンドの実行をトリガーするものです。ユーザーの操作を示すソースや、タイミングの推移に基づいてアクションをトリガーするソースを使用できます。ソースには次の種類があります。

  • Alexa ExecuteCommandsディレクティブ
  • 画面のタッチ
  • 画面のドラッグ(スクロール)
  • 背景ビデオで発生する特定のVideoコンポーネントイベント(onTrackUpdateなど)

ソースは、実行する一連のコマンドを起動します。これらのコマンドは、連続または並行して実行される別の一連のコマンドを構成することがあります。各コマンドは瞬時に行われることも、時間がかかることもあります。

コマンドツリー

コマンドツリーとは、実行される一連のコマンドのことです。コマンドツリーが発生するのは、コマンドがネストされている場合や、あるコマンドによって新しいイベントハンドラーが起動される場合です。次のようなプリミティブコマンドに、ネストされたコマンドが含まれます。

  • Parallel
  • Sequential
  • OpenURL

ユーザー定義のコマンドにもネストが含まれていることがあります。プリミティブコマンドはイベントハンドラーを起動することもあります。たとえば、onScrollイベントは、Scroll、ScrollToComponent、SpeakListイベントのいずれかによってトリガーされる可能性があります。

コマンドツリーは最後まで実行することも、途中で終了することもできます。コマンドツリーを終了すると、直ちにすべてのコマンドの実行が中止されます。つまり、ソースはコマンドツリーの実行をトリガーし、コマンドツリーは、最後まで実行することも、途中で終了することもできます。

コマンドツリーのサンプルは次のようになります。

ExecuteCommand
  + Scroll (distance=-10000)           // 上方向にスクロールする
    + onScroll                         // 一番上までスクロールするたびに起動される
      + SetValue (name="opacity", value=event.source.value * 10) // 不透明度を変更する
  + SpeakItem (id)                     // 項目をスクロールして表示させ、カラオケ状態にする
    + onScroll                         // スクロールされるたびに起動する
      + SetValue (name="opacity"....)
  + PlayVideo (synchronously)
    + onStart                          // 1回起動する
    + onTrackUpdate                    // 新しいトラックが表示されるたびに起動する
      + SetValue (name="progress"...)  // 進捗バーの表示を更新する
    + onStop                           // 1回起動する

上記の例では、Alexa ExecuteCommandsメッセージを使用して、画面の一番上までスクロールし、いずれかの項目を読み上げて、ビデオを再生します(画面の別のセクションで再生されるとします)。再生中にユーザーが画面にタッチすると、実行中の会話、スクロール、ビデオの再生が停止します。

ルール:

  • ユーザー起動の単一の「ライブ」ソースを取得します。既存のユーザー起動のソースが実行中である場合、該当するソースを終了して、新しいユーザー起動のソースが開始します。
  • ユーザー起動以外のソースでは、常に最後まで実行されます。唯一の例外として、APLテンプレートが閉じられると、ソースも終了します。ユーザー起動以外のソースが複数同時に実行されることがあります。

高速モード

コマンドツリーの一部として実行されるコマンドには、実行に一定の時間がかかるコマンドが含まれている場合があります。たとえば、画面上のリストをスクロールする、テキストを読み上げる、エフェクトを遅らせるなどです。実行中のコマンドシークエンスでは、イベントハンドラーをトリガーして新しいコマンドシークエンスの実行を開始する場合があります。onScrollイベントハンドラーの場合、ロングスクロールの操作中に画面のフレームレートで起動される可能性があります。onScrollイベントハンドラーが実行に時間がかかるコマンドシークエンス(テキストを読み上げるなど)をトリガーできるように設定されている場合、読み上げテキストをキューに入れて後で処理するか、読み上げテキストに別の読み上げテキストを何度も割り込ませなければならなくなります。

読み上げテキストに何度も割り込みが発生するのを防ぐために、コマンド実行に通常モードと高速モードという概念を取り入れています。フレームレートで実行可能なイベントハンドラーから生成されたコマンドシークエンスは、高速モードで実行されます。それ以外のコマンドシークエンスは、通常モードで実行されます。高速モードでコマンドを実行する場合、コマンド内のすべてのdelay設定は無視され、実行に時間がかかるコマンドは無視されます。イベントハンドラーは次のように動作します。

イベントハンドラー 動作
コンポーネントのonMountプロパティ 通常モード
ドキュメントのonMountプロパティ 通常モード
PagerのonPageChangedプロパティ 通常モード/高速モード
ScrollViewのonScrollプロパティ 高速モード
SequenceのonScrollプロパティ 高速モード
TouchWrapperのonPressプロパティ 通常モード
VideoのonEndプロパティ 通常モード/高速モード
VideoのonPause 通常モード/高速モード
VideoのonPlay 通常モード/高速モード
VideoのonTimeUpdate 高速モード
VideoのonTrackUpdate 通常モード/高速モード

ユーザーの操作(TouchWrapperを押すなど)によって発生するイベントは、常に通常モードで実行されます。スクロールや時間の更新などのイベントは、常に高速モードで実行されます。いずれのモードでも、実行できるイベントは通常のアクション(ビデオトラックの終了など)または最終的に高速モードでトリガーされたコマンド(スクロールイベントによるビデオの一時停止など)によってトリガーされます。外部コマンドは通常モードで実行されます。

各コマンドの説明には、高速モードでの動作が記載されています。次の表は、高速モードの動作をまとめたものです。

コマンド 高速モードの動作
AnimateItem` 終了状態にジャンプします。
AutoPage` 無視されます。
ControlMedia | command=play`の場合は無視されます。それ以外の場合は実行されます。  
Idle` 無視されます。
OpenURL` 無視されます。
Parallel` 実行されます。
PlayMedia` 無視されます。
Scroll` 無視されます。
ScrollToComponent` 無視されます。
ScrollToIndex` 無視されます。
SendEvent` 無視されます。
Sequential` 実行されます。
SetPage` 無視されます。
SetState` 実行されます。
SetValue` 実行されます。
SpeakItem` 無視されます。
SpeakList` 無視されます。

コマンドツリーの終了

コマンドツリーが終了したときは、一定の状態に遷移する必要があります。APLでは次のように想定しています。

  • スクロールを停止します。
  • ページめくりをキャンセルして、元のページか次のページのどちらか近い方に移動します。
  • 会話を直ちに中止します。
  • シーンの変更やレイアウトの構造的な変更の場合は、最終的な位置に「ジャンプ」します。

「通常」モードでは、コマンドが通常どおり実行されます。「高速」モードでは、設定したコマンドの期間が無効になります。コマンドのdelayプロパティは無視されます。実行に時間がかかるすべてのコマンド(スクロールなど)は、高速モードでは無視されます。各コマンドの説明には、「高速」モードでの動作が記載されています。

シーケンサーについて

処理のために新しい一連のコマンドを受け取る(ボタンを押すなどのアクションによって外部または内部から渡される)と、既存のコマンドツリーはすべて終了します。新しい一連のコマンドは、高速モードをfalseに設定して順番に処理されます。各コマンドについて、次の手順を実行します。

  1. when句を評価します。falseと評価された場合は、現在のコマンドをスキップして配列内の次のコマンドに進みます。
  2. delayプロパティを評価します。0より大きい場合は、ミリ秒単位で指定時間の間、一時停止します。
  3. コマンドの型を評価します。次の3つの可能性が考えられます。
    1. SendEventなどの標準コマンドである場合は、必要なコマンドプロパティがすべて設定されているかどうかを確認します。必要なプロパティが設定されていない場合は、コマンドを無視して続行します。必要なプロパティがすべて設定されている場合は、コマンドを実行して終了するまで待機します。
    2. ユーザー定義のコマンドである場合は、該当するセクションで定義されているルールに従って、コマンドを実行します。
    3. コマンドの型が認識されていない場合は、コマンドを無視して続行します。

標準コマンドはイベントハンドラーを起動する場合があります。通常、これらのイベントハンドラーは高速モードで実行されます。