スキルの応答にカードを追加する



スキルの応答にカードを追加する

ユーザーとAlexaデバイスとの対話には、Amazon Alexaアプリ(Fire OS、Android、iOS、デスクトップウェブブラウザで利用可能なコンパニオンアプリ)に表示するカードを追加することができます。これらは、音声での対話について説明したり、音声の対話を補強したりする視覚的なカードです。カスタムスキルでは、応答にこのカードを含めることができます。

カードを確認するには、Alexaアプリを開いてアクティビティページに移動します。スキルに画面専用のコンテンツ(DisplayテンプレートまたはAlexa Presentation Language)が含まれていない場合は、Echo Showなどの画面付きデバイスにカードを表示することもできます。

カードの概要

カードは、インタラクションを補強することができます。たとえば、音声の応答は、簡潔に、そして「耳で聞き取ることを前提に記述する」必要があります。カードでは、音声で応答するには長すぎたり、聞いただけでは分かりにくかったりする詳細情報や便利な情報を表示させることができます。たとえば、このシンプルなカードは、ユーザーのギフトカードの残高に関する詳細情報を提供します。

インタラクションの補足情報を提供するシンプルなテキストカードの例
インタラクションの補足情報を提供するシンプルなテキストカードの例

Alexa Skills Kitでは、さまざまなタイプのカードが提供されています。

  • Simpleカード:プレーンテキストを表示します。開発者は、カードのタイトルと本文のテキストを指定します。
  • Standardカード:プレーンテキストだけでなく、画像も表示できます。開発者は、タイトルと本文のテキストと、表示する画像のURLを指定します。
  • LinkAccountカード:アカウントリンクでのみ使用する特殊なカードタイプです。このカードを使うと、ユーザーはアカウントリンクプロセスを開始できます。
  • ユーザーがスキルに特定の権限を付与する必要がある場合は、AskForPermissionsConsentカードがAlexaアプリに送信されます。

カードをAlexaアプリに送信するには、サービスがAlexaに返す応答にカードを含めます。通常、スキルがユーザーのリクエストした情報を応答で返す際、カードのみを返します。ユーザーに詳しい情報をたずねる質問などの、その他の応答には通常カードを含めません。

カードを確認するには、Alexaアプリを開いてアクティビティページに移動します。

効果的なカードを設計する際の推奨事項については、スキルカードデザインのベストプラクティスを参照してください。

テキストを表示する基本的なカードを作成する

最もシンプルなカードは、プレーンテキストで構成されたものです。タイトルと本文を指定すると、以下のようにAlexaアプリに表示されます。

Simpleカードの例
Simpleカードの例

カードに含めることのできる文字数(タイトルと本文の合計)は、8,000文字以内です。

Simpleカードを作成するには、JSON応答にcardプロパティを追加します。

  • typeSimpleに設定します。
  • titleプロパティとcontentプロパティに、表示するテキストを設定します。改行を挿入するには、content内で「\r\n」または「\n」を使用します。

クリップボードにコピーされました。

このサンプルコードはAlexa Skills Kit SDK for Node.js (v2)を使用しています。

ResponseBuilderオブジェクトのspeakメソッドとwithSimpleCardメソッドを使って、読み上げとカードのテキストを定義します。getResponse()メソッドは、指定されたプロパティを含む応答を返します。

return handlerInput.responseBuilder
  .speak("これはAlexaが読み上げるテキストです。Alexaアプリを開いてカードを見てください。")
  .withSimpleCard(
    "これはカードのタイトルです。", 
    "これはカードの内容です。このカードはプレーンテキストのコンテンツです。\r\nコンテンツが読みやすいように改行を使用して調整します。")
  .getResponse();

クリップボードにコピーされました。

このサンプルコードはAlexa Skills Kit SDK for Pythonを使用しています。

ResponseFactoryオブジェクトのspeakメソッドとset_cardメソッドを使って、応答に含める読み上げとカードのテキストを定義します。

from ask_sdk_core.dispatch_components import AbstractRequestHandler
from ask_sdk_core.utils import is_intent_name
from ask_sdk_core.handler_input import HandlerInput
from ask_sdk_model import Response
from ask_sdk_model.ui import SimpleCard
 
 
class HelloWorldIntentHandler(AbstractRequestHandler):
    """ハローワールドインテント用ハンドラー"""
    def can_handle(self, handler_input):
        # type: (HandlerInput) -> bool
        return is_intent_name("HelloWorldIntent")(handler_input)
 
    def handle(self, handler_input):
        # type: (HandlerInput) -> Response
 
        speech_text = "これはAlexaが読み上げるテキストです。Alexaアプリを開いてカードを見てください。"
        card_title = "これはカードのタイトルです"
        card_text = “これはカードの内容です。このカードにはプレーンテキストのみ含まれます。\r\nコンテンツが読みやすいように改行を使用して調整します。"
 
        return handler_input.response_builder.speak(speech_text).set_card(
            SimpleCard(card_title, card_text)).response

