Risposte dettagliate (Dialogflow)

Esplora in Dialogflow

Fai clic su Continua per importare il nostro esempio di risposte in Dialogflow. Quindi, segui questi passaggi per eseguire il deployment e testare l'esempio:

  1. Inserisci il nome di un agente e crea un nuovo agente Dialogflow per l'esempio.
  2. Al termine dell'importazione dell'agente, fai clic su Vai all'agente.
  3. Nel menu di navigazione principale, vai ad Fulfillment.
  4. Attiva l'editor incorporato, quindi fai clic su Esegui il deployment. L'editor contiene il codice di esempio.
  5. Nel menu di navigazione principale, vai a Integrazioni, quindi fai clic su Assistente Google.
  6. Nella finestra modale visualizzata, attiva Anteprima automatica delle modifiche e fai clic su Test per aprire il simulatore di azioni.
  7. Nel simulatore, inserisci Talk to my test app per testare il campione.
Continua

Utilizza una risposta dettagliata se vuoi visualizzare elementi visivi per migliorare le interazioni degli utenti con l'Azione. Questi elementi visivi possono suggerire come continuare una conversazione.

Le risposte avanzate possono essere visualizzate solo sullo schermo o nelle esperienze audio e schermo. Possono contenere i seguenti componenti:

Puoi anche consultare le nostre linee guida per la progettazione delle conversazioni per scoprire come incorporare questi elementi visivi nell'Azione.

Proprietà

Le risposte avanzate hanno i seguenti requisiti e proprietà facoltative che puoi configurare:

  • Funzionalità supportata sulle piattaforme con la funzionalità actions.capability.SCREEN_OUTPUT.
  • Il primo elemento di una risposta multimediale deve essere una risposta semplice.
  • Al massimo due semplici risposte.
  • Al massimo una carta di base o StructuredResponse.
  • Al massimo 8 chip di suggerimenti.
  • I chip di suggerimenti non sono consentiti in una FinalResponse
  • Il collegamento al web da smart display non è attualmente supportato.

Le seguenti sezioni mostrano come creare vari tipi di risposte avanzate.

Carta di base

Figura 1. Esempio di scheda di base (smartphone)

Una scheda di base mostra informazioni che possono includere:

  • Immagine
  • Titolo
  • Sottotitolo
  • Corpo del testo
  • Pulsante Collega
  • Border

Utilizza le schede di base principalmente a scopo di visualizzazione. Sono progettati per essere concisi, per presentare informazioni chiave (o di riepilogo) agli utenti e per consentire agli utenti di saperne di più, se lo desideri, tramite un link web.

Nella maggior parte dei casi, devi aggiungere chip di suggerimenti sotto le schede per continuare o cambiare la conversazione.

Evita di ripetere a tutti i costi le informazioni presentate nella scheda nel fumetto della chat.

Proprietà

Il tipo di risposta della scheda di base ha i seguenti requisiti e proprietà facoltative che puoi configurare:

  • Funzionalità supportata sulle piattaforme con la funzionalità actions.capability.SCREEN_OUTPUT.
  • Testo formattato (obbligatorio se non ci sono immagini)
    • Testo normale per impostazione predefinita.
    • Non deve contenere un link.
    • Limite di 10 righe con un'immagine; limite di 15 righe senza un'immagine. Corrisponde a circa 500 (con immagine) o 750 (senza immagine). Anche i telefoni con schermi più piccoli troncano il testo prima di quelli con schermo più grande. Se il testo contiene troppe righe, viene troncato in corrispondenza dell'ultima interruzione di parola con i puntini di sospensione.
    • È supportato un sottoinsieme limitato di Markdown:
      • Nuova riga con un doppio spazio seguito da \n
      • **bold**
      • *italics*
  • Immagine (obbligatoria se non è presente testo formattato)
    • Tutte le immagini devono essere alte 192 dp.
    • Se le proporzioni dell'immagine sono diverse da quelle dello schermo, l'immagine è centrata con barre grigie sui bordi verticali o orizzontali.
    • L'origine dell'immagine è un URL.
    • Sono consentite le GIF in movimento.

