Alexa APLのカスタムパッケージを作成する

はじめに

AlexaのAPLドキュメントで、独自のレイアウトを作成し、パッケージ化することで複数のAPLドキュメントで再利用する方法について解説します。

APLドキュメントの基本構成やレイアウトについては、下記の記事を参照してください。

AlexaスキルのAPLドキュメントを作成する (以下「前記事」として参照)

APLドキュメント

ここでは前記事で作成した、下記の表示を行うAPLドキュメントを対象にパッケージ化を行い、カスタムパッケージとして再利用できるようにします。

まず元となるAPLドキュメントを再掲します。TextMessageというレイアウトが定義されており、そのレイアウトがmainTemplateで2回使用されています。これは前記事のバージョン8で作成されたものです。(ただしテーマはダークに戻されています)

APLドキュメント
{
    "type": "APL",
    "version": "1.6",
    "license": "",
    "theme": "dark",
    "import": [
        {
            "name": "alexa-styles",
            "version": "1.2.0"
        }
    ],
    "resources": [],
    "styles": {
        "titleStyle": {
            "values": [
                {
                    "fontSize": "@fontSize2XSmall",
                    "color": "red"
                }
            ]
        },
        "messageStyle": {
            "values": [
                {
                    "fontSize": "@fontSize2XLarge",
                    "color": "${viewport.theme == 'dark' ? 'yellow' : 'blue'}"
                }
            ]
        }
    },
    "layouts": {
        "TextMessage": {
            "parameters": [
                {
                    "name": "title",
                    "type": "string"
                },
                {
                    "name": "message",
                    "type": "string"
                }
            ],
            "items": [
                {
                    "type": "Container",
                    "items": [
                        {
                            "type": "Text",
                            "text": "${title}",
                            "style": "titleStyle"
                        },
                        {
                            "type": "Text",
                            "text": "${message}",
                            "style": "messageStyle"
                        }
                    ]
                }
            ]
        }
    },
    "mainTemplate": {
        "parameters": [
            "payload"
        ],
        "items": [
            {
                "type": "Container",
                "items": [
                    {
                        "type": "TextMessage",
                        "title": "${payload.data.title1}",
                        "message": "${payload.data.message1}"
                    },
                    {
                        "type": "TextMessage",
                        "title": "${payload.data.title2}",
                        "message": "${payload.data.message2}"
                    }
                ]
            }
        ]
    }
}

対応するデータソースを下記に示します。

データソース
{
    "data": {
        "title1": "タイトル1",
        "message1": "メッセージ1",
        "title2": "タイトル2",
        "message2": "メッセージ2"
    }
}

パッケージ化

前記事では、タイトルとメッセージを表示するコンポーネントを、MessageTextレイアウトとして部品化しました。今回はこれを更にパッケージとして別ファイルに分離して、他のAPLドキュメントで再利用できるようにします。

パッケージの構成はAPLドキュメントのうち、mainTemplateを除いたものとなります。つまり前掲のAPLドキュメントから、下記のようにmainTemplateを切り離せば良いことになります。(実はmainTemplateを残したままでもパッケージとして扱えます)

パッケージ
{
    "type": "APL",
    "version": "1.6",
    "license": "",
    "theme": "light",
    "import": [
        {
            "name": "alexa-styles",
            "version": "1.2.0"
        }
    ],
    "resources": [],
    "styles": {
        "titleStyle": {
            "values": [
                {
                    "fontSize": "@fontSize2XSmall",
                    "color": "red"
                }
            ]
        },
        "messageStyle": {
            "values": [
                {
                    "fontSize": "@fontSize2XLarge",
                    "color": "${viewport.theme == 'dark' ? 'yellow' : 'blue'}"
                }
            ]
        }
    },
    "layouts": {
        "TextMessage": {
            "parameters": [
                {
                    "name": "title",
                    "type": "string"
                },
                {
                    "name": "message",
                    "type": "string"
                }
            ],
            "items": [
                {
                    "type": "Container",
                    "items": [
                        {
                            "type": "Text",
                            "text": "${title}",
                            "style": "titleStyle"
                        },
                        {
                            "type": "Text",
                            "text": "${message}",
                            "style": "messageStyle"
                        }
                    ]
                }
            ]
        }
    }
}

ネット上の解説記事を見ると、versionにこのパッケージのバージョンを記載する、としているものもありました。しかしAlexaの技術ドキュメントの説明を読む限りでは、これは対応するAPLのバージョンであるようです。

