リッチ レスポンス(Dialogflow)

Dialogflow で探索

[続行] をクリックして、Dialogflow に Responses サンプルをインポートします。次に、 サンプルをデプロイしてテストする手順は次のとおりです。

  1. エージェント名を入力し、サンプルの新しい Dialogflow エージェントを作成します。
  2. エージェントのインポートが完了したら、[Go to agent] をクリックします。
  3. メインのナビゲーション メニューから [Fulfillment] に移動します。
  4. [Inline Editor] を有効にして、[Deploy] をクリックします。エディタにはサンプルが含まれています。 できます。
  5. メイン ナビゲーション メニューから [Integrations] に移動し、[Google] をクリックします アシスタント
  6. 表示されたモーダル ウィンドウで、[変更の自動プレビュー] を有効にして [テスト] をクリックします。 Actions シミュレータを開きます
  7. シミュレータで「Talk to my test app」と入力して、サンプルをテストします。
<ph type="x-smartling-placeholder"></ph> 続行

視覚要素を表示してユーザーとアクションのインタラクションを強化する場合は、リッチ レスポンスを使用します。これらの視覚要素は、ユーザーが会話を進めるためのヒントになります。

リッチ レスポンスは、画面のみ、または音声と画面のエクスペリエンスで使用できます。次の要素を含めることができます。

会話の設計ガイドラインもあわせてご覧ください。 これらの視覚要素をアクションに組み込む方法を紹介します

プロパティ

リッチ レスポンスには以下の要件があり、必要に応じてオプションのプロパティを設定できます。

  • actions.capability.SCREEN_OUTPUT 機能を持つサーフェスでサポートされています。
  • リッチ レスポンスの最初の項目はシンプル レスポンスにする必要があります。
  • シンプルな回答は 2 つまでです。
  • ベーシック カードまたは StructuredResponse は 1 つまでです。
  • 候補ワードは 8 個までにします。
  • 候補ワードはFinalResponseでは使用できません
  • スマートディスプレイからウェブへのリンクは現在サポートされていません。

以降のセクションでは、さまざまな種類のリッチ レスポンスを作成する方法について説明します。

ベーシック カード

で確認できます。 <ph type="x-smartling-placeholder">
</ph>
図 1.基本的なカードの例(スマートフォン)

ベーシック カードには次のような情報を表示できます。

  • 画像
  • タイトル
  • サブタイトル
  • テキスト本文
  • リンクボタン
  • 境界線

ベーシック カードは主に表示目的に使用します。これは重要な情報(または概要)をユーザーに簡潔に提示できるよう設計されており、必要に応じて(ウェブリンクを使用して)ユーザーが詳細を確認できるようにすることができます。

ほとんどの場合、下で候補ワードを追加する必要があります カードをクリックして会話を続けたり、会話を変えたりできます。

カードに表示されている情報をチャットふきだしで繰り返さないでください。

プロパティ

ベーシック カードのレスポンス タイプには以下の要件があり、必要に応じてオプションのプロパティを設定できます。

  • actions.capability.SCREEN_OUTPUT 機能を持つサーフェスでサポートされています。
  • 書式付きテキスト(画像がない場合は必須) <ph type="x-smartling-placeholder">
      </ph>
    • デフォルトは書式なしテキストです。
    • リンクを含めないでください。
    • 最大行数は、画像ありの場合は 10 行、画像なしの場合は 15 行です。こちらが 500 文字(画像あり)または 750 文字(画像なし)。画面の小さいスマートフォン 画面の大きなスマートフォンよりも先にテキストを切り捨てます。テキストに 最後の単語の区切りでは、省略記号で切り捨てられます。
    • マークダウンの限定されたサブセットがサポートされています。 <ph type="x-smartling-placeholder">
        </ph>
      • ダブルスペース + \n による改行
      • **bold**
      • *italics*
  • 画像(書式設定されたテキストがない場合は必須) <ph type="x-smartling-placeholder">
      </ph>
    • すべての画像は高さが 192 dp として表示されます。
    • 画像のアスペクト比が画面と異なる場合、画像は 垂直または水平の端に灰色のバーが現れます。
    • 画像ソースは URL です。
    • モーション GIF を使用できます。