Facoltativo

  • Titolo
    • Testo normale.
    • Le dimensioni e il carattere sono corretti.
    • Al massimo una riga; i caratteri aggiuntivi vengono troncati.
    • L'altezza della scheda si comprime se non viene specificato alcun titolo.
  • Sottotitolo
    • Testo normale.
    • Carattere e dimensione del carattere corretti.
    • Al massimo una riga; i caratteri aggiuntivi vengono troncati.
    • L'altezza della scheda si riduce se non viene specificato alcun sottotitolo.
  • Pulsante Link
    • Il titolo del link è obbligatorio
    • Al massimo un link
    • Sono consentiti link a siti esterni al dominio dello sviluppatore.
    • Il testo del link non può essere fuorviante. Questa opzione viene verificata durante la procedura di approvazione.
    • Una scheda di base non ha funzionalità di interazione senza un link. Toccando il link, l'utente viene reindirizzato al link, mentre il corpo principale della scheda rimane inattivo.
  • Bordo
    • Il bordo tra la scheda e il contenitore dell'immagine può essere regolato per personalizzare la presentazione della scheda di base.
    • Configurato impostando la proprietà della stringa JSON imageDisplayOptions
Figura 2. Esempio di scheda di base (smart display)

Codice campione

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

Tieni presente che il JSON di seguito descrive una risposta 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

Tieni presente che il JSON di seguito descrive una risposta 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?"
              }
            }
          ]
        }
      }
    }
  ]
}
Figura 3. Esempio di carosello di navigazione (smartphone)

Un carosello di navigazione è una risposta dettagliata che consente agli utenti di scorrere in verticale e selezionare un riquadro in una raccolta. I caroselli di navigazione sono progettati specificamente per i contenuti web aprendo il riquadro selezionato in un browser web (o in un browser AMP se tutti i riquadri sono abilitati per AMP). Il carosello di navigazione persiste anche sulla piattaforma dell'assistente per navigare in un secondo momento.

Proprietà

Il tipo di risposta del carosello di navigazione presenta i seguenti requisiti e proprietà facoltative che puoi configurare:

  • Supportato sulle piattaforme che hanno funzionalità sia di actions.capability.SCREEN_OUTPUT sia di actions.capability.WEB_BROWSER. Questo tipo di risposta non è al momento disponibile su smart display.
  • Esplorazione del carosello in corso
    • Massimo 10 riquadri.
    • Minimo due riquadri.
    • I riquadri nel carosello devono rimandare a contenuti web (contenuti AMP consigliati).
      • Affinché l'utente venga indirizzato a un visualizzatore AMP, l'elemento urlHintType nei riquadri di contenuti AMP deve essere impostato su "AMP_CONTENT".
  • Navigazione nei riquadri del carosello
    • Coerenza del riquadro (obbligatoria):
      • Tutti i riquadri di un carosello di navigazione devono avere gli stessi componenti. Ad esempio, se un riquadro ha un campo immagine, anche il resto dei riquadri nel carosello deve contenere campi immagine.
      • Se tutti i riquadri nel carosello di navigazione rimandano a contenuti abilitati per AMP, l'utente viene indirizzato a un browser AMP con funzionalità aggiuntive. Se un riquadro rimanda a contenuti non AMP, tutti i riquadri indirizzano gli utenti a un browser web.
    • Immagine (facoltativa)
      • L'immagine deve essere di 128 dp di altezza x 232 dp di larghezza.
      • Se le proporzioni non corrispondono a quelle del riquadro di delimitazione, l'immagine viene centrata con barre ai lati. Su smartphone, l'immagine è centrata in un quadrato con gli angoli arrotondati.
      • Se un link immagine non funziona, viene utilizzata un'immagine segnaposto.
      • Per un'immagine è necessario inserire testo alternativo.
    • Titolo (obbligatorio)
      • Stesse opzioni di formattazione della scheda di testo di base.
      • I titoli devono essere univoci (per supportare la selezione vocale).
      • Massimo due righe di testo.
      • Dimensione carattere 16 sp.
    • Descrizione (facoltativa)
      • Stesse opzioni di formattazione della scheda di testo di base.
      • Massimo quattro righe di testo.
      • Troncato con i puntini di sospensione (...)
      • Dimensione carattere 14 sp, colore grigio.
    • Piè di pagina (facoltativo)
      • Carattere e dimensione del carattere corretti.
      • Massimo una riga di testo.
      • Troncato con i puntini di sospensione (...)
      • Ancorati in basso, i riquadri con meno righe di corpo del testo potrebbero avere uno spazio bianco sopra il sottotitolo.
      • Dimensione carattere 14 sp, colore grigio.
  • Interazione
    • L'utente può scorrere la pagina in verticale per visualizzare gli elementi.
    • Scheda contactless: quando tocca un elemento, l'utente viene indirizzato a un browser, che mostra la pagina collegata.
  • Input vocale
    • Comportamento del microfono
      • Il microfono non si riapre quando viene inviato un carosello di navigazione all'utente.
      • L'utente può comunque toccare il microfono o chiamare l'assistente ("Hey Google") per riattivare il microfono.

