APLデータバインディングの評価

APLデータバインディングの評価

Alexa Presentation Language(APL)ドキュメントは、ユーザー提供のデータを取り込み、スタイルやその他の視覚的リソースを組み込み、パラメーターをレイアウトに渡し、データに基づいてレイアウトを条件付きでインフレートさせるためにデータバインディングを使用しています。ドキュメントでデータバインディングを使用するには、データバインディング式を記述します。これは、埋め込まれた${..}サブストリングを持つJSON文字列です。このドキュメントでは、AlexaがAPLの最新バージョンでこれらの式を評価する方法について説明します。

データバインディング構文については個別に取り上げます。

データバインディングアルゴリズム

APLドキュメントのサンプルでTextコンポーネントの定義を考えてみましょう。

{
  "type": "Text",
  "text": "さやには豆が${data.value}粒あります",
  "color": "@myBlue",
  "fontSize": "${@textSizePrimary * 1.2}"
}

この定義には評価する3つの式が含まれています。まず、textには長めの式に挿入されるdata.valueという数値が含まれています。次に、colorが「myBlue」に設定されています。この場合、ユーザー定義のリソースを指します。最後に、fontSizeがドキュメントのメインテキストの標準よりも1.2倍大きいサイズに設定されています。

これらのすべての式を、次に示す3段階アルゴリズム (式の評価、リソースの参照、型の強制)を使用して評価します。

ステップ1: 式の評価

右側(RHS)が文字列の場合、アルゴリズムは文字列にデータバインディング式がないかスキャンします('${}'が埋め込まれています)。1つ以上の埋め込み式が見つかると、文字列全体が抽象構文木(AST)に変換されます。たとえば、上記のtextの例では、次のような木構造に変換されます。

Concatenate
  String("さやには豆が")
  AttributeLookup
    Symbol("data")
    String("value")
  String("粒あります")

ASTは次に、現在のデータバインディングコンテキストを使用して評価されます。データバインディングコンテキストは、キーと値のペアからなるJSONディクショナリーで、値は数値、ブール値、オブジェクト、配列、文字列のいずれかです。「+」などの演算子が必要に応じて暗黙的な型変換をします。たとえば、データバインディングコンテキストがここで示すとおりである場合、「data」シンボルはオブジェクト 「{value:5}」を返し、「value」の属性アクセサーが数値の5を返します。この3つの値からなる連結演算子には2つの文字列と1つの数値があるため、数値を文字列としてキャストして「さやには豆が5粒あります」を文字列値として返します。

{
  "data": {
    "value": 5
  }
}

ステップ2: リソースの参照

データバインディングの後、文字列値はシステムで定義されたリソースへの参照である場合があります。リソースの参照は「@」で始まり、ハイフンの付いていない1つの単語で構成されます。リソースは型付けされています。元の例を見ると、テキストの色は@myBlueに設定されています。エバリュエーターは色のリソースから@myBlueという名前のリソースを探します。ユーザーがこの形式のリソースブロックを指定したとします。

{
  "resources": [
    {
      "colors": {
        "myBlue": "#0033ff"
      }
    }
  ]
}

次にリソース参照ステージでは「@myBlue」が「#0033ff」に置き換えられます。

ステップ3: 型の強制

最終ステップでは、設定値が正しい型になるようにします。colorの例では、「#0033ff」の文字列値が返されています。ターゲット値は色であることがわかっているので、この文字列値を、色を表す正しい内部型に変換する必要があります。

初期状態のデータバインディングコンテキスト

新しいAPLドキュメントがインフレートされると、データバインディングコンテキストは削除されます。削除されたデータバインディングコンテキストには、次の定義済みオブジェクトがあります。

プロパティ 説明 動的

displayState

画面上でのドキュメントの表示状態です。

elapsedTime

このドキュメントの実行時間(ミリ秒単位)です。

environment

現在のランタイム環境に関する情報です。

localTime

ローカル時間(ミリ秒)です。

Math

ビルトインの数学関数です。関数の呼び出しを参照してください。

String

ビルトインの文字列関数です。関数の呼び出しを参照してください。

Time

ビルトインの時間関数(時間関数を参照)です。

utcTime

UTC時間(ミリ秒)です。

viewport

現在のデバイスの設定情報です。データバインディングコンテキストのViewportオブジェクトを参照してください。

displayState

画面上のドキュメントの現在の状態を示す値を返します。displayStateには、以下の表の値のいずれかが含まれます。

名前 説明

hidden

ドキュメントは画面に表示されません。ドキュメントはティックイベントを生成せず、不規則な間隔でイベントを生成します。正しい動作をするドキュメントは、この状態に入るとすべてのアニメーションを停止します。