省略可

  • タイトル
    • 書式なしテキスト。
    • フォントとフォントサイズは固定です。
    • 1 行に制限され、余分な文字は切り捨てられます。
    • タイトルが指定されていない場合、カードの高さは縮小されます。
  • サブタイトル <ph type="x-smartling-placeholder">
      </ph>
    • 書式なしテキスト。
    • フォントとフォントサイズは固定です。
    • 1 行に制限され、余分な文字は切り捨てられます。
    • サブタイトルが指定されていない場合、カードの高さは縮小されます。
  • リンクボタン <ph type="x-smartling-placeholder">
      </ph>
    • リンクタイトルは必須です。
    • 指定できるリンクは 1 つだけです。
    • デベロッパーのドメイン以外のサイトへのリンクも許可されています。
    • リンクテキストは誤解を招かないようにする必要があります。これは承認プロセスでチェックされます。
    • リンクのないベーシック カードにはインタラクティブ機能はありません。[ リンクからユーザーを誘導し、カードの本文は 非アクティブのままとなります。
  • 枠線 <ph type="x-smartling-placeholder">
      </ph>
    • カードと画像コンテナの境界線を調整して、ベーシック カードの表示をカスタマイズできます。
    • JSON 文字列プロパティを設定して構成します。 imageDisplayOptions
図 2. 基本的なカードの例(スマートディスプレイ)

サンプルコード

Node.js

app.intent('Basic Card', (conv) => {
  if (!conv.screen) {
    conv.ask('Sorry, try this on a screen device or select the ' +
      'phone surface in the simulator.');
    conv.ask('Which response would you like to see next?');
    return;
  }

  conv.ask(`Here's an example of a basic card.`);
  conv.ask(new BasicCard({
    text: `This is a basic card.  Text in a basic card can include "quotes" and
    most other unicode characters including emojis.  Basic cards also support
    some markdown formatting like *emphasis* or _italics_, **strong** or
    __bold__, and ***bold itallic*** or ___strong emphasis___ as well as other
    things like line  \nbreaks`, // Note the two spaces before '\n' required for
                                 // a line break to be rendered in the card.
    subtitle: 'This is a subtitle',
    title: 'Title: this is a title',
    buttons: new Button({
      title: 'This is a button',
      url: 'https://assistant.google.com/',
    }),
    image: new Image({
      url: 'https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png',
      alt: 'Image alternate text',
    }),
    display: 'CROPPED',
  }));
  conv.ask('Which response would you like to see next?');
});

Java

@ForIntent("Basic Card")
public ActionResponse basicCard(ActionRequest request) {
  ResponseBuilder responseBuilder = getResponseBuilder(request);
  if (!request.hasCapability(Capability.SCREEN_OUTPUT.getValue())) {
    return responseBuilder
        .add("Sorry, try ths on a screen device or select the phone surface in the simulator.")
        .add("Which response would you like to see next?")
        .build();
  }

  // Prepare formatted text for card
  String text =
      "This is a basic card.  Text in a basic card can include \"quotes\" and\n"
          + "  most other unicode characters including emoji \uD83D\uDCF1. Basic cards also support\n"
          + "  some markdown formatting like *emphasis* or _italics_, **strong** or\n"
          + "  __bold__, and ***bold itallic*** or ___strong emphasis___ as well as other\n"
          + "  things like line  \\nbreaks"; // Note the two spaces before '\n' required for
  // a line break to be rendered in the card.
  responseBuilder
      .add("Here's an example of a basic card.")
      .add(
          new BasicCard()
              .setTitle("Title: this is a title")
              .setSubtitle("This is a subtitle")
              .setFormattedText(text)
              .setImage(
                  new Image()
                      .setUrl(
                          "https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png")
                      .setAccessibilityText("Image alternate text"))
              .setImageDisplayOptions("CROPPED")
              .setButtons(
                  new ArrayList<Button>(
                      Arrays.asList(
                          new Button()
                              .setTitle("This is a Button")
                              .setOpenUrlAction(
                                  new OpenUrlAction().setUrl("https://assistant.google.com"))))))
      .add("Which response would you like to see next?");

  return responseBuilder.build();
}

Node.js

if (!conv.screen) {
  conv.ask('Sorry, try this on a screen device or select the ' +
    'phone surface in the simulator.');
  conv.ask('Which response would you like to see next?');
  return;
}

conv.ask(`Here's an example of a basic card.`);
conv.ask(new BasicCard({
  text: `This is a basic card.  Text in a basic card can include "quotes" and
  most other unicode characters including emojis.  Basic cards also support
  some markdown formatting like *emphasis* or _italics_, **strong** or
  __bold__, and ***bold itallic*** or ___strong emphasis___ as well as other
  things like line  \nbreaks`, // Note the two spaces before '\n' required for
                               // a line break to be rendered in the card.
  subtitle: 'This is a subtitle',
  title: 'Title: this is a title',
  buttons: new Button({
    title: 'This is a button',
    url: 'https://assistant.google.com/',
  }),
  image: new Image({
    url: 'https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png',
    alt: 'Image alternate text',
  }),
  display: 'CROPPED',
}));
conv.ask('Which response would you like to see next?');

Java

ResponseBuilder responseBuilder = getResponseBuilder(request);
if (!request.hasCapability(Capability.SCREEN_OUTPUT.getValue())) {
  return responseBuilder
      .add("Sorry, try ths on a screen device or select the phone surface in the simulator.")
      .add("Which response would you like to see next?")
      .build();
}

// Prepare formatted text for card
String text =
    "This is a basic card.  Text in a basic card can include \"quotes\" and\n"
        + "  most other unicode characters including emoji \uD83D\uDCF1. Basic cards also support\n"
        + "  some markdown formatting like *emphasis* or _italics_, **strong** or\n"
        + "  __bold__, and ***bold itallic*** or ___strong emphasis___ as well as other\n"
        + "  things like line  \\nbreaks"; // Note the two spaces before '\n' required for
// a line break to be rendered in the card.
responseBuilder
    .add("Here's an example of a basic card.")
    .add(
        new BasicCard()
            .setTitle("Title: this is a title")
            .setSubtitle("This is a subtitle")
            .setFormattedText(text)
            .setImage(
                new Image()
                    .setUrl(
                        "https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png")
                    .setAccessibilityText("Image alternate text"))
            .setImageDisplayOptions("CROPPED")
            .setButtons(
                new ArrayList<Button>(
                    Arrays.asList(
                        new Button()
                            .setTitle("This is a Button")
                            .setOpenUrlAction(
                                new OpenUrlAction().setUrl("https://assistant.google.com"))))))
    .add("Which response would you like to see next?");

return responseBuilder.build();

JSON

下記の JSON は Webhook レスポンスを示します。

{
  "payload": {
    "google": {
      "expectUserResponse": true,
      "richResponse": {
        "items": [
          {
            "simpleResponse": {
              "textToSpeech": "Here's an example of a basic card."
            }
          },
          {
            "basicCard": {
              "title": "Title: this is a title",
              "subtitle": "This is a subtitle",
              "formattedText": "This is a basic card.  Text in a basic card can include \"quotes\" and\n    most other unicode characters including emojis.  Basic cards also support\n    some markdown formatting like *emphasis* or _italics_, **strong** or\n    __bold__, and ***bold itallic*** or ___strong emphasis___ as well as other\n    things like line  \nbreaks",
              "image": {
                "url": "https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png",
                "accessibilityText": "Image alternate text"
              },
              "buttons": [
                {
                  "title": "This is a button",
                  "openUrlAction": {
                    "url": "https://assistant.google.com/"
                  }
                }
              ],
              "imageDisplayOptions": "CROPPED"
            }
          },
          {
            "simpleResponse": {
              "textToSpeech": "Which response would you like to see next?"
            }
          }
        ]
      }
    }
  }
}

JSON

下記の JSON は Webhook レスポンスを示します。

{
  "expectUserResponse": true,
  "expectedInputs": [
    {
      "possibleIntents": [
        {
          "intent": "actions.intent.TEXT"
        }
      ],
      "inputPrompt": {
        "richInitialPrompt": {
          "items": [
            {
              "simpleResponse": {
                "textToSpeech": "Here's an example of a basic card."
              }
            },
            {
              "basicCard": {
                "title": "Title: this is a title",
                "subtitle": "This is a subtitle",
                "formattedText": "This is a basic card.  Text in a basic card can include \"quotes\" and\n    most other unicode characters including emojis.  Basic cards also support\n    some markdown formatting like *emphasis* or _italics_, **strong** or\n    __bold__, and ***bold itallic*** or ___strong emphasis___ as well as other\n    things like line  \nbreaks",
                "image": {
                  "url": "https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png",
                  "accessibilityText": "Image alternate text"
                },
                "buttons": [
                  {
                    "title": "This is a button",
                    "openUrlAction": {
                      "url": "https://assistant.google.com/"
                    }
                  }
                ],
                "imageDisplayOptions": "CROPPED"
              }
            },
            {
              "simpleResponse": {
                "textToSpeech": "Which response would you like to see next?"
              }
            }
          ]
        }
      }
    }
  ]
}
で確認できます。 <ph type="x-smartling-placeholder">
</ph>
図 3.ブラウジング カルーセルの例(スマートフォン)

ブラウジング カルーセルを使用すると、ユーザーが画面を垂直にスクロールしてコレクション内のタイルを選択できます。ブラウジング カルーセルはウェブ コンテンツ専用に設計されており、選択したタイルはウェブブラウザ(すべてのタイルが AMP に対応している場合は AMP ブラウザ)で開きます。ブラウジング カルーセルは、 ユーザーのアシスタント サーフェスに表示できます。

プロパティ

ブラウジング カルーセルのレスポンス タイプには以下の要件があり、必要に応じてオプションのプロパティを設定できます。

  • actions.capability.SCREEN_OUTPUT が両方とも設定されているサーフェスでサポートされています。 actions.capability.WEB_BROWSER 機能。このレスポンス タイプは現在、スマートディスプレイでは使用できません。
  • ブラウジング カルーセル <ph type="x-smartling-placeholder">
      </ph>
    • タイルの最大枚数は 10 枚です。
    • 少なくとも 2 枚のタイルが必要です。
    • カルーセルのタイルはすべてウェブ コンテンツ(AMP コンテンツ)にリンクしている必要があります 推奨)。
      • ユーザーを AMP ビューアに誘導するために、urlHintType 「AMP_CONTENT」に設定する必要があります。
  • ブラウジング カルーセル タイル <ph type="x-smartling-placeholder">
      </ph>
    • タイルの整合性(必須): <ph type="x-smartling-placeholder">
        </ph>
      • ブラウジング カルーセル内のすべてのタイルは、同じコンポーネントを持つ必要があります。 たとえば、1 つのタイルに画像フィールドがある場合、残りのタイルは 画像フィールドも必要です。
      • ブラウジング カルーセルのすべてのタイルが AMP 対応のコンテンツにリンクしている場合、 ユーザーが追加の機能を備えた AMP ブラウザに転送されます。 いずれかのタイルが非 AMP コンテンツにリンクされている場合は、すべてのタイルでユーザーが誘導されます できます。
    • 画像(省略可) <ph type="x-smartling-placeholder">
        </ph>
      • 画像は高さが 128 dp、幅が 232 dp として表示されます。
      • 画像のアスペクト比が画像の境界ボックスと一致しない場合は、 画像は中央に配置され、両側にバーが表示されます。スマートフォンでは 画像は角の丸い正方形の中央に配置されます。
      • 画像リンクが壊れている場合は、代わりにプレースホルダ画像が使用されます。
      • 画像には代替テキストが必要です。
    • タイトル(必須) <ph type="x-smartling-placeholder">
        </ph>
      • 書式設定オプションはベーシック カードと同じです。
      • タイトルは重複していない必要があります(音声による選択をサポートするため)。
      • テキストの最大行数は 2 行です。
      • フォントサイズは 16 sp です。
    • 説明(省略可) <ph type="x-smartling-placeholder">
        </ph>
      • 書式設定オプションはベーシック カードと同じです。
      • テキストの最大行数は 4 行です。
      • 切り捨てられた場合は省略記号(...)が付きます。
      • フォントサイズは 14 sp で、色はグレーです。
    • フッター(省略可) <ph type="x-smartling-placeholder">
        </ph>
      • フォントとフォントサイズは固定です。
      • テキストの最大行数は 1 行です。
      • 切り捨てられた場合は省略記号(...)が付きます。
      • 下端に固定されるため、本文の行数が少ないタイルではフッター テキストの上に空白ができる場合があります。
      • フォントサイズは 14 sp で、色はグレーです。
  • 操作 <ph type="x-smartling-placeholder">
      </ph>
    • ユーザーは画面を垂直にスクロールして項目を表示できます。
    • カードをタップ: 項目をタップすると、リンク先のページがブラウザで開きます。
  • 音声入力 <ph type="x-smartling-placeholder">
      </ph>
    • マイクの動作 <ph type="x-smartling-placeholder">
        </ph>
      • ブラウジング カルーセルがユーザーに送信されたとき、マイクは自動的に開きません。
      • マイクをタップするかアシスタントを呼び出す(「OK Google」と呼びかける)ことで、マイクを開くことができます。

ガイダンス

デフォルトでは、ブラウジング カルーセルが送信された後、マイクは閉じたままになります。目標 候補ワードを追加することを強くおすすめします。 。

リストで提示されている選択肢を候補ワードで繰り返さないでください。このコンテキストでの候補ワードは(選択肢から選択するためではなく)会話を別の方向に変えるために使用されます。

リストと同じように、カルーセル カードに付随するチャットふきだしは音声(TTS / SSML)のサブセットです。ここでの音声(TTS / SSML)は、カルーセルの最初のタイルの内容をまとめたものにします。カルーセルのすべての要素を読み上げることはしないでください。最初の項目とそれがその位置にある理由(たとえば、人気が高い、最近購入した、話題になっている、など)について言及することをおすすめします。