Consulenza

Per impostazione predefinita, il microfono rimane chiuso dopo l'invio di un carosello di navigazione. Se vuoi continuare la conversazione in seguito, ti consigliamo vivamente di aggiungere chip di suggerimento sotto il carosello.

Non ripetere mai le opzioni presentate nell'elenco sotto forma di chip di suggerimenti. I chip in questo contesto vengono utilizzati per ruotare la conversazione (non per la selezione della scelta).

Come per gli elenchi, la bolla della chat che accompagna la scheda carosello è un sottoinsieme dell'audio (TTS/SSML). L'audio (TTS/SSML) qui integra il primo riquadro nel carosello e sconsigliamo inoltre vivamente di leggere tutti gli elementi dal carosello. È meglio menzionare il primo articolo e il motivo per cui è presente (ad esempio, il più popolare, il acquistato più di recente, il più discusso).

Codice campione

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();

Tieni presente che il JSON di seguito descrive una risposta 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"
                  }
                }
              ]
            }
          }
        ]
      }
    }
  }
}

Tieni presente che il JSON di seguito descrive una risposta 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"
        }
      ]
    }
  ]
}

Gestione dell'elemento selezionato in corso...

Non è necessario alcun completamento di follow-up per le interazioni degli utenti con gli elementi del carosello di navigazione, poiché il carosello gestisce il passaggio al browser. Tieni presente che il microfono non si riaprirà dopo che l'utente ha interagito con un elemento del carosello di navigazione, quindi dovresti terminare la conversazione o includere chip di suggerimento nella risposta, come indicato nelle indicazioni precedenti.

Chip di suggerimenti

Figura 4. Esempio di chip di suggerimento (smartphone)

Utilizza i chip di suggerimenti per suggerire le risposte e continuare o cambiare la conversazione. Se durante la conversazione è presente un invito all'azione principale, puoi elencarlo come primo chip di suggerimento.

Quando possibile, dovresti incorporare un suggerimento chiave nel fumetto della chat, ma fallo solo se la risposta o la conversazione in chat ti sembrano naturali.

Proprietà

I chip di suggerimento hanno i seguenti requisiti e proprietà facoltative che puoi configurare:

  • Funzionalità supportata sulle piattaforme con la funzionalità actions.capability.SCREEN_OUTPUT.
  • Per collegare i chip di suggerimenti al web, le piattaforme devono avere anche la funzionalità actions.capability.WEB_BROWSER. Questa funzionalità non è attualmente disponibile su smart display.
  • Massimo otto chip.
  • Lunghezza massima del testo: 25 caratteri.
  • Supporta solo il testo normale.

Figura 5. Esempio di chip di suggerimento (smart display)

Codice campione

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

Tieni presente che il JSON di seguito descrive una risposta 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

Tieni presente che il JSON di seguito descrive una risposta 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/"
          }
        }
      }
    }
  ]
}

Risposte multimediali

Figura 6. Esempio di risposta multimediale (smartphone)

Le risposte multimediali consentono alle azioni di riprodurre contenuti audio con una durata di riproduzione superiore al limite di 240 secondi di SSML. Il componente principale di una risposta multimediale è la scheda a traccia singola. La scheda consente all'utente di eseguire queste operazioni:

  • Riproduci di nuovo gli ultimi 10 secondi.
  • Vai avanti di 30 secondi.
  • Visualizza la durata totale dei contenuti multimediali.
  • Visualizzare un indicatore di avanzamento per la riproduzione audio.
  • Visualizzare il tempo di riproduzione trascorso.

Le risposte multimediali supportano i seguenti controlli audio per l'interazione vocale:

  • "Hey Google, riproduci."
  • "Hey Google, metti in pausa."
  • "Hey Google, interrompi."
  • "Hey Google, ricomincia da capo."

Gli utenti possono regolare il volume anche dicendo frasi come "Hey Google, alza il volume" o "Hey Google, imposta il volume al 50%". Gli intent nell'Azione hanno la precedenza se gestiscono frasi di addestramento simili. Consenti all'assistente di gestire queste richieste degli utenti, a meno che l'Azione non abbia un motivo specifico.

Proprietà