background

ドキュメントが画面上に表示されているか、大半がほかのコンテンツで隠されています。ドキュメントにシステムのメインのフォーカスがない状態です。ドキュメントはティックイベントを生成しますが、ドキュメントアニメーションは最小に制限されます。

foreground

ドキュメントは画面上および前面に表示されています。

displayStateプロパティは読み取り専用です。

elapsedTime

elapsedTimeプロパティは、このドキュメントが作成されてからミリ秒単位で単調に増加する時間です。ドキュメントがレンダリングされたときにゼロから始まり、文書が画面上に表示されている間、カウントアップします。elapsedTimeプロパティは、ドキュメントが「フリーズ」しているか、ユーザーから見えないように非表示になっている場合には進みません。

environment

environmentオブジェクトには、動作しているAPL環境についてのランタイム情報が含まれます。environment値が、APLドキュメントが有効な間に変更されることはありません。

以下の表は、environmentオブジェクトのプロパティを示しています。設定可否列は、APLドキュメントのenvironmentプロパティを使ってAPLドキュメントで設定可能なenvironmentプロパティを示します。

プロパティ 設定可否 説明

agentName

文字列

ランタイム環境の名前です。

agentVersion

文字列

ランタイム環境のバージョンです。

allowOpenURL

ブール値

OpenURLコマンドが有効な場合はtrueです。

animation

noneslownormalのいずれか

ランタイムのアニメーション特性です。

aplVersion

文字列

サポートされているAPLのバージョンです。APLの現在のバージョンは1.9です。

disallowEditText

ブール値

EditTextコンポーネントが無効な場合はTrueです。

disallowDialog

ブール値

SpeakItemコマンドとSpeakListコマンドが無効な場合はTrueです。

disallowVideo

ブール値

Videoコンポーネントが無効な場合はtrueです。

extension

マップ

リクエストされたサポート対象のExtensionです。

fontScale

数値

オペレーティングシステムによってリクエストされた通常フォントサイズのパーセンテージです。

lang

文字列

テキスト表示に使用されるデフォルト言語(BCP-47形式)です。

layoutDirection

次のいずれかになります: LTR | RTL

ドキュメントのコンポーネントとテキストレイアウトのデフォルトの方向です。

reason

initialreinflationのいずれか

ドキュメントのこのインフレートが最初のインフレートか、後続の再インフレートかを表します。

screenMode

normalhigh-contrastのいずれか

画面モードの設定です。

screenReader

ブール値

スクリーンリーダーが有効な場合はtrueです。

timing

オブジェクト

標準システム時間に関するコンフィギュレーション情報です。

agentName

ランタイム環境の名前です。これはランタイムによって割り当てられる文字列で、デバッグに役立ちます。可能であれば、APLのバグや問題をレポートするときにこの情報を提供してください。必ずしも特定の形式や構造を持つとは限りません。

これらの値に基づく条件付き応答を提供する際、この値を使用しないでください。これらの値は、エージェントが更新されると変更される可能性があります。

agentVersion

ランタイム環境のバージョンです。これはランタイムによって割り当てられる文字列で、デバッグに役立ちます。可能であれば、APLのバグや問題をレポートするときにこの情報を提供してください。必ずしも特定の形式や構造を持つとは限りません。

これらの値に基づく条件付き応答を提供する際、この値を使用しないでください。これらの値は、エージェントが更新されると変更される可能性があります。

allowOpenURL

ブール値です。OpenURLコマンドが有効な場合はtrue、有効でない場合はfalseです。

animation

デバイスでのアニメーションサポートのレベルを示します。animationの有効な値は次のとおりです。

名前 説明
none このデバイスでは、アニメーションはサポートされていません。すべてのアニメーションコマンドは、高速モードで実行されます。
slow アニメーションはこのデバイスでサポートされていますが、視覚的なパフォーマンスは制限されます。
normal このデバイスでは、標準のアニメーションが許容速度で実行されます。

常にこの値を確認して、slowに設定されている場合は、アニメーションを簡略化するか削除します。

aplVersion

このデバイスでサポートされているAPLのバージョンです。この機能はAPLバージョン1.1で追加されました。APLバージョン1.9の場合、「1.9」を返します。

このプロパティはAPL 1.0には存在しないため、nullを返します。

たとえば、APLの現在のバージョンに基づいて属性文字列を作成するには、次のように記述します。