サンプルコード

app.intent('Browsing Carousel', (conv) => {
  if (!conv.screen
    || !conv.surface.capabilities.has('actions.capability.WEB_BROWSER')) {
    conv.ask('Sorry, try this on a phone or select the ' +
      'phone surface in the simulator.');
      conv.ask('Which response would you like to see next?');
    return;
  }

  conv.ask(`Here's an example of a browsing carousel.`);
  conv.ask(new BrowseCarousel({
    items: [
      new BrowseCarouselItem({
        title: 'Title of item 1',
        url: 'https://example.com',
        description: 'Description of item 1',
        image: new Image({
          url: 'https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png',
          alt: 'Image alternate text',
        }),
        footer: 'Item 1 footer',
      }),
      new BrowseCarouselItem({
        title: 'Title of item 2',
        url: 'https://example.com',
        description: 'Description of item 2',
        image: new Image({
          url: 'https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png',
          alt: 'Image alternate text',
        }),
        footer: 'Item 2 footer',
      }),
    ],
  }));
});
@ForIntent("Browsing Carousel")
public ActionResponse browseCarousel(ActionRequest request) {
  ResponseBuilder responseBuilder = getResponseBuilder(request);
  if (!request.hasCapability(Capability.SCREEN_OUTPUT.getValue())
      || !request.hasCapability(Capability.WEB_BROWSER.getValue())) {
    return responseBuilder
        .add("Sorry, try this on a phone or select the phone surface in the simulator.")
        .add("Which response would you like to see next?")
        .build();
  }

  responseBuilder
      .add("Here's an example of a browsing carousel.")
      .add(
          new CarouselBrowse()
              .setItems(
                  new ArrayList<CarouselBrowseItem>(
                      Arrays.asList(
                          new CarouselBrowseItem()
                              .setTitle("Title of item 1")
                              .setDescription("Description of item 1")
                              .setOpenUrlAction(new OpenUrlAction().setUrl("https://example.com"))
                              .setImage(
                                  new Image()
                                      .setUrl(
                                          "https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png")
                                      .setAccessibilityText("Image alternate text"))
                              .setFooter("Item 1 footer"),
                          new CarouselBrowseItem()
                              .setTitle("Title of item 2")
                              .setDescription("Description of item 2")
                              .setOpenUrlAction(new OpenUrlAction().setUrl("https://example.com"))
                              .setImage(
                                  new Image()
                                      .setUrl(
                                          "https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png")
                                      .setAccessibilityText("Image alternate text"))
                              .setFooter("Item 2 footer")))));

  return responseBuilder.build();
}
if (!conv.screen
  || !conv.surface.capabilities.has('actions.capability.WEB_BROWSER')) {
  conv.ask('Sorry, try this on a phone or select the ' +
    'phone surface in the simulator.');
    conv.ask('Which response would you like to see next?');
  return;
}

conv.ask(`Here's an example of a browsing carousel.`);
conv.ask(new BrowseCarousel({
  items: [
    new BrowseCarouselItem({
      title: 'Title of item 1',
      url: 'https://example.com',
      description: 'Description of item 1',
      image: new Image({
        url: 'https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png',
        alt: 'Image alternate text',
      }),
      footer: 'Item 1 footer',
    }),
    new BrowseCarouselItem({
      title: 'Title of item 2',
      url: 'https://example.com',
      description: 'Description of item 2',
      image: new Image({
        url: 'https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png',
        alt: 'Image alternate text',
      }),
      footer: 'Item 2 footer',
    }),
  ],
}));
ResponseBuilder responseBuilder = getResponseBuilder(request);
if (!request.hasCapability(Capability.SCREEN_OUTPUT.getValue())
    || !request.hasCapability(Capability.WEB_BROWSER.getValue())) {
  return responseBuilder
      .add("Sorry, try this on a phone or select the phone surface in the simulator.")
      .add("Which response would you like to see next?")
      .build();
}

responseBuilder
    .add("Here's an example of a browsing carousel.")
    .add(
        new CarouselBrowse()
            .setItems(
                new ArrayList<CarouselBrowseItem>(
                    Arrays.asList(
                        new CarouselBrowseItem()
                            .setTitle("Title of item 1")
                            .setDescription("Description of item 1")
                            .setOpenUrlAction(new OpenUrlAction().setUrl("https://example.com"))
                            .setImage(
                                new Image()
                                    .setUrl(
                                        "https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png")
                                    .setAccessibilityText("Image alternate text"))
                            .setFooter("Item 1 footer"),
                        new CarouselBrowseItem()
                            .setTitle("Title of item 2")
                            .setDescription("Description of item 2")
                            .setOpenUrlAction(new OpenUrlAction().setUrl("https://example.com"))
                            .setImage(
                                new Image()
                                    .setUrl(
                                        "https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png")
                                    .setAccessibilityText("Image alternate text"))
                            .setFooter("Item 2 footer")))));

return responseBuilder.build();

下記の JSON は Webhook レスポンスを示します。

{
  "payload": {
    "google": {
      "expectUserResponse": true,
      "richResponse": {
        "items": [
          {
            "simpleResponse": {
              "textToSpeech": "Here's an example of a browsing carousel."
            }
          },
          {
            "carouselBrowse": {
              "items": [
                {
                  "title": "Title of item 1",
                  "openUrlAction": {
                    "url": "https://example.com"
                  },
                  "description": "Description of item 1",
                  "footer": "Item 1 footer",
                  "image": {
                    "url": "https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png",
                    "accessibilityText": "Image alternate text"
                  }
                },
                {
                  "title": "Title of item 2",
                  "openUrlAction": {
                    "url": "https://example.com"
                  },
                  "description": "Description of item 2",
                  "footer": "Item 2 footer",
                  "image": {
                    "url": "https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png",
                    "accessibilityText": "Image alternate text"
                  }
                }
              ]
            }
          }
        ]
      }
    }
  }
}

下記の JSON は Webhook レスポンスを示します。

{
  "expectUserResponse": true,
  "expectedInputs": [
    {
      "inputPrompt": {
        "richInitialPrompt": {
          "items": [
            {
              "simpleResponse": {
                "textToSpeech": "Here's an example of a browsing carousel."
              }
            },
            {
              "carouselBrowse": {
                "items": [
                  {
                    "description": "Description of item 1",
                    "footer": "Item 1 footer",
                    "image": {
                      "accessibilityText": "Image alternate text",
                      "url": "https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png"
                    },
                    "openUrlAction": {
                      "url": "https://example.com"
                    },
                    "title": "Title of item 1"
                  },
                  {
                    "description": "Description of item 2",
                    "footer": "Item 2 footer",
                    "image": {
                      "accessibilityText": "Image alternate text",
                      "url": "https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png"
                    },
                    "openUrlAction": {
                      "url": "https://example.com"
                    },
                    "title": "Title of item 2"
                  }
                ]
              }
            }
          ]
        }
      },
      "possibleIntents": [
        {
          "intent": "actions.intent.TEXT"
        }
      ]
    }
  ]
}

選択された項目の処理

ブラウザへのハンドオフはカルーセルによって処理されるため、カルーセル項目とのユーザー インタラクションを処理するフォローアップ フルフィルメントは必要ありません。なお、マイクは ブラウズ カルーセルの項目を操作した後に再度開くことはないため、 会話を終了するか、 候補ワードを回答に含めます。

候補ワード

で確認できます。 <ph type="x-smartling-placeholder">
</ph>
図 4.候補ワードの例(スマートフォン)

候補ワードを使用して返信のヒントを得て、会話を続けたり会話を変えたりできます。 会話中に主要なアクションを促す場合は、 最初の候補ワードとして表示します

可能であれば、1 つの重要な候補をチャットふきだしの一部として組み込むことが望ましいですが、そうするのはレスポンスまたはチャットの会話が自然に感じられる場合に限ります。

プロパティ

候補ワードには以下の要件があり、必要に応じてオプションのプロパティを設定できます。

  • actions.capability.SCREEN_OUTPUT 機能を持つサーフェスでサポートされています。
  • 候補ワードをウェブにリンクするには、サーフェスに actions.capability.WEB_BROWSER 機能。この機能は現在、スマートディスプレイでは使用できません。
  • 設定可能な最大の候補ワード数は 8 個です。
  • テキストの最大文字数は 25 文字です。
  • 書式なしテキストのみをサポートします。

で確認できます。 <ph type="x-smartling-placeholder">
</ph>
図 5.候補ワードの例(スマートディスプレイ)

サンプルコード

Node.js

app.intent('Suggestion Chips', (conv) => {
  if (!conv.screen) {
    conv.ask('Chips can be demonstrated on screen devices.');
    conv.ask('Which response would you like to see next?');
    return;
  }

  conv.ask('These are suggestion chips.');
  conv.ask(new Suggestions('Suggestion 1'));
  conv.ask(new Suggestions(['Suggestion 2', 'Suggestion 3']));
  conv.ask(new LinkOutSuggestion({
    name: 'Suggestion Link',
    url: 'https://assistant.google.com/',
  }));
  conv.ask('Which type of response would you like to see next?'); ;
});