クリップボードにコピーされました。

このサンプルコードはAlexa Skills Kit SDK for Javaを使用しています。

ResponseBuilderオブジェクトのwithSpeech()メソッドとwithSimpleCardメソッドを使って、読み上げとカードのテキストを定義します。build()メソッドは、指定されたプロパティを含む応答を返します。

@Override
public Optional<Response> handle(HandlerInput handlerInput, IntentRequest intentRequest) {

    String speechText ="これはAlexaが読み上げるテキストです。Alexaアプリを開いてカードを見てください。";
    String cardTitle = "これはカードのタイトルです";
    String cardText = “これはカードの内容です。このカードにはプレーンテキストのみ含まれます。\r\nコンテンツが読みやすいように改行を使用して調整します。";

    return handlerInput.getResponseBuilder()
        .withSpeech(speechText)
        .withSimpleCard(cardTitle, cardText)
        .build();
}

クリップボードにコピーされました。

このJSON応答は、シンプルなプレーンテキストのoutputSpeech文字列を返す方法の例です。この応答には、タイトルとシンプルなコンテンツを表示するカードも含まれています。

{
  "version": "1.0",
  "response": {
    "outputSpeech": {
      "type": "PlainText",
      "text": "これはAlexaが読み上げるテキストです。Alexaアプリを開いてカードを見てください。"
    },
    "card": {
      "type": "Simple",
      "title": "これはカードのタイトルです",
      "content": “これはカードの内容です。このカードにはプレーンテキストのみ含まれます。\r\nコンテンツが読みやすいように改行を使用して調整します。"
    }
  }
}

テキストと画像を表示するカードを作成する

カードでは、1枚のみですが画像を表示することができます。この場合、タイトルと本文のほかに、表示する画像のURLを2つ(小さい画像用と大きい画像用)指定します。

画像を使ったStandardカードの例
画像を使ったStandardカードの例

カードに含めることのできる文字数(titlecontent、2つのURLの合計)は、8,000文字以内です。画像のURLは、それぞれ2000文字以内でなければなりません。

画像付きのカードを作成するには、JSON応答にcardプロパティを追加します。

  • typeStandardに設定します。
  • titleプロパティとtextプロパティに、表示するテキストを設定します。
    • このタイプのカードでは、Simpleのようにcontentプロパティを使うのではなく、textプロパティを使用することに注意してください。
    • 改行を挿入するには、text内で「\r\n」または「\n」を使用します。
  • smallImageUrllargeImageUrlを指定したimageオブジェクトを追加します。
  • smallImageUrllargeImageUrlに、表示する画像の小さいバージョンと大きいバージョンのURLを設定します。画像の形式サイズホスティング要件の詳細については、以下を参照してください。
{
  "version": "1.0",
  "response": {
    "outputSpeech": {"type":"PlainText","text":"タクシーが向かっています!"},
    "card": {
      "type": "Standard",
      "title": "車の手配",
      "text": "予約車は中央通り123番地に向かっています。\n見積料金は2500円です"
      "image": {
        "smallImageUrl": "https://ridehailer.com/resources/card-images/race-car-small.png",
        "largeImageUrl": "https://ridehailer.com/resources/card-images/race-car-large.png"
      }
    }
  }
}

画像の形式とサイズ

以下の形式の画像が提供できます。

  • JPEG
  • PNG

画像のサイズは500 KB未満である必要があります。

画像を含める際、解像度の低い画像と高い画像の2つのURLを指定します。異なるサイズの画面にカードを表示する際、異なるサイズの画像が使い分けられます。

プロパティ 説明 推奨サイズ(ピクセル)
smallImageUrl 小さい画面に表示されます 横720 x 縦480
largeImageUrl 大きい画面に表示されます 横1200 x 縦800