Le risposte multimediali hanno i seguenti requisiti e proprietà facoltative che puoi configurare:

  • Supportato sulle piattaforme con la funzionalità actions.capability.MEDIA_RESPONSE_AUDIO.
  • L'audio per la riproduzione deve essere in un file .mp3 formattato correttamente. Il live streaming non è supportato.
  • Il file multimediale per la riproduzione deve essere specificato come URL HTTPS.
  • Immagine (facoltativa)
    • Se lo desideri, puoi includere un'icona o un'immagine.
    • Icona
      • L'icona viene visualizzata come miniatura senza bordi a destra della scheda del player multimediale.
      • La dimensione deve essere 36 x 36 dp. Le immagini di dimensioni maggiori vengono ridimensionate per essere adattate.
    • Immagine
      • Il contenitore dell'immagine avrà un'altezza di 192 dp.
      • L'immagine viene visualizzata nella parte superiore della scheda del media player e si estende per l'intera larghezza della scheda. La maggior parte delle immagini viene visualizzata con barre in alto o ai lati.
      • Sono consentite le GIF in movimento.
    • Devi specificare l'origine dell'immagine come URL.
    • Il testo alternativo è obbligatorio per tutte le immagini.

Comportamento sulle piattaforme

Le risposte multimediali sono supportate sui telefoni Android e su Google Home. Il comportamento delle risposte multimediali dipende dalla superficie su cui gli utenti interagiscono con le tue Azioni.

Sui telefoni Android, gli utenti possono visualizzare le risposte multimediali quando viene soddisfatta una delle seguenti condizioni:

  • L'Assistente Google è in primo piano e lo schermo del telefono è attivo.
  • L'utente esce dall'Assistente Google durante la riproduzione dell'audio e torna all'Assistente Google entro 10 minuti dal completamento della riproduzione. Quando torna all'Assistente Google, l'utente vede la scheda dei contenuti multimediali e i chip di suggerimenti.
  • L'assistente consente agli utenti di controllare il volume del dispositivo all'interno dell'Azione conversazionale dicendo, ad esempio, "alza il volume" o "imposta il volume al 50%". Se hai intent che gestiscono frasi di addestramento simili, hanno la precedenza. Ti consigliamo di consentire all'assistente di gestire queste richieste degli utenti, a meno che l'Azione non abbia un motivo specifico.

I controlli multimediali sono disponibili quando il telefono è bloccato. Su Android, i controlli vengono visualizzati anche nell'area di notifica.

Figura 7. Esempio di risposta multimediale (smart display)

Codice campione

Il seguente esempio di codice mostra come aggiornare le risposte multimediali per includere contenuti multimediali.

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

Tieni presente che il JSON di seguito descrive una risposta 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

Tieni presente che il JSON di seguito descrive una risposta 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"
            }
          ]
        }
      }
    }
  ]
}

Consulenza

La tua risposta deve includere un valore mediaResponse con un valore di mediaType pari a AUDIO e contenente un valore mediaObject nell'array di elementi della risposta avanzata. Una risposta multimediale supporta un singolo oggetto multimediale. Un oggetto multimediale deve includere l'URL dei contenuti del file audio. Un oggetto multimediale può facoltativamente includere un nome, un testo secondario (descrizione) e un'icona o un URL immagine.

Sui telefoni e su Google Home, quando l'Azione completa la riproduzione audio, l'Assistente Google controlla se la risposta multimediale è FinalResponse. In caso contrario, viene inviato un callback al fulfillment per consentirti di rispondere all'utente.

L'Azione deve includere chip di suggerimento se la risposta non è una FinalResponse.

Gestione del callback dopo il completamento della riproduzione

L'Azione deve gestire l'intent actions.intent.MEDIA_STATUS per richiedere all'utente di proseguire (ad esempio, riprodurre un'altra canzone). L'Azione riceve questo callback una volta completata la riproduzione dei contenuti multimediali. Nel callback, l'argomento MEDIA_STATUS contiene informazioni sullo stato del contenuto multimediale corrente. Il valore dello stato sarà FINISHED o STATUS_UNSPECIFIED.

Utilizzo di Dialogflow

Se vuoi eseguire la diramazione conversazionale in Dialogflow, dovrai configurare un contesto di input di actions_capability_media_response_audio nell'intent per assicurarti che si attivi solo sulle piattaforme che supportano una risposta multimediale.

Creare la distribuzione

Lo snippet di codice riportato di seguito mostra come scrivere il codice di fulfillment per l'azione. Se utilizzi Dialogflow, sostituisci actions.intent.MEDIA_STATUS con il nome dell'azione specificato nell'intent che riceve l'evento actions_intent_MEDIA_STATUS, ad esempio "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

Tieni presente che il JSON di seguito descrive una richiesta 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

Tieni presente che il JSON di seguito descrive una richiesta 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"
}

Schede tabella

