在 Dialogflow 中探索
按一下 [繼續],將回應範例匯入 Dialogflow。接著,請按照 部署及測試範例的步驟:
- 輸入虛擬服務專員名稱,並為範例建立新的 Dialogflow 代理程式。
- 代理程式匯入完畢後,按一下「Go to agent」。
- 在主要導覽選單中,前往「Fulfillment」(執行要求)。
- 啟用「Inline Editor」(內嵌編輯器),然後按一下 [Deploy] (部署)。編輯器包含範例 再也不是件繁重乏味的工作
- 在主要導覽選單中,前往「Integrations」(整合),然後按一下「Google」 Google 助理。
- 在出現的互動視窗中,啟用「自動預覽變更」,然後按一下「測試」 以開啟動作模擬工具
- 在模擬工具中輸入
Talk to my test app
即可測試範例!
如果想顯示視覺元素來提升使用者參與度,請使用複合式回應 互動情形。這些視覺元素可讓系統提示 來延續對話。
複合式回應可能只會出現在純螢幕或音訊和螢幕上。他們 可包含下列元件:
或是參閱對話設計指南,瞭解 如何將這些視覺元素整合至動作中。
屬性
複合式回應具有下列規定和選填項目 您可以設定下列屬性:
- 支援具有
actions.capability.SCREEN_OUTPUT
功能的介面。 - 複合式回應中的第一個項目必須是簡易回應。
- 最多兩個簡單的回應。
- 最多只能設定一張基本卡片或
StructuredResponse
。 - 最多 8 個建議方塊。
FinalResponse
不支援建議方塊- 目前不支援透過智慧螢幕連結至網路。
以下章節將說明如何建立各種複合式回應。
基本資訊卡
,瞭解如何調查及移除這項存取權。![](https://developers-dot-devsite-v2-prod.appspot.com/static/assistant/conversational/images/basic-card.png?authuser=9&hl=zh-tw)
基本資訊卡會顯示下列資訊:
- 圖片
- 標題
- 副標題
- 文字內文
- 連結按鈕
- 英蘇邊界
基本資訊卡主要用於顯示。設計精簡扼要 向使用者呈現關鍵 (或摘要) 資訊,並讓使用者 (使用網頁連結)。
在多數情況下,應在下方新增建議方塊 以繼續或轉向對話方向。
避免重複即時通訊泡泡中顯示的資訊卡資訊 。
屬性
基本資訊卡回應類型具有以下要求和選用項目 您可以設定下列屬性:
- 支援具有
actions.capability.SCREEN_OUTPUT
功能的介面。 - 格式化文字(如果沒有圖片,則為必要參數)
- 預設為純文字。
- 不得包含連結。
- 最多 10 行 (含圖片),不含圖片的行數上限為 15 行。這是關於 500 (含圖片) 或 750 (不含圖片) 字元。小螢幕手機 而且截斷比大螢幕手機更少的文字如果文字包含 許多行,在最後一個字詞斷行時可能會以刪節號截斷。
- 系統支援的 Markdown 子集如下:
- 新增一行雙空格,後接\n
**bold**
*italics*
- 圖片(如果沒有格式化文字,則為必要選項)
- 所有圖片的高度強制設為 192 dp。
- 如果圖片的長寬比與螢幕不同, 垂直或水平邊緣置中顯示灰色長條。
- 圖片來源是網址。
- 系統允許使用動態 GIF。
選用
- 標題
- 純文字。
- 固定字型和大小。
- 最多一行;多餘的字元遭到截斷。
- 如未指定標題,資訊卡高度會收合。
- 副標題
- 純文字。
- 固定字型和字型大小。
- 最多一行;多餘的字元遭到截斷。
- 如未指定副標題,資訊卡高度會收合。
- 連結按鈕
- 必須提供連結標題
- 最多一個連結
- 可以提供開發人員網域以外的網站連結。
- 連結文字不得誤導使用者。我們會在核准程序進行檢查。
- 基本資訊卡在沒有連結的情況下無法互動。輕觸 連結會將使用者帶往連結,資訊卡的主要內文則 就會維持停用狀態。
- 框線
- 資訊卡和映像檔容器之間的邊框可調整為 自訂基本資訊卡的呈現方式
- 透過設定 JSON 字串屬性進行設定
imageDisplayOptions
敬上
![](https://developers-dot-devsite-v2-prod.appspot.com/static/assistant/conversational/images/smart-display/basic-card.png?authuser=9&hl=zh-tw)
程式碼範例
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?" } } ] } } } ] }
瀏覽輪轉介面
,瞭解如何調查及移除這項存取權。![](https://developers-dot-devsite-v2-prod.appspot.com/static/assistant/conversational/images/browse-carousel.png?authuser=9&hl=zh-tw)
瀏覽輪轉介面是一種豐富的回應內容,可讓使用者垂直捲動 並從集合中選取圖塊。瀏覽輪轉介面經過特別設計 在網路瀏覽器 (或 AMP 瀏覽器) 中開啟所選圖塊,以監控網頁內容 (如果所有圖塊都已啟用 AMP)。瀏覽輪轉介面也會保留在 的 Google 助理介面,以供日後瀏覽時使用。
屬性
瀏覽輪轉介面回應類型具有下列規定和選用選項 您可以設定下列屬性:
- 支援同時具備
actions.capability.SCREEN_OUTPUT
的介面 和actions.capability.WEB_BROWSER
功能這個回應類型 目前不適用於智慧螢幕。 - 瀏覽輪轉介面
- 最多只能有十個圖塊。
- 至少兩個圖塊。
- 輪轉介面中的圖塊必須全部連結至網路內容 (AMP 內容)
建議)。
- 為了將使用者導向 AMP 檢視器,
urlHintType
AMP 內容圖塊必須設為「AMP_CONTENT」。
- 為了將使用者導向 AMP 檢視器,
- 瀏覽輪轉介面資訊方塊
- 圖塊一致性 (必要):
- 瀏覽輪轉介面中的所有資訊方塊都必須具有相同元件。 舉例來說,如果一個圖塊有圖片欄位,其餘圖塊 輪轉介面中也必須包含圖片欄位
- 如果瀏覽輪轉介面中的所有圖塊都連結到支援 AMP 的內容, 將使用者帶往 AMP 瀏覽器的網頁。 如果有任何資訊方塊連結至非 AMP 內容,則所有圖塊會引導使用者 轉換為網路瀏覽器。
- 圖片 (選用)
- 圖片的寬度強制設為 128 dp x 232 dp。
- 如果圖片的長寬比與圖片定界框不符 表示圖片置中且兩側皆有長條使用智慧型手機時 圖片將置中擺放為圓角的正方形。
- 如果圖片連結損毀,系統會改用預留位置圖片。
- 請為圖片加上替代文字。
- 標題 (必填)
- 格式選項與基本文字資訊卡相同。
- 標題不得重複 (即支援語音選項功能),
- 最多兩行文字。
- 字型大小:16 sp。
- 說明 (選填)
- 格式選項與基本文字資訊卡相同。
- 最多 4 行文字。
- 以刪節號 (...) 截斷 (...)
- 字型大小:14sp,灰色。
- 頁尾 (選填)
- 固定字型和字型大小。
- 最多一行。
- 以刪節號 (...) 截斷 (...)
- 固定在底部,因此內文較少的資訊方塊可能會 子文字上方有空白字元。
- 字型大小:14sp,灰色。
- 圖塊一致性 (必要):
- 互動情形
- 使用者可以垂直捲動查看項目。
- 輕觸資訊卡:使用者輕觸某項商品後,系統會將他們導向瀏覽器,顯示 連結的網頁。
- 語音輸入
- 麥克風行為
- 當系統傳送瀏覽輪轉介面給使用者時,麥克風不會重新開啟。
- 使用者仍可輕觸麥克風或叫用 Google 助理 (「Ok Google」) 重新開啟麥克風。
- 麥克風行為
指引
根據預設,傳送瀏覽輪轉介面後,麥克風會保持關閉狀態。如果您希望 之後如要延續對話,我們強烈建議你加入建議方塊 面板下方
建議不要在建議方塊內重複顯示清單中的選項。來自以下區塊的方塊: 此情境用於引導對話方向 (不適用於選取選項)。
與清單相同,輪轉介面資訊卡隨附的即時通訊泡泡為 與音訊的子集 (TTS/SSML)這裡的音訊 (TTS/SSML) 整合了第一個 我們也強烈建議不要閱讀所有元素 選項。建議先提及第一個項目,並說明原因 會很明顯 (例如最受歡迎、最近購買、最常購買 剛才談到的事)。
程式碼範例
Node.js
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', }), ], })); });
Java
@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(); }
Node.js
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', }), ], }));
Java
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
請注意,下列 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
請注意,下列 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" } ] } ] }
處理選取的項目
使用者與瀏覽輪轉介面進行互動時,不需要執行後續追蹤要求 項目,因為輪轉介面會處理瀏覽器轉換。請注意,麥克風 使用者與瀏覽輪轉介面項目互動後,系統就不會重新開啟,因此 應結束對話或是包括 按照上述指南在回覆中顯示建議方塊。
建議方塊
,瞭解如何調查及移除這項存取權。![](https://developers-dot-devsite-v2-prod.appspot.com/static/assistant/conversational/images/suggestions.png?authuser=9&hl=zh-tw)
使用建議方塊在回覆內容提示中繼續操作或透視對話。 如果在會談期間有主要的行動號召,建議刊登產品資訊 做為第一個建議方塊
請盡可能在聊天室中納入一項重要建議。 但前提是回覆或即時通訊對話內容不夠自然。
屬性
建議方塊有下列規定和選用欄位 您可以設定下列屬性:
- 支援具有
actions.capability.SCREEN_OUTPUT
功能的介面。 - 如要將建議方塊連結至網路,平台也必須有
actions.capability.WEB_BROWSER
功能。這項功能目前 適用於智慧螢幕 - 最多只能有八個方塊。
- 文字長度上限為 25 個字元。
僅支援純文字。
![](https://developers-dot-devsite-v2-prod.appspot.com/static/assistant/conversational/images/smart-display/chips.png?authuser=9&hl=zh-tw)
程式碼範例
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/" } } } } ] }
媒體回應
,瞭解如何調查及移除這項存取權。![](https://developers-dot-devsite-v2-prod.appspot.com/static/assistant/conversational/images/media.png?authuser=9&hl=zh-tw)
媒體回應可讓動作透過播放時間長度播放音訊內容 超過 240 秒的 SSML 限制媒體的主要元件 則是單軌資訊卡資訊卡可讓使用者 作業:
- 重播最後 10 秒。
- 快轉 30 秒。
- 查看媒體內容的總長度。
- 查看音訊播放的進度指標。
- 查看經過時間的播放時間。
媒體回應支援下列語音互動音訊控制項:
- 「Ok Google,播放。」
- 「Ok Google,暫停。」
- 「Ok Google,停止。」
- 「Ok Google,重新開始。」
使用者也可以說出「Ok Google,調高音量」這類指令 。"或「Ok Google,將音量設為百分之 50。」在 如果處理的訓練詞組相似,系統會優先採取動作。允許 Google 助理 除非你的動作有特定原因,否則應處理這些使用者要求。
屬性
媒體回應具有下列需求和選用屬性 可以設定:
- 支援具有
actions.capability.MEDIA_RESPONSE_AUDIO
的介面 技術。 - 要播放的音訊必須使用格式正確的
.mp3
檔案。即時影像 不支援串流。 - 播放的媒體檔案必須指定為 HTTPS 網址。
- 圖片 (選用)
- 您可以視需要加入圖示或圖片。
- 圖示
- 你的圖示會顯示為媒體右側的無邊框縮圖 玩家卡。
- 大小應為 36 x 36 dp。系統會將較大的圖片調整為適當大小,
- 圖片
- 圖片容器的高度為 192 dp。
- 您的圖片會顯示在媒體播放器資訊卡頂端,範圍涵蓋 資訊卡的完整寬度。大部分圖片都會顯示在 水平或側邊
- 系統允許使用動態 GIF。
- 您必須將圖片來源指定為網址。
- 所有圖片都必須有替代文字。
平台上的行為
Android 手機和 Google Home 都支援媒體回應功能。 媒體回應的行為取決於使用者互動平台 互動。
如果 Android 手機符合下列任一條件,使用者就能查看媒體回應 滿足:
- Google 助理在前景並已開啟手機螢幕。
- 使用者在音訊播放過程中離開 Google 助理,並返回 Google 助理在播放完畢後 10 分鐘內。返回 Google 助理,使用者會看到媒體資訊卡和建議方塊。
- Google 助理可讓使用者控制你的 對話動作。只要說「調高音量」或「設定 將音量調高到 50%」即可。如果您的意圖會處理類似的訓練詞組 意圖的優先順序建議您讓 Google 助理處理這些資訊 。
手機鎖定時仍可使用媒體控制選項,在 Android 上,控制項 也會顯示在通知區域中
![](https://developers-dot-devsite-v2-prod.appspot.com/static/assistant/conversational/images/smart-display/media.png?authuser=9&hl=zh-tw)
程式碼範例
以下程式碼範例說明如何將複合式回應更新為 包括媒體
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" } ] } } } ] }
指引
回覆必須包含 mediaType
為 AUDIO
的 mediaResponse
,以及
包含 mediaObject
出現在複合式回應項目陣列中。媒體
回應可支援單一媒體物件。媒體物件必須包含內容
音訊檔案的網址。媒體物件可選擇在當中加入名稱、副文字
,以及圖示或圖片網址。
在手機上和 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 列) 要求 Google 助理顯示在表格資訊卡上。 您也可以定義其他資料欄和資料列,以及其優先順序。
表格與直向清單不同,因為表格會顯示靜態資料 則無法與清單元素互動
,瞭解如何調查及移除這項存取權。![](https://developers-dot-devsite-v2-prod.appspot.com/static/assistant/conversational/images/smart-display/table.png?authuser=9&hl=zh-tw)
屬性
表格資訊卡具有下列要求和選用屬性,可讓您 設定:
- 支援具有
actions.capability.SCREEN_OUTPUT
功能的介面。
以下章節將摘要說明如何自訂表格中的元素 資訊卡
名稱 | 選填 | 可自訂 | 自訂附註 |
---|---|---|---|
title |
是 | 是 | 表格的整體標題。如有設定字幕,就必須設定標題。你可以 自訂字型系列和顏色。 |
subtitle |
是 | 否 | 資料表的副標題。 |
image |
是 | 是 | 與資料表相關聯的圖片。 |
Row |
否 | 是 |
表格的資料列資料。由 前 3 列保證會顯示,但有些可能不會顯示 出現在某些表面上 請使用模擬工具進行測試,看看哪些資料列會顯示於
系統的預測位置在支援 |
ColumnProperties |
是 | 是 | 資料欄的標頭和對齊方式。由 header 組成
屬性 (代表資料欄的標題文字) 和
horizontal_alignment 屬性 (類型為
HorizontalAlignment )。 |
Cell |
否 | 是 | 說明資料列中的儲存格。每個儲存格都包含代表 文字值。您可以自訂儲存格中的文字。 |
Button |
是 | 是 | 通常顯示在資訊卡底部的按鈕物件。表格 資訊卡只能有 1 個按鈕。您可以自訂按鈕的顏色。 |
HorizontalAlignment |
是 | 是 | 儲存格內內容的水平對齊方式。值可以是
LEADING 、CENTER 或 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 專案定義主題,就能讓整個應用程式包含 專案的動作會依照你的主題樣式。這個自訂品牌宣傳元素 也可以為對話定義獨特的外觀和風格 在螢幕上叫用動作。
如要設定自訂回應主題,請按照下列步驟操作:
- 在 Actions 主控台中,前往「開發」>「開發」>「開發自訂主題。
- 設定以下任一或所有資訊:
- 背景顏色:做為資訊卡的背景。於 一般而言,應用程式背景應使用淺色, 內容易讀易懂
- Primary color (主要顏色) 是資訊卡的主要顏色標題文字和 UI 元素。一般而言,建議使用較深的主色來對比 與背景一起編輯
- 「字型系列」說明標題和其他文字使用的字型類型 醒目的文字元素
- 圖片邊角樣式可變更資訊卡的外觀也不必那麼單憑空像
- 背景圖片會使用自訂圖片取代背景 顏色。您必須提供兩張不同的圖片, 介面裝置分別處於橫向或直向模式。請注意, 如果使用背景圖片,主要顏色會設定為白色。
- 按一下 [儲存]。
![](https://developers-dot-devsite-v2-prod.appspot.com/static/assistant/conversational/images/theme-customization.png?authuser=9&hl=zh-tw)