Java

@ForIntent("Suggestion Chips")
public ActionResponse suggestionChips(ActionRequest request) {
  ResponseBuilder responseBuilder = getResponseBuilder(request);
  if (!request.hasCapability(Capability.SCREEN_OUTPUT.getValue())) {
    return responseBuilder
        .add("Sorry, try ths on a screen device or select the phone surface in the simulator.")
        .add("Which response would you like to see next?")
        .build();
  }

  responseBuilder
      .add("These are suggestion chips.")
      .addSuggestions(new String[] {"Suggestion 1", "Suggestion 2", "Suggestion 3"})
      .add(
          new LinkOutSuggestion()
              .setDestinationName("Suggestion Link")
              .setUrl("https://assistant.google.com/"))
      .add("Which type of response would you like to see next?");
  return responseBuilder.build();
}

Node.js

if (!conv.screen) {
  conv.ask('Chips can be demonstrated on screen devices.');
  conv.ask('Which response would you like to see next?');
  return;
}

conv.ask('These are suggestion chips.');
conv.ask(new Suggestions('Suggestion 1'));
conv.ask(new Suggestions(['Suggestion 2', 'Suggestion 3']));
conv.ask(new LinkOutSuggestion({
  name: 'Suggestion Link',
  url: 'https://assistant.google.com/',
}));
conv.ask('Which type of response would you like to see next?');

Java

ResponseBuilder responseBuilder = getResponseBuilder(request);
if (!request.hasCapability(Capability.SCREEN_OUTPUT.getValue())) {
  return responseBuilder
      .add("Sorry, try ths on a screen device or select the phone surface in the simulator.")
      .add("Which response would you like to see next?")
      .build();
}

responseBuilder
    .add("These are suggestion chips.")
    .addSuggestions(new String[] {"Suggestion 1", "Suggestion 2", "Suggestion 3"})
    .add(
        new LinkOutSuggestion()
            .setDestinationName("Suggestion Link")
            .setUrl("https://assistant.google.com/"))
    .add("Which type of response would you like to see next?");
return responseBuilder.build();

JSON

下記の JSON は Webhook レスポンスを示します。

{
  "payload": {
    "google": {
      "expectUserResponse": true,
      "richResponse": {
        "items": [
          {
            "simpleResponse": {
              "textToSpeech": "These are suggestion chips."
            }
          },
          {
            "simpleResponse": {
              "textToSpeech": "Which type of response would you like to see next?"
            }
          }
        ],
        "suggestions": [
          {
            "title": "Suggestion 1"
          },
          {
            "title": "Suggestion 2"
          },
          {
            "title": "Suggestion 3"
          }
        ],
        "linkOutSuggestion": {
          "destinationName": "Suggestion Link",
          "url": "https://assistant.google.com/"
        }
      }
    }
  }
}

JSON

下記の JSON は Webhook レスポンスを示します。

{
  "expectUserResponse": true,
  "expectedInputs": [
    {
      "possibleIntents": [
        {
          "intent": "actions.intent.TEXT"
        }
      ],
      "inputPrompt": {
        "richInitialPrompt": {
          "items": [
            {
              "simpleResponse": {
                "textToSpeech": "These are suggestion chips."
              }
            },
            {
              "simpleResponse": {
                "textToSpeech": "Which type of response would you like to see next?"
              }
            }
          ],
          "suggestions": [
            {
              "title": "Suggestion 1"
            },
            {
              "title": "Suggestion 2"
            },
            {
              "title": "Suggestion 3"
            }
          ],
          "linkOutSuggestion": {
            "destinationName": "Suggestion Link",
            "url": "https://assistant.google.com/"
          }
        }
      }
    }
  ]
}

メディア レスポンス

で確認できます。 <ph type="x-smartling-placeholder">
</ph>
図 6.メディア レスポンスの例(スマートフォン)

メディア レスポンスを使用すると、アクションで再生時間のあるオーディオ コンテンツを再生できます 240 秒という SSML の制限を超えていますメディアの主なコンポーネントは シングルトラックカードですこのカードで、ユーザーは次のことができます。 運用:

  • 最後の 10 秒をもう一度再生する。
  • 30 秒後に進む。
  • メディア コンテンツの総時間を表示する。
  • オーディオ再生の進行状況インジケーターを表示する。
  • 再生経過時間を表示する。

メディア レスポンスは次の音声コマンドをサポートしています。

  • 「OK Google, 再生して」
  • 「OK Google, 一時停止して」
  • 「OK Google, 停止して」
  • 「OK Google, 最初からやり直して」

「OK Google, 音量を調節して」 「音量を上げて」「OK Google, 音量を 50 パーセントに設定して」kubectl の「get」コマンドや 類似したトレーニング フレーズを処理する場合は、アクションが優先されます。アシスタントに許可 特別な理由がない限り、これらのユーザー リクエストを処理できます。

プロパティ

メディア レスポンスには次の要件があり、必要に応じてオプションのプロパティを 以下を構成できます。

  • actions.capability.MEDIA_RESPONSE_AUDIO があるサーフェスでサポートされています。 備えています。
  • 再生用の音声は、正しい形式の .mp3 ファイルである必要があります。公開中 ストリーミングはサポートされていません
  • 再生用のメディア ファイルは HTTPS URL として指定する必要があります。
  • 画像(省略可) <ph type="x-smartling-placeholder">
      </ph>
    • 必要に応じて、アイコンや画像を含めることができます。
    • アイコン
      • アイコンは、枠線のないサムネイルとしてメディアの右側に表示されます 表示されます。
      • サイズは 36 x 36 dp にします。それより大きい画像は、このサイズに収まるように縮小されます。
    • 画像 <ph type="x-smartling-placeholder">
        </ph>
      • 画像コンテナの高さは 192 dp です。
      • 画像はメディア プレーヤー カードの上部に表示され、 カードの全幅が表示されます。ほとんどの画像は、 上や側面です
      • モーション GIF を使用できます。
    • 画像ソースを URL として指定する必要があります。
    • すべての画像に代替テキストが必要です。

サーフェスでの動作

メディア レスポンスは、Android スマートフォンと Google Home でサポートされています。メディア レスポンスの動作は、ユーザーがどのサーフェスでアクションとやり取りするかによって異なります。

Android スマートフォンでは、次のいずれかの条件が満たされている場合、メディア レスポンスを表示できます。

  • Google アシスタントがフォアグラウンドにあり、スマートフォンの画面がオンになっている。
  • 音声の再生中に Google アシスタントを離れ、ユーザーが再び 再生が完了してから 10 分以内に Google アシスタントが応答します。職場復帰時 Google アシスタントの場合、メディアカードと候補ワードが表示されます。
  • アシスタントを使用すると、 会話型アクション: 「音量を上げて」や「音量を上げて」 音量を 50 パーセントにして」のように表示されます。類似したトレーニング フレーズを処理するインテントがある場合、 優先されます。こうした処理はアシスタントにお任せください リクエストする特別な理由がある場合を除いて、ユーザーのリクエストには応じられません。

メディア コントロールは、スマートフォンがロックされていても使用できます。Android では、これらのコントロールは通知領域にも表示されます。

<ph type="x-smartling-placeholder">
</ph>
図 7.メディア レスポンスの例(スマートディスプレイ)

サンプルコード

次のコードサンプルは、リッチ レスポンスを更新してメディアを含める方法を示します。

Node.js

app.intent('Media Response', (conv) => {
  if (!conv.surface.capabilities
    .has('actions.capability.MEDIA_RESPONSE_AUDIO')) {
      conv.ask('Sorry, this device does not support audio playback.');
      conv.ask('Which response would you like to see next?');
      return;
  }

  conv.ask('This is a media response example.');
  conv.ask(new MediaObject({
    name: 'Jazz in Paris',
    url: 'https://storage.googleapis.com/automotive-media/Jazz_In_Paris.mp3',
    description: 'A funky Jazz tune',
    icon: new Image({
      url: 'https://storage.googleapis.com/automotive-media/album_art.jpg',
      alt: 'Album cover of an ocean view',
    }),
  }));
  conv.ask(new Suggestions(['Basic Card', 'List',
    'Carousel', 'Browsing Carousel']));
});

Java

@ForIntent("Media Response")
public ActionResponse mediaResponse(ActionRequest request) {
  ResponseBuilder responseBuilder = getResponseBuilder(request);
  if (!request.hasCapability(Capability.MEDIA_RESPONSE_AUDIO.getValue())) {
    return responseBuilder
        .add("Sorry, this device does not support audio playback.")
        .add("Which response would you like to see next?")
        .build();
  }

  responseBuilder
      .add("This is a media response example.")
      .add(
          new MediaResponse()
              .setMediaObjects(
                  new ArrayList<MediaObject>(
                      Arrays.asList(
                          new MediaObject()
                              .setName("Jazz in Paris")
                              .setDescription("A funky Jazz tune")
                              .setContentUrl(
                                  "https://storage.googleapis.com/automotive-media/Jazz_In_Paris.mp3")
                              .setIcon(
                                  new Image()
                                      .setUrl(
                                          "https://storage.googleapis.com/automotive-media/album_art.jpg")
                                      .setAccessibilityText("Album cover of an ocean view")))))
              .setMediaType("AUDIO"))
      .addSuggestions(new String[] {"Basic Card", "List", "Carousel", "Browsing Carousel"});
  return responseBuilder.build();
}