{
  "resources": [
    {
      "strings": {
        "versionString": "これはAPLバージョン1.0以前です"
      },
      "colors": {
        "versionColor": "red"
      }
    },
    {
      "when": "${environment.aplVersion}",
      "strings": {
        "versionString": "これは想定外のAPLバージョンです:${environment.aplVersion}"
      },
      "colors": {
        "versionColor": "yellow"
      }
    },
    {
      "when": "${environment.aplVersion == '1.9'}",
      "strings": {
        "versionString": "これは想定されるAPLバージョン1.9です"
      },
      "colors": {
        "versionColor": "green"
      }
    }
  ]
}

1.1以降で導入された機能を使用する場合、ドキュメントの該当するセクションを、aplVersionを確認するwhen句でラップする必要があります。

disallowEditText

このランタイムでEditTextコンポーネントが無効になっている場合はtrueです。EditTextコンポーネントは画面上のスペースを占有しますが、コンポーネントのコンテンツは表示されません。コンポーネントはユーザーの対話に応答しません。

disallowDialog

このランタイムでSpeakItemコマンドとSpeakListコマンドが無効な場合はTrueです。無効なコマンドは無視されます。

disallowVideo

このランタイムでVideoコンポーネントが無効になっている場合はtrueです。Videoコンポーネントは引き続き画面上のスペースを占有しますが、ビデオは再生されず、コンポーネントはコマンドに応答しません。

extension

extensionプロパティは、リクエストとロードされたextensionの状態を報告します。これは、extensionで定義された値への文字列名のマップが含まれています。文字列名は、APLドキュメントによってリクエストされたextensionの名前です(extensionsを参照)。例えば、ドキュメントが「Button」という名前のextension「aplext:remotebutton:v13」をリクエストした場合、データバインディング式を使用して、そのextensionの有無を確認できます。

"when": "${environment.extension.Button}"

マップはtrueと見なされることに注意してください。たとえば、extensionは、「Button」エクステンションの環境内の情報のマップを提供する場合があります。

{
  "author": "Fred Flintstone",
  "version": "1.3"
}

ドキュメントには次のように書くことができます:

{
  "type": "Text",
  "when": "${environment.extension.Button}",
  "text": "extensionのバージョン ${environment.extension.Button.version}をロードしました"
}

このテキストコンポーネントは、「Button」エクステンションが存在する場合にのみ表示され、ロードされたextensionのバージョンが表示されます。

fontScale

オペレーティングシステムのアクセシビリティ設定で指定した、表示するフォントの相対サイズを返します。ほとんどのオペレーティングシステムには、ユーザーが制御可能なアクセシビリティ設定があります。この設定で、視覚に障がいのあるユーザー向けにフォントサイズを標準より大きく変更できます。この数値は、ユーザーがリクエストしたフォントサイズの倍率です。デフォルト設定は1.0です。オペレーティングシステムの多くは、このほかに1.5と2.0のアクセシビリティ倍率をサポートしています。

lang

lang環境プロパティはデフォルトのランタイム言語をレポートします。これには、BCP-47文字列("en-US"や"ja-JP"など)が含まれます。

langプロパティを使って、言語に適したリソースを選択できます。

次の例は、指定した言語によって変わるアトリビューション文字列リソースを作成する方法を示しています。

resources定義

{
    "resources": [
        {
            "strings": {
                "helloText": "こんにちは"
            }
        },
        {
            "when": "${environment.lang == 'ja-JP'}",
            "strings": {
                "helloText": "こんにちは"
            }
        }
    ]
}

リソースの使用

{
    "type": "Text",
    "text": "@helloText"
}

ランタイムソフトウェアはデフォルトのlang値を指定します。この値は空の文字列の可能性があるため、特定の言語設定とは一致しません。APLドキュメントのenvironmentプロパティを使用してデフォルトのlang値をオーバーライドできます。

ドキュメントレベルのlangプロパティ設定のベストプラクティスは、ドキュメントのenvironmentプロパティを使ってlangをデータソースの値にバインドすることです。スキルコードで、スキルリクエストのロケールに基づいてデータソースのlang値を設定します。

layoutDirection

layoutDirection環境プロパティは、テキストとコンポーネントのデフォルトのレイアウト方向をレポートします。layoutDirectionの有効な値は次のとおりです。

名前 説明

LTR

左から右です。

RTL

右から左です。

layoutDirectionがコンポーネントにどう影響を及ぼすかについて詳しくは、layoutDirectionを参照してください。

layoutDirectionプロパティを使って方向に適したリソースを作成できます。

以下の例は、前方矢印を表示するリソースを作成する方法を示しています。左から右のドキュメントの場合、リソースは右を指す矢印のUnicode文字を表示します。右から左のドキュメントの場合、リソースは左を指す矢印のUnicode文字を表示します。