画面のサイズが変わってもカードを適切に表示するには、smallImageUrllargeImageUrlの両方を指定してください。URLを1つしか指定しない場合、表示される画面のサイズにかかわらずその画像が使用されます。それによってカードが見えづらくなる場合があります。たとえば、smallImageUrlのみを指定した場合では、大きな画面に表示するときに画像が拡大されるため、画質が低下する可能性があります。

推奨サイズに近い画像を使用すれば、アプリの画像の画質が損なわれることはありません。小さい画像は拡大されることで、画質が下がることがあります。逆に、大きい画像は読み込みに時間がかかるので、必要以上に大きなサイズを指定するとアプリでのカードの表示パフォーマンスが下がる可能性があります。

たとえば、以下は、非常に小さい画像を拡大している例です。

拡大せざるを得ない小さい画像を使ったStandardカードの例
拡大せざるを得ない小さい画像を使ったStandardカードの例

カードは、必ずAlexaアプリで(できれば、さまざまな画面サイズの複数のデバイスを使用して)テストをして、適切に表示されることを確認してください。

画像をホストする

Alexaアプリは、実行時に、指定したURLから画像を読み込みます。指定する画像ファイルは、以下の要件を満たすHTTPSエンドポイントでホストされる必要があります。

  • エンドポイントでは、Amazon認定の認証局が署名したSSL証明書を提供します。これは、多くのコンテンツホスティングサービスで提供されています。たとえば、Amazon Simple Storage Service(Amazon S3)アマゾンウェブサービスが提供)などのサービスでファイルをホストできます。
  • エンドポイントで、画像のCross-Origin Resource Sharing(CORS)が許可する必要があります。これにより、Amazon Alexaアプリが画像をダウンロードして、アプリで表示する前に処理や検証ができるようになります。

CORSを有効にするには、画像のサーバーで、応答にAccess-Control-Allow-Originヘッダーを設定する必要があります。リソースをAlexaアプリのみに限定する場合は、取得元としてhttp://ask-ifr-download.s3.amazonaws.comとhttps://ask-ifr-download.s3.amazonaws.comのみを許可してください。

この設定方法は、画像のホストによって異なります。たとえば、Amazon S3バケットで画像をホストする場合は、以下のCORSコンフィギュレーションを使用してバケットを設定します。

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
    <CORSRule>
        <AllowedOrigin>http://ask-ifr-download.s3.amazonaws.com</AllowedOrigin>
        <AllowedMethod>GET</AllowedMethod>
    </CORSRule>
    <CORSRule>
        <AllowedOrigin>https://ask-ifr-download.s3.amazonaws.com</AllowedOrigin>
        <AllowedMethod>GET</AllowedMethod>
    </CORSRule>
</CORSConfiguration>

S3およびCORSの詳細については、Enabling Cross-Origin Resource Sharingを有効にするを参照してください。

Standardカードに画像を含める際によくある問題

このセクションでは、Standardカードに画像を含める際に発生する可能性がある、よくある問題について説明します。

画像のスペースが空白になっている場合: 以下の理由が考えられます。

  • 画像がない: 指定した画像のURLが実際の画像を参照していない、公開されていない画像を参照している、URLの有効期限が切れている、などの原因で発生します。

  • 画像のホストがCORS対応ではない: 画像をホストするサーバーがCORS対応ではありません。
  • 画像の形式が正しくない: 画像のURLで参照している画像が、サポート対象外の形式(PNGJPEG以外)になっています。
  • 画像が大きすぎる:指定した画像ファイルのサイズが大きすぎます。
画像が表示されないStandardカードの例
画像が表示されないStandardカードの例

画像もプレースホルダーもない状態でカードが表示される: 応答に実際の画像オブジェクトが含まれていない場合に発生します。カードは表示されますが、画像は表示されません。

例として、以下のJSONを見てみましょう。Standardカードとして指定されていますが、imageがありません。

{
  "version": "1.0",
  "response": {
    "outputSpeech": {"type":"PlainText","text":"タクシーが向かっています!"},
    "card": {
      "type": "Standard",
      "title": "車の手配",
      "text": "予約車は中央通り123番地に向かっています。\n見積料金は2500円です"
    }
  }
}

このコードでは次のようなカードが作成されます。

画像オブジェクトが指定されていないStandardカードの例
画像オブジェクトが指定されていないStandardカードの例

アカウントリンクに使用するカードを定義する

Alexaスキルの中には、エンドユーザーのIDと別のシステムのユーザーアカウントを結び付ける機能が必要なものもあります。この機能を、「アカウントリンク」と呼びます。Alexaユーザーとシステムのユーザーアカウント間でリンクを作成することを目的としているためです。