Node.js

if (!conv.surface.capabilities
  .has('actions.capability.MEDIA_RESPONSE_AUDIO')) {
    conv.ask('Sorry, this device does not support audio playback.');
    conv.ask('Which response would you like to see next?');
    return;
}

conv.ask('This is a media response example.');
conv.ask(new MediaObject({
  name: 'Jazz in Paris',
  url: 'https://storage.googleapis.com/automotive-media/Jazz_In_Paris.mp3',
  description: 'A funky Jazz tune',
  icon: new Image({
    url: 'https://storage.googleapis.com/automotive-media/album_art.jpg',
    alt: 'Album cover of an ocean view',
  }),
}));
conv.ask(new Suggestions(['Basic Card', 'List',
  'Carousel', 'Browsing Carousel']));

Java

ResponseBuilder responseBuilder = getResponseBuilder(request);
if (!request.hasCapability(Capability.MEDIA_RESPONSE_AUDIO.getValue())) {
  return responseBuilder
      .add("Sorry, this device does not support audio playback.")
      .add("Which response would you like to see next?")
      .build();
}

responseBuilder
    .add("This is a media response example.")
    .add(
        new MediaResponse()
            .setMediaObjects(
                new ArrayList<MediaObject>(
                    Arrays.asList(
                        new MediaObject()
                            .setName("Jazz in Paris")
                            .setDescription("A funky Jazz tune")
                            .setContentUrl(
                                "https://storage.googleapis.com/automotive-media/Jazz_In_Paris.mp3")
                            .setIcon(
                                new Image()
                                    .setUrl(
                                        "https://storage.googleapis.com/automotive-media/album_art.jpg")
                                    .setAccessibilityText("Album cover of an ocean view")))))
            .setMediaType("AUDIO"))
    .addSuggestions(new String[] {"Basic Card", "List", "Carousel", "Browsing Carousel"});
return responseBuilder.build();

JSON

下記の JSON は Webhook レスポンスを示します。

{
  "payload": {
    "google": {
      "expectUserResponse": true,
      "richResponse": {
        "items": [
          {
            "simpleResponse": {
              "textToSpeech": "This is a media response example."
            }
          },
          {
            "mediaResponse": {
              "mediaType": "AUDIO",
              "mediaObjects": [
                {
                  "contentUrl": "https://storage.googleapis.com/automotive-media/Jazz_In_Paris.mp3",
                  "description": "A funky Jazz tune",
                  "icon": {
                    "url": "https://storage.googleapis.com/automotive-media/album_art.jpg",
                    "accessibilityText": "Album cover of an ocean view"
                  },
                  "name": "Jazz in Paris"
                }
              ]
            }
          }
        ],
        "suggestions": [
          {
            "title": "Basic Card"
          },
          {
            "title": "List"
          },
          {
            "title": "Carousel"
          },
          {
            "title": "Browsing Carousel"
          }
        ]
      }
    }
  }
}

JSON

下記の JSON は Webhook レスポンスを示します。

{
  "expectUserResponse": true,
  "expectedInputs": [
    {
      "possibleIntents": [
        {
          "intent": "actions.intent.TEXT"
        }
      ],
      "inputPrompt": {
        "richInitialPrompt": {
          "items": [
            {
              "simpleResponse": {
                "textToSpeech": "This is a media response example."
              }
            },
            {
              "mediaResponse": {
                "mediaType": "AUDIO",
                "mediaObjects": [
                  {
                    "contentUrl": "https://storage.googleapis.com/automotive-media/Jazz_In_Paris.mp3",
                    "description": "A funky Jazz tune",
                    "icon": {
                      "url": "https://storage.googleapis.com/automotive-media/album_art.jpg",
                      "accessibilityText": "Album cover of an ocean view"
                    },
                    "name": "Jazz in Paris"
                  }
                ]
              }
            }
          ],
          "suggestions": [
            {
              "title": "Basic Card"
            },
            {
              "title": "List"
            },
            {
              "title": "Carousel"
            },
            {
              "title": "Browsing Carousel"
            }
          ]
        }
      }
    }
  ]
}

ガイダンス

レスポンスには、mediaTypeAUDIOmediaResponse を含める必要があります。 リッチ レスポンスの item 配列内に mediaObject が含まれています。メディア 単一のメディア オブジェクトをサポートします。メディア オブジェクトにはコンテンツを含める必要がある 音声ファイルの URL。メディア オブジェクトには、任意で名前、サブテキスト (説明)、アイコンまたは画像の URL です。

スマートフォンと Google Home で、アクションが音声の再生を完了すると、 Google アシスタントは、メディア レスポンスが FinalResponse かどうかを確認します。 そうでない場合は、フルフィルメントにコールバックが送信され、 できます。

アクションに候補ワードを組み込む必要があります。 レスポンスが FinalResponse ではありません。

再生完了後のコールバックの処理

アクションで、actions.intent.MEDIA_STATUS インテントを処理して、プロンプトを表示する必要があります。 ユーザーにフォローアップを要求します(別の曲を再生するなど)。アクションが受信した このコールバックは、メディアの再生が完了したときに行われます。コールバックでは、 MEDIA_STATUS 引数には、現在のメディアに関するステータス情報が含まれます。「 ステータス値は FINISHED または STATUS_UNSPECIFIED です。

Dialogflow の使用

Dialogflow で会話を分岐させる場合は、以下を行う必要があります。 actions_capability_media_response_audio の入力コンテキストを メディア レスポンスをサポートするサーフェスでのみトリガーされるようにします。

フルフィルメントの作成

以下のコード スニペットは、 アクション。Dialogflow を使用している場合は、actions.intent.MEDIA_STATUS を置き換えます。 メッセージを受け取るインテントで指定されたアクション名で置き換えられます。 actions_intent_MEDIA_STATUS イベント(「media.status.update」など)。

Node.js

app.intent('Media Status', (conv) => {
  const mediaStatus = conv.arguments.get('MEDIA_STATUS');
  let response = 'Unknown media status received.';
  if (mediaStatus && mediaStatus.status === 'FINISHED') {
    response = 'Hope you enjoyed the tune!';
  }
  conv.ask(response);
  conv.ask('Which response would you like to see next?');
});

Java

@ForIntent("Media Status")
public ActionResponse mediaStatus(ActionRequest request) {
  ResponseBuilder responseBuilder = getResponseBuilder(request);
  String mediaStatus = request.getMediaStatus();
  String response = "Unknown media status received.";
  if (mediaStatus != null && mediaStatus.equals("FINISHED")) {
    response = "Hope you enjoyed the tune!";
  }
  responseBuilder.add(response);
  responseBuilder.add("Which response would you like to see next?");
  return responseBuilder.build();
}

Node.js

app.intent('actions.intent.MEDIA_STATUS', (conv) => {
  const mediaStatus = conv.arguments.get('MEDIA_STATUS');
  let response = 'Unknown media status received.';
  if (mediaStatus && mediaStatus.status === 'FINISHED') {
    response = 'Hope you enjoyed the tune!';
  }
  conv.ask(response);
  conv.ask('Which response would you like to see next?');
});

Java

@ForIntent("actions.intent.MEDIA_STATUS")
public ActionResponse mediaStatus(ActionRequest request) {
  ResponseBuilder responseBuilder = getResponseBuilder(request);
  String mediaStatus = request.getMediaStatus();
  String response = "Unknown media status received.";
  if (mediaStatus != null && mediaStatus.equals("FINISHED")) {
    response = "Hope you enjoyed the tune!";
  }
  responseBuilder.add(response);
  responseBuilder.add("Which response would you like to see next?");
  return responseBuilder.build();
}

JSON

下記の JSON は Webhook リクエストを示します。