resources定義

{
    "resources": [
        {
            "strings": {
                "forwardArrow": "→"
            }
        },
        {
            "when": "${environment.layoutDirection == 'RTL'}",
            "strings": {
                "forwardArrow": "←"
            }
        }
    ]
}

リソースの使用

{
    "type": "Text",
    "text": "@forwardArrow"
}

ランタイムソフトウェアはデフォルトのlayoutDirection値を指定します。APLドキュメントのenvironmentプロパティを使用してデフォルトのlang値をオーバーライドできます。

ドキュメントレベルのlayoutDirectionプロパティ設定のベストプラクティスは、ドキュメントのenvironmentプロパティを使ってlayoutDirectionをデータソースの値にバインドすることです。スキルロジックで、スキルリクエストのロケールに基づいてデータソースのlayoutDirection値を設定します。

reason

reason環境プロパティは、ドキュメントが最初にインフレートしたときにinitialを返し、Reinflateを使って再インフレートした場合にreinflationを返します。ドキュメントのサイズ変更と再インフレートについて詳しくは、サイズ変更が可能なタブレットなどのデバイスをサポートするを参照してください。

screenMode

色の表示方法に関するアクセシビリティ設定を返します。指定可能な値は、normalhigh-contrastの2つです。high-contrastがリクエストされた場合、テキストと画像の表示に使う色として、視覚に障がいのあるユーザーが異なる要素を区別できるような色を選択する必要があります。

screenReader

trueの場合、ユーザーがデバイスのスクリーンリーダーを有効にしたことを表します。

timing

標準システム時間情報を返します。これらの値は、デバイスの性質やアクセシビリティ設定によって変わります。ドキュメントで絶対数値ではなく、timing値を設定した場合は、これらの値を使用します。

すべてのtiming値はミリ秒で指定しますが、すべてのvelocity値は秒あたりのdpで指定します。この例に示した値は参照目的でのみ使用します。実行時には異なる可能性があります。

名前 説明

doublePressTimeout

300

最初のタップを放してから2回目のタップを開始するまでの最大時間です。この時間以内であればダブルタップとみなされます。

longPressTimeout

500

最小押下時間です。これ以上押下し続けると長押しイベントになります。

minimumFlingVelocity

50

フリックを開始するまでに必要な最低速度(dp/秒)です。

pressedDuration

64

プログラムで呼び出された際に、「押された」状態を表示する時間の長さです。

tapOrScrollTimeout

100

ユーザーがコンポーネントをタップしていたか、領域をスクロール・スワイプしていたかを判断する場合、ユーザーがタッチポイントを移動しているかを確認するために待機する時間です。

maximumTapVelocity

500

Tapジェスチャーとみなされる最大速度(dp/秒)です。

localTime

localTimeプロパティは、Unixエポック(1970年1月1日00:00:00 UTC)以降に経過したミリ秒数で、UTCからのローカルタイムゾーンオフセットとサマータイムによって調整されます。localTimeプロパティは、utcTimeプロパティから派生します。localTimeプロパティは、サマータイムやタイムゾーンの変更などによるシステム時間の変更に伴い、前後に「ジャンプ」する可能性があることに注意してください。localTimeを使用してイベント期間を測定しないでください。

utcTime

utcTimeプロパティは、Unixエポック(1970年1月1日00:00:00 UTC)から経過したミリ秒数です。utcTimeプロパティは通常は単調に増加しますが、NTPを使用するデバイスではタイムサーバーと定期的に同期するためにわずかにシフトすることがあります。utcTimeプロパティは、実際の経過時間を測定するのに適しています。

データバインディングコンテキストを展開する

APLレイアウトにはパラメーターが含まれます。この例でわかるように、レイアウトをインフレートすると、名前付きのパラメーターがデータバインディングコンテキストに追加されます。

  "myQuoteLayout": {
    "parameters": [ "quotes" ],
    "item": {
      "type": "Text",
      "text": "${quotes.shakespeareQuotes[0]}"
    }
  }