カスタムパッケージのホスティング

カスタムパッケージは、ネット上からAlexaデバイスにダウンロードされる必要があります。このためカスタムパッケージのファイルをどこかのサーバーでホスティングする必要があります。ここでは下記の3つの方法について説明します。

  • 自前のWebサーバー
  • S3ストレージ
  • GitHub

参考: 視覚要素を簡単に作成する
「2.独自のAPLパッケージをホストする」にパッケージ化とホスティングについての説明があります。

自前のWebサーバーにホスティング

カスタムパッケージのファイル (本例ではsample-template.json) を自前のWebサーバーに配置します。ただしCORS (Cross Origin Resource Sharing) をサポートしている必要があります。

筆者の場合は、カスタムパッケージを配置したWebサーバーのディレクトリに.htaccessファイルを置いて、下記を記述しています。

Header set Access-Control-Allow-Origin "*"

CORSをサポートできるかどうかはWebサーバーの設定によります。ホスティングサービスを利用している場合は、そのサービスの仕様にも依存します。

対象のOriginとして、”*”で全てのホストを許可していますが、実際には*.amazon.comを許可していれば良いようです。(特定のドメインに対してのみ、上記のヘッダを返す方法は、ネット上に紹介がありますが、筆者は力不足でうまく設定できませんでした)

Amazon S3ストレージにホスティング

AWSのAmazon S3ストレージにファイルを格納し、HTTPでアクセスすることができます。これを利用してカスタムパッケージをホスティングできます。ただしこの場合もCORSのサポートが必要になります。設定方法については下記に記述されています。

リソースのCross-Origin Resource Sharing(CORS)を設定する

参考:

Alexa-Hostedスキルから使えるS3ストレージは、CORSの許可が設定できないため、残念ながらこの用途には使えません。AWS上で別途プロビジョニングする必要があります。

GitHubでのホスティング

参考記事 (視覚要素を簡単に作成する) では、GitHubにカスタムパッケージのファイルを入れるとCORS対応でアクセスできると書かれています。調べて見るとGitHubのパブリックレポジトリにファイルを入れて、rawモードで開くと、CORSのヘッダがついて来ます。開発中に一時的に使うには良いかも知れません。

APLドキュメントへの組み込み

カスタマパッケージをAPLドキュメントで利用するには、APLドキュメントのimportセクションでカスタムパッケージをインポートします。

    "import": [
        {
            "name": "sample-template",
            "version": "1.0.0",
            "source": "https://<domain>/<path-to-template>/sample-template.json"
        }
    ]

name
[a-zA-Z][a-zA-Z0-9-]*の形式に従っていれば良い

version
セマンティックバージョン規則に従っていれば良い
カスタムパッケージ側にバージョンを持たないのでチェックはされない

source
カスタムパッケージのURL

Alexaデバイスでは、nameとversionの組み合わせで、パッケージをキャッシュをします。このため開発中にカスタムパッケージを更新したときは、versionを更新することでキャッシュを強制的にクリアできます。

APLドキュメントの全体定義を下記に示します。

APLドキュメント
{
    "type": "APL",
    "version": "1.6",
    "license": "",
    "theme": "dark",
    "import": [
        {
            "name": "sample-template",
            "version": "1.0.0",
            "source": "https://pvision.jp/alexa/apl/sample-template.json"
        }
    ],
    "resources": [],
    "styles": {},
    "layouts": {},
    "mainTemplate": {
        "parameters": [
            "payload"
        ],
        "items": [
            {
                "type": "Container",
                "items": [
                    {
                        "type": "TextMessage",
                        "title": "${payload.data.title1}",
                        "message": "${payload.data.message1}"
                    },
                    {
                        "type": "TextMessage",
                        "title": "${payload.data.title2}",
                        "message": "${payload.data.message2}"
                    }
                ]
            }
        ]
    }
}

オリジナルのAPLドキュメントと比べると、随分スッキリしたことが判ります。再利用性の他に、ドキュメントを整理する効果もありそうです。(セットアップが大変ですが …)

おわりに

APLのカスタムパッケージの作成方法について解説しました。この例のレイアウト自体は、再利用するまでもありません (あくまで説明用ということで …)。 しかしスキルの中で同じようなパターンが出てくることはよくあります。このパッケージ化の方法が使えるシーンは多そうです。

またデザインが得意な方は、カッコいいテンプレートを作って公開する、なんてことができると楽しそうです。

変更履歴

日付内容
2021/07/09初版公開