{
  "responseId": "151b68df-98de-41fb-94b5-caeace90a7e9-21947381",
  "queryResult": {
    "queryText": "actions_intent_MEDIA_STATUS",
    "parameters": {},
    "allRequiredParamsPresent": true,
    "fulfillmentText": "Webhook failed for intent: Media Status",
    "fulfillmentMessages": [
      {
        "text": {
          "text": [
            "Webhook failed for intent: Media Status"
          ]
        }
      }
    ],
    "outputContexts": [
      {
        "name": "projects/df-responses-kohler/agent/sessions/ABwppHHsebncupHK11oKhsCTgyH96GRNYH-xpeeMTqb-cvOxbd67QenbRlZM4bGAIB8_KXdTfI7-7lYVKN1ovAhCaA/contexts/actions_capability_media_response_audio"
      },
      {
        "name": "projects/df-responses-kohler/agent/sessions/ABwppHHsebncupHK11oKhsCTgyH96GRNYH-xpeeMTqb-cvOxbd67QenbRlZM4bGAIB8_KXdTfI7-7lYVKN1ovAhCaA/contexts/actions_capability_account_linking"
      },
      {
        "name": "projects/df-responses-kohler/agent/sessions/ABwppHHsebncupHK11oKhsCTgyH96GRNYH-xpeeMTqb-cvOxbd67QenbRlZM4bGAIB8_KXdTfI7-7lYVKN1ovAhCaA/contexts/actions_capability_web_browser"
      },
      {
        "name": "projects/df-responses-kohler/agent/sessions/ABwppHHsebncupHK11oKhsCTgyH96GRNYH-xpeeMTqb-cvOxbd67QenbRlZM4bGAIB8_KXdTfI7-7lYVKN1ovAhCaA/contexts/actions_capability_screen_output"
      },
      {
        "name": "projects/df-responses-kohler/agent/sessions/ABwppHHsebncupHK11oKhsCTgyH96GRNYH-xpeeMTqb-cvOxbd67QenbRlZM4bGAIB8_KXdTfI7-7lYVKN1ovAhCaA/contexts/actions_capability_audio_output"
      },
      {
        "name": "projects/df-responses-kohler/agent/sessions/ABwppHHsebncupHK11oKhsCTgyH96GRNYH-xpeeMTqb-cvOxbd67QenbRlZM4bGAIB8_KXdTfI7-7lYVKN1ovAhCaA/contexts/google_assistant_input_type_voice"
      },
      {
        "name": "projects/df-responses-kohler/agent/sessions/ABwppHHsebncupHK11oKhsCTgyH96GRNYH-xpeeMTqb-cvOxbd67QenbRlZM4bGAIB8_KXdTfI7-7lYVKN1ovAhCaA/contexts/actions_intent_media_status",
        "parameters": {
          "MEDIA_STATUS": {
            "@type": "type.googleapis.com/google.actions.v2.MediaStatus",
            "status": "FINISHED"
          }
        }
      }
    ],
    "intent": {
      "name": "projects/df-responses-kohler/agent/intents/068b27d3-c148-4044-bfab-dfa37eebd90d",
      "displayName": "Media Status"
    },
    "intentDetectionConfidence": 1,
    "languageCode": "en"
  },
  "originalDetectIntentRequest": {
    "source": "google",
    "version": "2",
    "payload": {
      "user": {
        "locale": "en-US",
        "lastSeen": "2019-08-04T23:57:15Z",
        "userVerificationStatus": "VERIFIED"
      },
      "conversation": {
        "conversationId": "ABwppHHsebncupHK11oKhsCTgyH96GRNYH-xpeeMTqb-cvOxbd67QenbRlZM4bGAIB8_KXdTfI7-7lYVKN1ovAhCaA",
        "type": "ACTIVE",
        "conversationToken": "[]"
      },
      "inputs": [
        {
          "intent": "actions.intent.MEDIA_STATUS",
          "rawInputs": [
            {
              "inputType": "VOICE"
            }
          ],
          "arguments": [
            {
              "name": "MEDIA_STATUS",
              "extension": {
                "@type": "type.googleapis.com/google.actions.v2.MediaStatus",
                "status": "FINISHED"
              }
            }
          ]
        }
      ],
      "surface": {
        "capabilities": [
          {
            "name": "actions.capability.MEDIA_RESPONSE_AUDIO"
          },
          {
            "name": "actions.capability.ACCOUNT_LINKING"
          },
          {
            "name": "actions.capability.WEB_BROWSER"
          },
          {
            "name": "actions.capability.SCREEN_OUTPUT"
          },
          {
            "name": "actions.capability.AUDIO_OUTPUT"
          }
        ]
      },
      "isInSandbox": true,
      "availableSurfaces": [
        {
          "capabilities": [
            {
              "name": "actions.capability.WEB_BROWSER"
            },
            {
              "name": "actions.capability.AUDIO_OUTPUT"
            },
            {
              "name": "actions.capability.SCREEN_OUTPUT"
            }
          ]
        }
      ],
      "requestType": "SIMULATOR"
    }
  },
  "session": "projects/df-responses-kohler/agent/sessions/ABwppHHsebncupHK11oKhsCTgyH96GRNYH-xpeeMTqb-cvOxbd67QenbRlZM4bGAIB8_KXdTfI7-7lYVKN1ovAhCaA"
}

JSON

下記の JSON は Webhook リクエストを示します。

{
  "user": {
    "locale": "en-US",
    "lastSeen": "2019-08-06T07:38:40Z",
    "userVerificationStatus": "VERIFIED"
  },
  "conversation": {
    "conversationId": "ABwppHGcqunXh1M6IE0lu2sVqXdpJfdpC5FWMkMSXQskK1nzb4IkSUSRqQzoEr0Ly0z_G3mwyZlk5rFtd1w",
    "type": "NEW"
  },
  "inputs": [
    {
      "intent": "actions.intent.MEDIA_STATUS",
      "rawInputs": [
        {
          "inputType": "VOICE"
        }
      ],
      "arguments": [
        {
          "name": "MEDIA_STATUS",
          "extension": {
            "@type": "type.googleapis.com/google.actions.v2.MediaStatus",
            "status": "FINISHED"
          }
        }
      ]
    }
  ],
  "surface": {
    "capabilities": [
      {
        "name": "actions.capability.SCREEN_OUTPUT"
      },
      {
        "name": "actions.capability.WEB_BROWSER"
      },
      {
        "name": "actions.capability.AUDIO_OUTPUT"
      },
      {
        "name": "actions.capability.MEDIA_RESPONSE_AUDIO"
      },
      {
        "name": "actions.capability.ACCOUNT_LINKING"
      }
    ]
  },
  "isInSandbox": true,
  "availableSurfaces": [
    {
      "capabilities": [
        {
          "name": "actions.capability.WEB_BROWSER"
        },
        {
          "name": "actions.capability.AUDIO_OUTPUT"
        },
        {
          "name": "actions.capability.SCREEN_OUTPUT"
        }
      ]
    }
  ],
  "requestType": "SIMULATOR"
}

テーブルカード

テーブルカードを使用すると、レスポンスで表形式のデータを表示できます(たとえば、 スポーツの順位、選挙結果、フライトなど)が表示されます。列を定義し、 テーブルカードにアシスタントで表示する必要のある行(それぞれ最大 3 行)が表示されます。 追加の列や行を、優先順位とともに定義することもできます。

表は垂直リストと異なり、表には静的データが表示され、 リスト要素のように操作できません。

で確認できます。 <ph type="x-smartling-placeholder">
</ph>
図 8.表カードの例(スマートディスプレイ)

プロパティ

テーブルカードには次の要件があり、オプションのプロパティも指定できます。 構成:

  • actions.capability.SCREEN_OUTPUT 機能を持つサーフェスでサポートされています。

次のセクションでは、テーブルの要素をカスタマイズする方法の概要を説明します。 。

名前 省略可 カスタマイズ可 カスタマイズに関する注意
title テーブルの全体的なタイトル。サブタイトルが設定されている場合は必ず設定する必要があります。Google Chat では フォント ファミリーと色をカスタマイズできます。
subtitle × テーブルのサブタイトル。
image テーブルに関連付けられている画像。
Row ×

テーブルの行データ。Cell の配列で構成されます divider_after プロパティを使用して、 行の後には分割線が必要です

最初の 3 行は表示されることが保証されているが、それ以外の行は表示されない可能性がある 特定のサーフェスに表示されます

各期間のどの行が表示されるかをシミュレータでテストしてください。 表します。WEB_BROWSER をサポートするサーフェスの場合 詳細なデータが記載されたウェブページにユーザーを誘導できます。リンク スマート ディスプレイでは利用できません。

ColumnProperties 列の見出しと配置。header で構成 プロパティ(列のヘッダー テキストを表す)と horizontal_alignment プロパティ(型 HorizontalAlignment)。
Cell いいえ 行のセルを記述します。各セルには、個々のセルを表す文字列が あります。セル内のテキストをカスタマイズできます。
Button 通常はカードの一番下に表示されるボタン オブジェクト。テーブル カードには 1 つのボタンしか追加できません。ボタンの色をカスタマイズできます。
HorizontalAlignment セルの内容の水平方向の配置。指定できる値は次のとおりです。 LEADINGCENTER、または TRAILING。条件 指定しない場合、内容はセルの前端に揃えられます。

サンプルコード

次のスニペットは、単純なテーブルカードを実装する方法を示します。

Node.js

app.intent('Simple Table Card', (conv) => {
  if (!conv.screen) {
    conv.ask('Sorry, try this on a screen device or select the ' +
      'phone surface in the simulator.');
    conv.ask('Which response would you like to see next?');
    return;
  }

  conv.ask('This is a simple table example.');
  conv.ask(new Table({
    dividers: true,
    columns: ['header 1', 'header 2', 'header 3'],
    rows: [
      ['row 1 item 1', 'row 1 item 2', 'row 1 item 3'],
      ['row 2 item 1', 'row 2 item 2', 'row 2 item 3'],
    ],
  }));
  conv.ask('Which response would you like to see next?');
});