// インフレーション
{
  "type": "myQuoteLayout",
  "quotes": {
    "shakespeareQuotes": [
      "一番大事なことは、おのれに忠実なれ...",
      "この婦人は大仰なことばかり言うと私は思う。",
      "すべての人を愛し、信頼するのを一握りの人に留めれば、無難に生きれる。"
    ],
  "shakespeareSonnets": [
     "くたびれ果てて私は寝床へと急ぐ。旅に疲れた手足を伸ばせるところへと..." 
	 ]
  }

この例では、quotesはカスタムmyQuoteLayoutのパラメーターです。myQuoteLayoutが使用されると、データバインディングコンテキストは、一致する値を持つ新しいquotesプロパティを追加することによって拡張されます。quotesが指定されていない場合は、quotesのデフォルト値(通常はnull)がデータバインディングコンテキストに追加されます。この追加されたデータバインディングコンテキストは、カスタムレイアウトとその子のインフレートに対してのみ有効です。

データバインディングコンテキストの展開

コンポーネントがインフレートされると、データバインディングコンテキストが展開され、追加情報をインフレートされたコンポーネントに渡します。

コンポーネントバインドの展開

各コンポーネントには、現在のデータバインディングコンテキストを展開する任意のバインディングプロパティがあります。バインドプロパティは、(名前、値、型)の組が順序に従って配列されています。各値は現在のデータバインディングコンテキストで評価され、コンテキストに追加されます。

コンポーネントの子要素の展開

複数の子コンポーネントを持つことができるコンポーネントは、次のようなグローバル名をデータバインディングコンテキストに追加します。

名前 説明
data コンポーネントのインフレーション時に、ユーザー指定のデータ配列から割り当てられる新しいデータです。
index 現在の子コンポーネントのゼロから始まるインデックスです。
ordinal 現在の子コンポーネントの1から始まる序数です。順序数の付け方については、SequenceコンポーネントとContainerコンポーネントのnumberingをご覧ください。
length 現在のコンポーネントの子コンポーネントの合計数です。

dataordinalは、適切なプロパティがコンポーネントに設定されているときにのみ設定されます。

複数子コンポーネントの一覧については、複数子コンポーネントのプロパティを参照してください。

データバインディングコンテキストを明示的に伝える

子のindexordinallengthプロパティを下位方向に伝えなければならない場合があります。たとえば、Sequenceの子がそれ自体Containerであれば、Containerの子のindexプロパティはSequenceではなく、子Containerに基づきます。このような状況では、Containerのindexをその子に伝える目的で、「bind」プロパティを次のように使用できます。

{
  "type": "Sequence",
  "width": "100%",
  "height": "100%",
  "numbered": true,
  "data": "${payload.templateData.properties.rows}",
  "item": {
    "type": "Container",
    "bind": [
      {
        "name": "parentIndex",
        "value": "${index}"
      }
    ],
    "items": [
      {
        "type": "Text",
        "text": "Index ${parentIndex}"
      }
    ]
  }
}

リソースの定義

パッケージで定義された新しいリソースが、現在のデータバインディングコンテキストのパターン@の後に追加されます。たとえば、上記の「myBlue」の色は、「${@myBlue}」として明示的に参照されると共に、「@myBlue」として暗黙的に参照されます。

配列を使ったデータバインディング

多くのAPL式には配列の評価が含まれます。APLは配列型の強制、暗黙的な配列化、データバインディング式の配列への補間をサポートしています。

配列型の強制

プロパティが既知の型の配列を保持するものとして定義される場合、配列の各要素には、プロパティ割り当て時にその型が強制されます。たとえば、数値の配列が想定されたレイアウトであれば、割り当て時にその配列の各要素に数値が強制されます。

暗黙的な配列化

便宜上、値の配列をとるすべてのAPLプロパティには、配列の角かっこを持たない単一のプロパティを使用することもできます。たとえば、Containerのitemsプロパティはコンポーネントの配列として定義されます。渡される項目が1つだけの場合は、次のアプローチは同じ意味を持ちます。

"item": {<<ITEM>>}
"item": [ {<<ITEM>>} ]

APLランタイムはどちらもlength 1の配列に展開します。

配列を想定するプロパティの多くには複数のエイリアスがあります。したがって、itemitemsは同じプロパティを表します。

データバインディング式の配列への補間

配列の展開では、配列から配列への補間をサポートしています。次に例を示します。

// コンテキスト
{
	"a": "value",
	"b": [ "alpha", "bravo" ]
}

"values": "${a}" 		-> values = [ "value" ] // 暗黙的な 配列化
"values": [ "${a}" ] 	-> values = [ "value" ]
"values": "${b}" 		-> values = [ "alpha", "bravo" ]
"values": [ "x", "${b}", "${a}" ] -> values = [ "x", "alpha", "bravo", "value" ]

配列化のルールは次のとおりです。

  • 値が文字列の場合、データバインディングを使用して評価し、正しい型を強制します(その上で配列化を適用します)。

  • 値が配列の場合、文字列である配列の各要素について、データバインディングを使用して評価します。結果が1つの項目になる場合、それを配列に挿入します。結果が複数の項目になる場合、すべての項目を配列に挿入します。