ユーザーがこのリンクを必要とするインテントを呼び出したときにリンクが確立されていない場合、スキルでは、Alexaアプリを使用してアカウントをリンクするよう指示する応答をユーザーに返す必要があります。アプリに表示されるカードは、ユーザーにアカウントをリンクさせるための特殊なタイプのカードです。アカウントリンクカードは、アクティビティフィードに加えて、Alexaアプリのメインホームフィードに表示されます。

アプリのホームフィードに表示されるアカウントリンクカード
アプリのホームフィードに表示されるアカウントリンクカード

カードにはスキルのアイコンと名前が含まれます。「アカウントをリンク」というリンクは、スキルのアカウントリンクの設定時に開発者コンソールで設定した認証画面のURIに移動します。

アカウントリンクのカードを作成するには、JSON応答にcardプロパティを追加します。タイプをLinkAccountに設定し、それ以外のプロパティは渡しません。

{
  "version": "1.0",
  "response": {
    "outputSpeech": {"type":"PlainText","text":"Alexaアプリに移動して、アカウントをリンクしてください。"},
    "card": {
      "type": "LinkAccount"
    }
  }
}

以下の例は、Alexa Skills Kit SDK for Node.jsAlexa Skills Kit SDK v2 for Javaを使ってアカウントリンクカードを返す方法を示しています。

クリップボードにコピーされました。

このサンプルコードはAlexa Skills Kit SDK for Node.js (v2)を使用しています。

const OrderCarIntentHandler = {

  // ...

  handle(handlerInput){

    // このインテントではユーザーのタクシー予約プロフィールと支払い情報を
    // 取得するためにアクセストークンが必要です。

    // アクセストークンはContextオブジェクトにあります。ハンドラーに渡される
    // HandlerInputオブジェクトでリクエストに
    // アクセスします。

    var accessToken = handlerInput.requestEnvelope.context.System.user.accessToken;

    if (accessToken == undefined){
        // リクエストにはトークンが含まれなかったため、ユーザーに
        // リンクするよう伝えてアカウントリンクカードを返します。
        var speechText = "車を手配するには、タクシー予約アカウントが必要です。" +
                    "Alexaアプリを使用してAmazonアカウントとタクシー予約アカウントを" +
                    "リンクしてください。";

        return handlerInput.responseBuilder
            .speak(speechText)
            .withLinkAccountCard()
            .getResponse();
    } else {

        // トークンを使ってユーザーのプロフィールにアクセスします。ここでもトークンが有効な
        // タクシー予約ユーザーを表すことを確認する必要があります。

        // ...

    }
  }
};


クリップボードにコピーされました。

このサンプルコードはAlexa Skills Kit SDK for Javaを使用しています。

public class OrderCarIntentHandler implements RequestHandler {

    // ...

    @Override
    public Optional<Response> handle(HandlerInput handlerInput) {

        // このインテントではユーザーのタクシー予約プロフィールと支払い情報を
        // 取得するためにアクセストークンが必要です。

        // アクセストークンはContextオブジェクトにあります。ハンドラーに渡される
        // HandlerInputオブジェクトでリクエストに
        // アクセスします。

        String accessToken = handlerInput
                .getRequestEnvelope()
                .getContext()
                .getSystem()
                .getUser()
                .getAccessToken();

        if (accessToken != null) {
            // メソッドを呼び出してトークンを検証し、ユーザーのタクシー予約プロフィールを
            // 取得し、車を手配します。
            return orderCarForUser(accessToken, handlerInput);
        } else {
            // リクエストにはトークンが含まれなかったため、ユーザーに
            // リンクするよう伝えてアカウントリンクカードを返します。

            String speechText = "車を手配するには、タクシー予約アカウントが必要です。"
                    + "Alexaアプリを使用してAmazonアカウントとタクシー予約アカウントを"
                    + "リンクしてください。";

            // 出力音声とアカウントリンクカードを含む応答を作成します。        
            return handlerInput.getResponseBuilder()
                    .withSpeech(speechText)
                    .withLinkAccountCard()
                    .build();
        }
    }
}

詳細については、カスタムスキルのアカウントリンクを参照してください。

特定の権限を申請するためにAskForPermissionsConsentカードを送信する

スキルはAskForPermissionsConsent権限カードを表示して、ユーザーに動的に同意を求めることができます。ユーザーの同意をリクエストする権限カードについては、ユーザー同意をリクエストする権限カードを参照してください。