Java

@ForIntent("Simple Table Card")
public ActionResponse simpleTable(ActionRequest request) {
  ResponseBuilder responseBuilder = getResponseBuilder(request);
  if (!request.hasCapability(Capability.SCREEN_OUTPUT.getValue())) {
    return responseBuilder
        .add("Sorry, try ths on a screen device or select the phone surface in the simulator.")
        .add("Which response would you like to see next?")
        .build();
  }

  responseBuilder
      .add("This is a simple table example.")
      .add(
          new TableCard()
              .setColumnProperties(
                  Arrays.asList(
                      new TableCardColumnProperties().setHeader("header 1"),
                      new TableCardColumnProperties().setHeader("header 2"),
                      new TableCardColumnProperties().setHeader("header 3")))
              .setRows(
                  Arrays.asList(
                      new TableCardRow()
                          .setCells(
                              Arrays.asList(
                                  new TableCardCell().setText("row 1 item 1"),
                                  new TableCardCell().setText("row 1 item 2"),
                                  new TableCardCell().setText("row 1 item 3"))),
                      new TableCardRow()
                          .setCells(
                              Arrays.asList(
                                  new TableCardCell().setText("row 2 item 1"),
                                  new TableCardCell().setText("row 2 item 2"),
                                  new TableCardCell().setText("row 2 item 3"))))));
  return responseBuilder.build();
}

Node.js

if (!conv.screen) {
  conv.ask('Sorry, try this on a screen device or select the ' +
    'phone surface in the simulator.');
  conv.ask('Which response would you like to see next?');
  return;
}

conv.ask('This is a simple table example.');
conv.ask(new Table({
  dividers: true,
  columns: ['header 1', 'header 2', 'header 3'],
  rows: [
    ['row 1 item 1', 'row 1 item 2', 'row 1 item 3'],
    ['row 2 item 1', 'row 2 item 2', 'row 2 item 3'],
  ],
}));
conv.ask('Which response would you like to see next?');

Java

ResponseBuilder responseBuilder = getResponseBuilder(request);
if (!request.hasCapability(Capability.SCREEN_OUTPUT.getValue())) {
  return responseBuilder
      .add("Sorry, try ths on a screen device or select the phone surface in the simulator.")
      .add("Which response would you like to see next?")
      .build();
}

responseBuilder
    .add("This is a simple table example.")
    .add(
        new TableCard()
            .setColumnProperties(
                Arrays.asList(
                    new TableCardColumnProperties().setHeader("header 1"),
                    new TableCardColumnProperties().setHeader("header 2"),
                    new TableCardColumnProperties().setHeader("header 3")))
            .setRows(
                Arrays.asList(
                    new TableCardRow()
                        .setCells(
                            Arrays.asList(
                                new TableCardCell().setText("row 1 item 1"),
                                new TableCardCell().setText("row 1 item 2"),
                                new TableCardCell().setText("row 1 item 3"))),
                    new TableCardRow()
                        .setCells(
                            Arrays.asList(
                                new TableCardCell().setText("row 2 item 1"),
                                new TableCardCell().setText("row 2 item 2"),
                                new TableCardCell().setText("row 2 item 3"))))));
return responseBuilder.build();

JSON

下記の JSON は Webhook レスポンスを示します。

{
  "payload": {
    "google": {
      "expectUserResponse": true,
      "richResponse": {
        "items": [
          {
            "simpleResponse": {
              "textToSpeech": "This is a simple table example."
            }
          },
          {
            "tableCard": {
              "rows": [
                {
                  "cells": [
                    {
                      "text": "row 1 item 1"
                    },
                    {
                      "text": "row 1 item 2"
                    },
                    {
                      "text": "row 1 item 3"
                    }
                  ],
                  "dividerAfter": true
                },
                {
                  "cells": [
                    {
                      "text": "row 2 item 1"
                    },
                    {
                      "text": "row 2 item 2"
                    },
                    {
                      "text": "row 2 item 3"
                    }
                  ],
                  "dividerAfter": true
                }
              ],
              "columnProperties": [
                {
                  "header": "header 1"
                },
                {
                  "header": "header 2"
                },
                {
                  "header": "header 3"
                }
              ]
            }
          },
          {
            "simpleResponse": {
              "textToSpeech": "Which response would you like to see next?"
            }
          }
        ]
      }
    }
  }
}

JSON

下記の JSON は Webhook レスポンスを示します。

{
  "expectUserResponse": true,
  "expectedInputs": [
    {
      "inputPrompt": {
        "richInitialPrompt": {
          "items": [
            {
              "simpleResponse": {
                "textToSpeech": "This is a simple table example."
              }
            },
            {
              "tableCard": {
                "columnProperties": [
                  {
                    "header": "header 1"
                  },
                  {
                    "header": "header 2"
                  },
                  {
                    "header": "header 3"
                  }
                ],
                "rows": [
                  {
                    "cells": [
                      {
                        "text": "row 1 item 1"
                      },
                      {
                        "text": "row 1 item 2"
                      },
                      {
                        "text": "row 1 item 3"
                      }
                    ],
                    "dividerAfter": true
                  },
                  {
                    "cells": [
                      {
                        "text": "row 2 item 1"
                      },
                      {
                        "text": "row 2 item 2"
                      },
                      {
                        "text": "row 2 item 3"
                      }
                    ],
                    "dividerAfter": true
                  }
                ]
              }
            },
            {
              "simpleResponse": {
                "textToSpeech": "Which response would you like to see next?"
              }
            }
          ]
        }
      },
      "possibleIntents": [
        {
          "intent": "actions.intent.TEXT"
        }
      ]
    }
  ]
}

次のスニペットは、複雑なテーブルカードを実装する方法を示します。

Node.js

app.intent('Advanced Table Card', (conv) => {
  if (!conv.screen) {
    conv.ask('Sorry, try this on a screen device or select the ' +
      'phone surface in the simulator.');
    conv.ask('Which response would you like to see next?');
    return;
  }

  conv.ask('This is a table with all the possible fields.');
  conv.ask(new Table({
    title: 'Table Title',
    subtitle: 'Table Subtitle',
    image: new Image({
      url: 'https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png',
      alt: 'Alt Text',
    }),
    columns: [
      {
        header: 'header 1',
        align: 'CENTER',
      },
      {
        header: 'header 2',
        align: 'LEADING',
      },
      {
        header: 'header 3',
        align: 'TRAILING',
      },
    ],
    rows: [
      {
        cells: ['row 1 item 1', 'row 1 item 2', 'row 1 item 3'],
        dividerAfter: false,
      },
      {
        cells: ['row 2 item 1', 'row 2 item 2', 'row 2 item 3'],
        dividerAfter: true,
      },
      {
        cells: ['row 3 item 1', 'row 3 item 2', 'row 3 item 3'],
      },
    ],
    buttons: new Button({
      title: 'Button Text',
      url: 'https://assistant.google.com',
    }),
  }));
  conv.ask('Which response would you like to see next?');
});

Java

@ForIntent("Advanced Table Card")
public ActionResponse advancedTable(ActionRequest request) {
  ResponseBuilder responseBuilder = getResponseBuilder(request);
  if (!request.hasCapability(Capability.SCREEN_OUTPUT.getValue())) {
    return responseBuilder
        .add("Sorry, try ths on a screen device or select the phone surface in the simulator.")
        .add("Which response would you like to see next?")
        .build();
  }

  responseBuilder
      .add("This is a table with all the possible fields.")
      .add(
          new TableCard()
              .setTitle("Table Title")
              .setSubtitle("Table Subtitle")
              .setImage(
                  new Image()
                      .setUrl(
                          "https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png")
                      .setAccessibilityText("Alt text"))
              .setButtons(
                  Arrays.asList(
                      new Button()
                          .setTitle("Button Text")
                          .setOpenUrlAction(
                              new OpenUrlAction().setUrl("https://assistant.google.com"))))
              .setColumnProperties(
                  Arrays.asList(
                      new TableCardColumnProperties()
                          .setHeader("header 1")
                          .setHorizontalAlignment("CENTER"),
                      new TableCardColumnProperties()
                          .setHeader("header 2")
                          .setHorizontalAlignment("LEADING"),
                      new TableCardColumnProperties()
                          .setHeader("header 3")
                          .setHorizontalAlignment("TRAILING")))
              .setRows(
                  Arrays.asList(
                      new TableCardRow()
                          .setCells(
                              Arrays.asList(
                                  new TableCardCell().setText("row 1 item 1"),
                                  new TableCardCell().setText("row 1 item 2"),
                                  new TableCardCell().setText("row 1 item 3")))
                          .setDividerAfter(false),
                      new TableCardRow()
                          .setCells(
                              Arrays.asList(
                                  new TableCardCell().setText("row 2 item 1"),
                                  new TableCardCell().setText("row 2 item 2"),
                                  new TableCardCell().setText("row 2 item 3")))
                          .setDividerAfter(true),
                      new TableCardRow()
                          .setCells(
                              Arrays.asList(
                                  new TableCardCell().setText("row 2 item 1"),
                                  new TableCardCell().setText("row 2 item 2"),
                                  new TableCardCell().setText("row 2 item 3"))))));
  return responseBuilder.build();
}