Le schede tabella ti consentono di visualizzare dati tabulari nella risposta (ad esempio, classifiche sportive, risultati elettorali e voli). Puoi definire colonne e righe (fino a tre ciascuna) che l'assistente deve mostrare nella scheda della tabella. Puoi anche definire colonne e righe aggiuntive insieme alla loro priorità.

Le tabelle sono diverse dagli elenchi verticali perché visualizzano dati statici e non sono interattive, come gli elementi degli elenchi.

Figura 8. Esempio di scheda tabella (smart display)

Proprietà

Le schede della tabella hanno i seguenti requisiti e proprietà facoltative che puoi configurare:

  • Funzionalità supportata sulle piattaforme con la funzionalità actions.capability.SCREEN_OUTPUT.

La seguente sezione riassume come personalizzare gli elementi in una scheda della tabella.

Nome È facoltativo È personalizzabile Note di personalizzazione
title Titolo generale della tabella. Deve essere impostato se è impostato un sottotitolo. Puoi personalizzare la famiglia e il colore di caratteri.
subtitle No Sottotitolo della tabella.
image Immagine associata alla tabella.
Row No

Dati delle righe della tabella. Deve essere composto da un array di oggetti Cell e da una proprietà divider_after che indica se deve essere presente un divisore dopo la riga.

È garantito che le prime 3 righe vengano mostrate, ma altre potrebbero non essere visualizzate su alcune piattaforme.

Esegui un test con il simulatore per vedere quali righe vengono mostrate per una determinata superficie. Sulle piattaforme che supportano la funzionalità WEB_BROWSER, puoi indirizzare l'utente a una pagina web con più dati. Il collegamento al web non è attualmente disponibile per gli smart display.

ColumnProperties Intestazione e allineamento di una colonna. Composto da una proprietà header (che rappresenta il testo dell'intestazione per una colonna) e una proprietà horizontal_alignment (di tipo HorizontalAlignment).
Cell No Descrive una cella in una riga. Ogni cella contiene una stringa che rappresenta un valore di testo. Puoi personalizzare il testo nella cella.
Button Un oggetto pulsante che solitamente viene visualizzato nella parte inferiore di una scheda. Una scheda tabella può avere un solo pulsante. Puoi personalizzare il colore dei pulsanti.
HorizontalAlignment Allineamento orizzontale dei contenuti all'interno della cella. I valori possono essere LEADING, CENTER o TRAILING. Se non specificati, i contenuti vengono allineati al bordo iniziale della cella.

Codice campione

I seguenti snippet mostrano come implementare una semplice scheda della tabella:

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

Tieni presente che il JSON di seguito descrive una risposta 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

Tieni presente che il JSON di seguito descrive una risposta 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"
        }
      ]
    }
  ]
}

I seguenti snippet mostrano come implementare una scheda della tabella complessa:

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

Tieni presente che il JSON di seguito descrive una risposta 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

Tieni presente che il JSON di seguito descrive una risposta 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?"
              }
            }
          ]
        }
      }
    }
  ]
}

Personalizzazione delle risposte

Puoi modificare l'aspetto delle tue risposte avanzate creando un tema personalizzato. Se definisci un tema per il progetto Actions, le risposte avanzate nelle azioni del progetto avranno uno stile basato sul tema. Questo branding personalizzato può essere utile per definire un aspetto unico per la conversazione quando gli utenti invocano le tue azioni su una piattaforma con uno schermo.

Per impostare un tema di risposta personalizzato:

  1. Nella console di Actions, vai a Sviluppo > Personalizzazione del tema.
  2. Imposta una o tutte le seguenti opzioni:
    • Colore sfondo da utilizzare come sfondo delle schede. In generale, dovresti utilizzare un colore chiaro per lo sfondo, in modo che i contenuti della scheda siano facilmente leggibili.
    • Colore principale è il colore principale per i testi delle intestazioni e gli elementi dell'interfaccia utente delle schede. In generale, ti consigliamo di usare un colore principale più scuro per creare un contrasto con lo sfondo.
    • Famiglia di caratteri descrive il tipo di carattere utilizzato per i titoli e altri elementi di testo in evidenza.
    • Lo stile degli angoli dell'immagine può modificare l'aspetto degli angoli delle schede.
    • L'immagine di sfondo utilizza un'immagine personalizzata al posto del colore di sfondo. Devi fornire due immagini diverse quando il dispositivo di superficie è rispettivamente in modalità Orizzontale o Ritratto. Tieni presente che se utilizzi un'immagine di sfondo, il colore principale è impostato sul bianco.
  3. Fai clic su Salva.
Figura 9. Personalizzazione del tema nella console di Actions