Node.js

if (!conv.screen) {
  conv.ask('Sorry, try this on a screen device or select the ' +
    'phone surface in the simulator.');
  conv.ask('Which response would you like to see next?');
  return;
}

conv.ask('This is a table with all the possible fields.');
conv.ask(new Table({
  title: 'Table Title',
  subtitle: 'Table Subtitle',
  image: new Image({
    url: 'https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png',
    alt: 'Alt Text',
  }),
  columns: [
    {
      header: 'header 1',
      align: 'CENTER',
    },
    {
      header: 'header 2',
      align: 'LEADING',
    },
    {
      header: 'header 3',
      align: 'TRAILING',
    },
  ],
  rows: [
    {
      cells: ['row 1 item 1', 'row 1 item 2', 'row 1 item 3'],
      dividerAfter: false,
    },
    {
      cells: ['row 2 item 1', 'row 2 item 2', 'row 2 item 3'],
      dividerAfter: true,
    },
    {
      cells: ['row 3 item 1', 'row 3 item 2', 'row 3 item 3'],
    },
  ],
  buttons: new Button({
    title: 'Button Text',
    url: 'https://assistant.google.com',
  }),
}));
conv.ask('Which response would you like to see next?');

Java

ResponseBuilder responseBuilder = getResponseBuilder(request);
if (!request.hasCapability(Capability.SCREEN_OUTPUT.getValue())) {
  return responseBuilder
      .add("Sorry, try ths on a screen device or select the phone surface in the simulator.")
      .add("Which response would you like to see next?")
      .build();
}

responseBuilder
    .add("This is a table with all the possible fields.")
    .add(
        new TableCard()
            .setTitle("Table Title")
            .setSubtitle("Table Subtitle")
            .setImage(
                new Image()
                    .setUrl(
                        "https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png")
                    .setAccessibilityText("Alt text"))
            .setButtons(
                Arrays.asList(
                    new Button()
                        .setTitle("Button Text")
                        .setOpenUrlAction(
                            new OpenUrlAction().setUrl("https://assistant.google.com"))))
            .setColumnProperties(
                Arrays.asList(
                    new TableCardColumnProperties()
                        .setHeader("header 1")
                        .setHorizontalAlignment("CENTER"),
                    new TableCardColumnProperties()
                        .setHeader("header 2")
                        .setHorizontalAlignment("LEADING"),
                    new TableCardColumnProperties()
                        .setHeader("header 3")
                        .setHorizontalAlignment("TRAILING")))
            .setRows(
                Arrays.asList(
                    new TableCardRow()
                        .setCells(
                            Arrays.asList(
                                new TableCardCell().setText("row 1 item 1"),
                                new TableCardCell().setText("row 1 item 2"),
                                new TableCardCell().setText("row 1 item 3")))
                        .setDividerAfter(false),
                    new TableCardRow()
                        .setCells(
                            Arrays.asList(
                                new TableCardCell().setText("row 2 item 1"),
                                new TableCardCell().setText("row 2 item 2"),
                                new TableCardCell().setText("row 2 item 3")))
                        .setDividerAfter(true),
                    new TableCardRow()
                        .setCells(
                            Arrays.asList(
                                new TableCardCell().setText("row 2 item 1"),
                                new TableCardCell().setText("row 2 item 2"),
                                new TableCardCell().setText("row 2 item 3"))))));
return responseBuilder.build();

JSON

下記の JSON は Webhook レスポンスを示します。

{
  "payload": {
    "google": {
      "expectUserResponse": true,
      "richResponse": {
        "items": [
          {
            "simpleResponse": {
              "textToSpeech": "This is a table with all the possible fields."
            }
          },
          {
            "tableCard": {
              "title": "Table Title",
              "subtitle": "Table Subtitle",
              "image": {
                "url": "https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png",
                "accessibilityText": "Alt Text"
              },
              "rows": [
                {
                  "cells": [
                    {
                      "text": "row 1 item 1"
                    },
                    {
                      "text": "row 1 item 2"
                    },
                    {
                      "text": "row 1 item 3"
                    }
                  ],
                  "dividerAfter": false
                },
                {
                  "cells": [
                    {
                      "text": "row 2 item 1"
                    },
                    {
                      "text": "row 2 item 2"
                    },
                    {
                      "text": "row 2 item 3"
                    }
                  ],
                  "dividerAfter": true
                },
                {
                  "cells": [
                    {
                      "text": "row 3 item 1"
                    },
                    {
                      "text": "row 3 item 2"
                    },
                    {
                      "text": "row 3 item 3"
                    }
                  ]
                }
              ],
              "columnProperties": [
                {
                  "header": "header 1",
                  "horizontalAlignment": "CENTER"
                },
                {
                  "header": "header 2",
                  "horizontalAlignment": "LEADING"
                },
                {
                  "header": "header 3",
                  "horizontalAlignment": "TRAILING"
                }
              ],
              "buttons": [
                {
                  "title": "Button Text",
                  "openUrlAction": {
                    "url": "https://assistant.google.com"
                  }
                }
              ]
            }
          },
          {
            "simpleResponse": {
              "textToSpeech": "Which response would you like to see next?"
            }
          }
        ]
      }
    }
  }
}

JSON

下記の JSON は Webhook レスポンスを示します。

{
  "expectUserResponse": true,
  "expectedInputs": [
    {
      "possibleIntents": [
        {
          "intent": "actions.intent.TEXT"
        }
      ],
      "inputPrompt": {
        "richInitialPrompt": {
          "items": [
            {
              "simpleResponse": {
                "textToSpeech": "This is a table with all the possible fields."
              }
            },
            {
              "tableCard": {
                "title": "Table Title",
                "subtitle": "Table Subtitle",
                "image": {
                  "url": "https://storage.googleapis.com/actionsresources/logo_assistant_2x_64dp.png",
                  "accessibilityText": "Alt Text"
                },
                "rows": [
                  {
                    "cells": [
                      {
                        "text": "row 1 item 1"
                      },
                      {
                        "text": "row 1 item 2"
                      },
                      {
                        "text": "row 1 item 3"
                      }
                    ],
                    "dividerAfter": false
                  },
                  {
                    "cells": [
                      {
                        "text": "row 2 item 1"
                      },
                      {
                        "text": "row 2 item 2"
                      },
                      {
                        "text": "row 2 item 3"
                      }
                    ],
                    "dividerAfter": true
                  },
                  {
                    "cells": [
                      {
                        "text": "row 3 item 1"
                      },
                      {
                        "text": "row 3 item 2"
                      },
                      {
                        "text": "row 3 item 3"
                      }
                    ]
                  }
                ],
                "columnProperties": [
                  {
                    "header": "header 1",
                    "horizontalAlignment": "CENTER"
                  },
                  {
                    "header": "header 2",
                    "horizontalAlignment": "LEADING"
                  },
                  {
                    "header": "header 3",
                    "horizontalAlignment": "TRAILING"
                  }
                ],
                "buttons": [
                  {
                    "title": "Button Text",
                    "openUrlAction": {
                      "url": "https://assistant.google.com"
                    }
                  }
                ]
              }
            },
            {
              "simpleResponse": {
                "textToSpeech": "Which response would you like to see next?"
              }
            }
          ]
        }
      }
    }
  ]
}

レスポンスのカスタマイズ

カスタムテーマを作成すると、リッチ レスポンスの外観を変更できます。 Actions プロジェクトのテーマを定義した場合は、 プロジェクトのアクションは、テーマに従ってスタイルが設定されます。このカスタム ブランディングは、ユーザーが画面付きのサーフェスでアクションを呼び出すときに会話に固有のデザインを与えるのに役立ちます。

カスタムのレスポンス テーマを設定する手順は次のとおりです。

  1. Actions Console で、[Develop] >テーマのカスタマイズ
  2. 次のいずれかまたはすべてを設定します。 <ph type="x-smartling-placeholder">
      </ph>
    • カードの背景として使用する背景色。イン 通常は、カードが見やすくなるように、背景に明るい色を 読みやすいものである必要があります。
    • [Primary color](メインの色)は、カードのヘッダー テキストと UI 要素のメインの色です。一般に、メインの色には背景とのコントラストを際立たせるために濃い色を使用します。
    • [Font family](フォント ファミリー)は、タイトルやその他の主なテキスト要素に使用されるフォントの種類を表します。
    • [Image corner style](画像コーナー スタイル)では、カードのコーナーの外観を変更できます。
    • 背景画像: 背景の代わりにカスタム画像を使用します。 指定します。ランドスケープ モード用とポートレート モード用の 2 つの画像を指定する必要があります。注: 背景画像を使用する場合、プライマリ カラーは白に設定されます。
  3. [保存] をクリックします。
で確認できます。 <ph type="x-smartling-placeholder">
</ph>
図 9.Actions Console でのテーマのカスタマイズ