在 Dialogflow 中探索
点击继续,将我们的 Surface 功能示例导入 Dialogflow。然后,按照 部署和测试示例的步骤如下:
- 输入代理名称并为示例创建新的 Dialogflow 代理。
- 代理导入完成后,点击转到代理 (Go to agent)。
- 在主导航菜单中,前往 Fulfillment。
- 启用内嵌编辑器,然后点击部署。编辑器包含示例 代码。
- 在主导航菜单中,前往 Integrations(集成),然后点击 Google Google 助理。
- 在显示的模态窗口中,启用 Auto-preview changes(自动预览更改),然后点击 Test(测试) 打开 Actions 模拟器。
- 在模拟器中,输入
Talk to my test app
以测试该示例!
你的 Action 可以出现在各种平台上,包括纯音频 界面(智能音箱)以及音频和(例如智能显示屏和 )。
要设计和打造可在所有 surface 上顺畅运行的对话,请使用 surface 功能来适当控制对话范围并限定对话范围。
适用于 Action 的 Surface capability
通过 Actions on Google,您可以控制用户能否基于以下特征调用您的 Action: 呈现方式如果用户尝试在 他们会收到一条错误消息,告知他们 不受支持。
您可以在 Actions 项目中定义 Action 的 Surface 支持。
你的 Action 可以出现在各种途径中, 如智能手机(Android 和 iOS)和 Google Home 设备。
运行时 surface 功能
您可以通过两种主要方式利用运行时 surface 功能提供用户体验:
- 响应分支 - 向用户提供不同的响应,但具有 在不同平台上以相同的结构和流程开展对话。对于 例如,天气 Action 可能会在手机上显示一张带有图片的卡片, 在 Google Home 上播放音频文件,但对话流程是一样的 展示广告
会话分支 - 向用户呈现完全不同的 每个平台上的对话例如,如果你要打造一个 你可能需要在 Google Home 上提供重新排序流程, 移动设备上的购物车装配流程。如要进行对话分支,请限定范围 通过 Dialogflow 触发 intent 触发特定 Surface 功能 上下文。除非用户执行了特定操作 surface 功能。
多平台对话 - 通过单一平台向用户呈现对话 这个表面在对话过程中过渡到另一个表面。例如,如果 当用户通过 Google 等纯音频途径使用图片调用您的 Action 主屏幕,你可以构建 Action 以查找其他具有视觉效果的 surface 功能,并尽可能将对话推进。
响应分支
每当你的执行方式收到来自 Google 助理的请求时, 可以查询以下 surface(例如 Google Home 或 Android 手机) 功能:
Node.js
const hasScreen = conv.surface.capabilities.has('actions.capability.SCREEN_OUTPUT'); // OR conv.screen; const hasAudio = conv.surface.capabilities.has('actions.capability.AUDIO_OUTPUT'); const hasMediaPlayback = conv.surface.capabilities.has('actions.capability.MEDIA_RESPONSE_AUDIO'); const hasWebBrowser = conv.surface.capabilities.has('actions.capability.WEB_BROWSER'); // Interactive Canvas must be enabled in your project to see this const hasInteractiveCanvas = conv.surface.capabilities.has('actions.capability.INTERACTIVE_CANVAS');
Java
boolean hasScreen = request.hasCapability(Capability.SCREEN_OUTPUT.getValue()); boolean hasAudio = request.hasCapability(Capability.AUDIO_OUTPUT.getValue()); boolean hasMediaPlayback = request.hasCapability(Capability.MEDIA_RESPONSE_AUDIO.getValue()); boolean hasWebBrowser = request.hasCapability(Capability.WEB_BROWSER.getValue()); // Interactive Canvas must be enabled in your project to see this boolean hasInteractiveCanvas = request.hasCapability("INTERACTIVE_CANVAS");
Node.js
const hasScreen = conv.surface.capabilities.has('actions.capability.SCREEN_OUTPUT'); // OR conv.screen; const hasAudio = conv.surface.capabilities.has('actions.capability.AUDIO_OUTPUT'); const hasMediaPlayback = conv.surface.capabilities.has('actions.capability.MEDIA_RESPONSE_AUDIO'); const hasWebBrowser = conv.surface.capabilities.has('actions.capability.WEB_BROWSER'); // Interactive Canvas must be enabled in your project to see this const hasInteractiveCanvas = conv.surface.capabilities.has('actions.capability.INTERACTIVE_CANVAS');
Java
boolean hasScreen = request.hasCapability(Capability.SCREEN_OUTPUT.getValue()); boolean hasAudio = request.hasCapability(Capability.AUDIO_OUTPUT.getValue()); boolean hasMediaPlayback = request.hasCapability(Capability.MEDIA_RESPONSE_AUDIO.getValue()); boolean hasWebBrowser = request.hasCapability(Capability.WEB_BROWSER.getValue()); // Interactive Canvas must be enabled in your project to see this boolean hasInteractiveCanvas = request.hasCapability("INTERACTIVE_CANVAS");
JSON
请注意,下面的 JSON 描述的是 webhook 请求。
{ "responseId": "206a66fb-a572-4cfc-9e41-8e2eb62fdf18-712767ed", "queryResult": { "queryText": "Current capabilities", "parameters": {}, "allRequiredParamsPresent": true, "fulfillmentText": "Webhook failed for intent: Current Capabilities", "fulfillmentMessages": [ { "text": { "text": [ "Webhook failed for intent: Current Capabilities" ] } } ], "outputContexts": [ { "name": "projects/df-surface-caps-kohler/agent/sessions/ABwppHG7pYytu-kJGJApvrFTk2iNkshy-NLsjlzJg2ntVbxZkoz-rdFch3Fd8Vmlgf0VxmNSK1woelx1otayGwCnE8gzAQ/contexts/actions_capability_media_response_audio" }, { "name": "projects/df-surface-caps-kohler/agent/sessions/ABwppHG7pYytu-kJGJApvrFTk2iNkshy-NLsjlzJg2ntVbxZkoz-rdFch3Fd8Vmlgf0VxmNSK1woelx1otayGwCnE8gzAQ/contexts/actions_capability_audio_output" }, { "name": "projects/df-surface-caps-kohler/agent/sessions/ABwppHG7pYytu-kJGJApvrFTk2iNkshy-NLsjlzJg2ntVbxZkoz-rdFch3Fd8Vmlgf0VxmNSK1woelx1otayGwCnE8gzAQ/contexts/actions_capability_account_linking" }, { "name": "projects/df-surface-caps-kohler/agent/sessions/ABwppHG7pYytu-kJGJApvrFTk2iNkshy-NLsjlzJg2ntVbxZkoz-rdFch3Fd8Vmlgf0VxmNSK1woelx1otayGwCnE8gzAQ/contexts/actions_capability_web_browser" }, { "name": "projects/df-surface-caps-kohler/agent/sessions/ABwppHG7pYytu-kJGJApvrFTk2iNkshy-NLsjlzJg2ntVbxZkoz-rdFch3Fd8Vmlgf0VxmNSK1woelx1otayGwCnE8gzAQ/contexts/actions_capability_screen_output" }, { "name": "projects/df-surface-caps-kohler/agent/sessions/ABwppHG7pYytu-kJGJApvrFTk2iNkshy-NLsjlzJg2ntVbxZkoz-rdFch3Fd8Vmlgf0VxmNSK1woelx1otayGwCnE8gzAQ/contexts/google_assistant_input_type_touch" } ], "intent": { "name": "projects/df-surface-caps-kohler/agent/intents/4e191eef-ba17-4f68-8a97-85a43cbc9ed1", "displayName": "Current Capabilities" }, "intentDetectionConfidence": 1, "languageCode": "en" }, "originalDetectIntentRequest": { "source": "google", "version": "2", "payload": { "user": { "locale": "en-US", "userVerificationStatus": "VERIFIED" }, "conversation": { "conversationId": "ABwppHG7pYytu-kJGJApvrFTk2iNkshy-NLsjlzJg2ntVbxZkoz-rdFch3Fd8Vmlgf0VxmNSK1woelx1otayGwCnE8gzAQ", "type": "ACTIVE", "conversationToken": "[]" }, "inputs": [ { "intent": "actions.intent.TEXT", "rawInputs": [ { "inputType": "TOUCH", "query": "Current capabilities" } ], "arguments": [ { "name": "text", "rawText": "Current capabilities", "textValue": "Current capabilities" } ] } ], "surface": { "capabilities": [ { "name": "actions.capability.MEDIA_RESPONSE_AUDIO" }, { "name": "actions.capability.AUDIO_OUTPUT" }, { "name": "actions.capability.ACCOUNT_LINKING" }, { "name": "actions.capability.WEB_BROWSER" }, { "name": "actions.capability.SCREEN_OUTPUT" } ] }, "availableSurfaces": [ { "capabilities": [ { "name": "actions.capability.AUDIO_OUTPUT" }, { "name": "actions.capability.SCREEN_OUTPUT" }, { "name": "actions.capability.WEB_BROWSER" } ] } ] } }, "session": "projects/df-surface-caps-kohler/agent/sessions/ABwppHG7pYytu-kJGJApvrFTk2iNkshy-NLsjlzJg2ntVbxZkoz-rdFch3Fd8Vmlgf0VxmNSK1woelx1otayGwCnE8gzAQ" }
JSON
请注意,下面的 JSON 描述的是 webhook 请求。
{ "user": { "locale": "en-US", "userVerificationStatus": "VERIFIED" }, "conversation": { "conversationId": "ABwppHENuB8dw7LgVquXnW5Bmy9hwu1Qz4bsaL7uIb9vDSBYPAFhFgsMWnMV6m4JEDgaUWz9FUVuIhQqWh1KZ_jjTwKEIlza", "type": "NEW" }, "inputs": [ { "intent": "actions.intent.TEXT", "rawInputs": [ { "inputType": "TOUCH", "query": "Current capabilities" } ], "arguments": [ { "name": "text", "rawText": "Current capabilities", "textValue": "Current capabilities" } ] } ], "surface": { "capabilities": [ { "name": "actions.capability.MEDIA_RESPONSE_AUDIO" }, { "name": "actions.capability.SCREEN_OUTPUT" }, { "name": "actions.capability.WEB_BROWSER" }, { "name": "actions.capability.ACCOUNT_LINKING" }, { "name": "actions.capability.AUDIO_OUTPUT" } ] }, "availableSurfaces": [ { "capabilities": [ { "name": "actions.capability.WEB_BROWSER" }, { "name": "actions.capability.AUDIO_OUTPUT" }, { "name": "actions.capability.SCREEN_OUTPUT" } ] } ] }
对话分支
您可以将 Dialogflow intent 设置为仅在使用 预定义的 Dialogflow 上下文。每次匹配意图时,Dialogflow 根据设备自带的一组 Surface 功能自动生成上下文, 可用。您可以将其中一个或多个上下文指定为“输入上下文” 对 intent 进行初始化。这样,您就可以根据模态控制 intent 触发。
例如,如果您只想在具有屏幕输出的设备上触发 intent,
您可以将 intent 上的输入上下文设置为 actions_capability_screen_output
。
可用的上下文如下:
actions_capability_audio_output
- 设备配有扬声器。actions_capability_screen_output
- 设备具有输出显示屏幕。actions_capability_media_response_audio
- 设备支持播放媒体内容。actions_capability_web_browser
- 设备支持网络浏览器。( 该功能目前不适用于智能显示屏)。
以下示例展示了一个只会在带有屏幕的 surface 上触发的 intent:
多平台对话
在 Action 流程期间,您可以随时检查用户是否有任何其他 具有特定功能的平台如果其他平台 功能可用,您便可将当前 转移到这个新的平台
Surface 转移流程的工作原理如下:
- 检查用户是否有可用的界面
在网络钩子处理程序中,您可以查询用户是否具有 Surface 具有特定 capability 的可用资源。请注意,此表面必须与 所用的 Google 账号与来源平台相同。
Node.js
const screenAvailable = conv.available.surfaces.capabilities.has( 'actions.capability.SCREEN_OUTPUT');
Java
String screen = Capability.SCREEN_OUTPUT.getValue(); boolean screenAvailable = false; for (Surface surface : request.getAvailableSurfaces()) { for (com.google.api.services.actions_fulfillment.v2.model.Capability capability : surface.getCapabilities()) { if (capability.getName().equals(screen)) { screenAvailable = true; break; } } }
Node.js
const screenAvailable = conv.available.surfaces.capabilities.has( 'actions.capability.SCREEN_OUTPUT');
Java
String screen = Capability.SCREEN_OUTPUT.getValue(); boolean screenAvailable = false; for (Surface surface : request.getAvailableSurfaces()) { for (com.google.api.services.actions_fulfillment.v2.model.Capability capability : surface.getCapabilities()) { if (capability.getName().equals(screen)) { screenAvailable = true; break; } } }
JSON
请注意,下面的 JSON 描述的是 webhook 请求。
{ "responseId": "206a66fb-a572-4cfc-9e41-8e2eb62fdf18-712767ed", "queryResult": { "queryText": "Current capabilities", "parameters": {}, "allRequiredParamsPresent": true, "fulfillmentText": "Webhook failed for intent: Current Capabilities", "fulfillmentMessages": [ { "text": { "text": [ "Webhook failed for intent: Current Capabilities" ] } } ], "outputContexts": [ { "name": "projects/df-surface-caps-kohler/agent/sessions/ABwppHG7pYytu-kJGJApvrFTk2iNkshy-NLsjlzJg2ntVbxZkoz-rdFch3Fd8Vmlgf0VxmNSK1woelx1otayGwCnE8gzAQ/contexts/actions_capability_media_response_audio" }, { "name": "projects/df-surface-caps-kohler/agent/sessions/ABwppHG7pYytu-kJGJApvrFTk2iNkshy-NLsjlzJg2ntVbxZkoz-rdFch3Fd8Vmlgf0VxmNSK1woelx1otayGwCnE8gzAQ/contexts/actions_capability_audio_output" }, { "name": "projects/df-surface-caps-kohler/agent/sessions/ABwppHG7pYytu-kJGJApvrFTk2iNkshy-NLsjlzJg2ntVbxZkoz-rdFch3Fd8Vmlgf0VxmNSK1woelx1otayGwCnE8gzAQ/contexts/actions_capability_account_linking" }, { "name": "projects/df-surface-caps-kohler/agent/sessions/ABwppHG7pYytu-kJGJApvrFTk2iNkshy-NLsjlzJg2ntVbxZkoz-rdFch3Fd8Vmlgf0VxmNSK1woelx1otayGwCnE8gzAQ/contexts/actions_capability_web_browser" }, { "name": "projects/df-surface-caps-kohler/agent/sessions/ABwppHG7pYytu-kJGJApvrFTk2iNkshy-NLsjlzJg2ntVbxZkoz-rdFch3Fd8Vmlgf0VxmNSK1woelx1otayGwCnE8gzAQ/contexts/actions_capability_screen_output" }, { "name": "projects/df-surface-caps-kohler/agent/sessions/ABwppHG7pYytu-kJGJApvrFTk2iNkshy-NLsjlzJg2ntVbxZkoz-rdFch3Fd8Vmlgf0VxmNSK1woelx1otayGwCnE8gzAQ/contexts/google_assistant_input_type_touch" } ], "intent": { "name": "projects/df-surface-caps-kohler/agent/intents/4e191eef-ba17-4f68-8a97-85a43cbc9ed1", "displayName": "Current Capabilities" }, "intentDetectionConfidence": 1, "languageCode": "en" }, "originalDetectIntentRequest": { "source": "google", "version": "2", "payload": { "user": { "locale": "en-US", "userVerificationStatus": "VERIFIED" }, "conversation": { "conversationId": "ABwppHG7pYytu-kJGJApvrFTk2iNkshy-NLsjlzJg2ntVbxZkoz-rdFch3Fd8Vmlgf0VxmNSK1woelx1otayGwCnE8gzAQ", "type": "ACTIVE", "conversationToken": "[]" }, "inputs": [ { "intent": "actions.intent.TEXT", "rawInputs": [ { "inputType": "TOUCH", "query": "Current capabilities" } ], "arguments": [ { "name": "text", "rawText": "Current capabilities", "textValue": "Current capabilities" } ] } ], "surface": { "capabilities": [ { "name": "actions.capability.MEDIA_RESPONSE_AUDIO" }, { "name": "actions.capability.AUDIO_OUTPUT" }, { "name": "actions.capability.ACCOUNT_LINKING" }, { "name": "actions.capability.WEB_BROWSER" }, { "name": "actions.capability.SCREEN_OUTPUT" } ] }, "availableSurfaces": [ { "capabilities": [ { "name": "actions.capability.AUDIO_OUTPUT" }, { "name": "actions.capability.SCREEN_OUTPUT" }, { "name": "actions.capability.WEB_BROWSER" } ] } ] } }, "session": "projects/df-surface-caps-kohler/agent/sessions/ABwppHG7pYytu-kJGJApvrFTk2iNkshy-NLsjlzJg2ntVbxZkoz-rdFch3Fd8Vmlgf0VxmNSK1woelx1otayGwCnE8gzAQ" }
JSON
请注意,下面的 JSON 描述的是 webhook 请求。
{ "user": { "locale": "en-US", "userVerificationStatus": "VERIFIED" }, "conversation": { "conversationId": "ABwppHENuB8dw7LgVquXnW5Bmy9hwu1Qz4bsaL7uIb9vDSBYPAFhFgsMWnMV6m4JEDgaUWz9FUVuIhQqWh1KZ_jjTwKEIlza", "type": "NEW" }, "inputs": [ { "intent": "actions.intent.TEXT", "rawInputs": [ { "inputType": "TOUCH", "query": "Current capabilities" } ], "arguments": [ { "name": "text", "rawText": "Current capabilities", "textValue": "Current capabilities" } ] } ], "surface": { "capabilities": [ { "name": "actions.capability.MEDIA_RESPONSE_AUDIO" }, { "name": "actions.capability.SCREEN_OUTPUT" }, { "name": "actions.capability.WEB_BROWSER" }, { "name": "actions.capability.ACCOUNT_LINKING" }, { "name": "actions.capability.AUDIO_OUTPUT" } ] }, "availableSurfaces": [ { "capabilities": [ { "name": "actions.capability.WEB_BROWSER" }, { "name": "actions.capability.AUDIO_OUTPUT" }, { "name": "actions.capability.SCREEN_OUTPUT" } ] } ] }
- 请求将用户转移到新 surface
如果有具有所需功能的可用 surface,您的 Action 将 需要询问用户是否要转移对话。
Node.js
if (conv.screen) { conv.ask(`You're already on a screen device.`); conv.ask('What else would you like to try?'); conv.ask(new Suggestions([ 'Current Capabilities', 'Check Audio Capability', 'Check Screen Capability', 'Check Media Capability', 'Check Web Capability', ])); return; } else if (screenAvailable) { const context = `Let's move you to a screen device for cards and other visual responses`; const notification = 'Try your Action here!'; const capabilities = ['actions.capability.SCREEN_OUTPUT']; return conv.ask(new NewSurface({context, notification, capabilities})); } else { conv.ask('It looks like there is no screen device ' + 'associated with this user.'); conv.ask('What else would you like to try?'); conv.ask(new Suggestions([ 'Current Capabilities', 'Check Audio Capability', 'Check Screen Capability', 'Check Media Capability', 'Check Web Capability', ])); };
Java
ResponseBuilder responseBuilder = getResponseBuilder(request); if (request.hasCapability(Capability.SCREEN_OUTPUT.getValue())) { responseBuilder.add("You're already on a screen device"); responseBuilder.add("What else would you like to try?"); responseBuilder.addSuggestions( new String[] { "Transfer surface", "Check Audio Capability", "Check Screen Capability", "Check Media Capability", "Check Web Capability", }); return responseBuilder.build(); } else if (screenAvailable) { responseBuilder.add( new NewSurface() .setContext("Let's move you to a screen device for cards and other visual responses") .setNotificationTitle("Try your Action here!") .setCapabilities(Collections.singletonList(screen))); return responseBuilder.build(); } else { responseBuilder.add("It looks like there is no screen device associated with this user."); responseBuilder.add("What else would you like to try?"); responseBuilder.addSuggestions( new String[] { "Transfer surface", "Check Audio Capability", "Check Screen Capability", "Check Media Capability", "Check Web Capability", }); return responseBuilder.build(); }
Node.js
if (conv.screen) { conv.ask(`You're already on a screen device.`); conv.ask('What else would you like to try?'); conv.ask(new Suggestions([ 'Transfer surface', 'Current capabilities', ])); return; } else if (screenAvailable) { const context = `Let's move you to a screen device for cards and other visual responses`; const notification = 'Try your Action here!'; const capabilities = ['actions.capability.SCREEN_OUTPUT']; return conv.ask(new NewSurface({context, notification, capabilities})); } else { conv.ask('It looks like there is no screen device ' + 'associated with this user.'); conv.ask('What else would you like to try?'); conv.ask(new Suggestions([ 'Transfer surface', 'Current capabilities', ])); };
Java
ResponseBuilder responseBuilder = getResponseBuilder(request); if (request.hasCapability(Capability.SCREEN_OUTPUT.getValue())) { responseBuilder.add("You're already on a screen device"); responseBuilder.add("What else would you like to try?"); responseBuilder.addSuggestions( new String[] { "Current capabilities", "Transfer surface", }); return responseBuilder.build(); } else if (screenAvailable) { responseBuilder.add( new NewSurface() .setContext("Let's move you to a screen device for cards and other visual responses") .setNotificationTitle("Try your Action here!") .setCapabilities(Collections.singletonList(screen))); return responseBuilder.build(); } else { responseBuilder.add("It looks like there is no screen device associated with this user."); responseBuilder.add("What else would you like to try?"); responseBuilder.addSuggestions( new String[] { "Current capabilities", "Transfer surface", }); return responseBuilder.build(); }
JSON
请注意,下面的 JSON 描述的是 webhook 响应。
{ "payload": { "google": { "expectUserResponse": true, "systemIntent": { "intent": "actions.intent.NEW_SURFACE", "data": { "@type": "type.googleapis.com/google.actions.v2.NewSurfaceValueSpec", "capabilities": [ "actions.capability.SCREEN_OUTPUT" ], "context": "Let's move you to a screen device for cards and other visual responses", "notificationTitle": "Try your Action here!" } } } } }
JSON
请注意,下面的 JSON 描述的是 webhook 响应。
{ "expectUserResponse": true, "expectedInputs": [ { "possibleIntents": [ { "intent": "actions.intent.NEW_SURFACE", "inputValueData": { "@type": "type.googleapis.com/google.actions.v2.NewSurfaceValueSpec", "capabilities": [ "actions.capability.SCREEN_OUTPUT" ], "context": "Let's move you to a screen device for cards and other visual responses", "notificationTitle": "Try your Action here!" } } ] } ] }
- 处理用户的响应
根据用户对您的请求做出的响应,您的 Action 会提供 将对话的控制权移交或交回给原始 surface。 无论采用哪种方式,向端点发送的下一个请求都会包含
actions.intent.NEW_SURFACE
因此您应使用 相应的处理程序。在处理程序代码中,您应该 检查转移是否成功。Node.js
app.intent('Transfer Surface - NEW_SURFACE', (conv, input, newSurface) => { if (newSurface.status === 'OK') { conv.ask('Welcome to a screen device!'); conv.ask(new BasicCard({ title: `You're on a screen device!`, text: `Screen devices support basic cards and other visual responses!`, })); } else { conv.ask(`Ok, no problem.`); } conv.ask('What else would you like to try?'); conv.ask(new Suggestions([ 'Current Capabilities', 'Check Audio Capability', 'Check Screen Capability', 'Check Media Capability', 'Check Web Capability', ])); });
Java
@ForIntent("Transfer Surface - NEW_SURFACE") public ActionResponse newSurface(ActionRequest request) { ResponseBuilder responseBuilder = getResponseBuilder(request); Map<String, Object> newSurfaceStatus = request.getArgument("NEW_SURFACE").getExtension(); if (newSurfaceStatus.get("status").equals("OK")) { responseBuilder.add("Welcome to a screen device!"); responseBuilder.add( new BasicCard() .setTitle("You're on a screened device!") .setFormattedText("Screen devices support basic cards and other visual responses!")); } else { responseBuilder.add("Ok, no problem."); } responseBuilder.add("What else would you like to try?"); responseBuilder.addSuggestions( new String[] { "Transfer surface", "Check Audio Capability", "Check Screen Capability", "Check Media Capability", "Check Web Capability", }); return responseBuilder.build(); }
Node.js
app.intent('actions.intent.NEW_SURFACE', (conv) => { if (conv.arguments.get('NEW_SURFACE').status === 'OK') { conv.ask('Welcome to a screen device!'); conv.ask(new BasicCard({ title: `You're on a screen device!`, text: `Screen devices support basic cards and other visual responses!`, })); } else { conv.ask(`Ok, no problem.`); } conv.ask('What else would you like to try?'); conv.ask(new Suggestions([ 'Transfer surface', 'Current capabilities', ])); });
Java
@ForIntent("actions.intent.NEW_SURFACE") public ActionResponse newSurface(ActionRequest request) { ResponseBuilder responseBuilder = getResponseBuilder(request); Map<String, Object> newSurfaceStatus = request.getArgument("NEW_SURFACE").getExtension(); if (newSurfaceStatus.get("status").equals("OK")) { responseBuilder.add("Welcome to a screen device!"); responseBuilder.add( new BasicCard() .setTitle("You're on a screened device!") .setFormattedText("Screen devices support basic cards and other visual responses!")); } else { responseBuilder.add("Ok, no problem."); } responseBuilder.add("What else would you like to try?"); responseBuilder.addSuggestions( new String[] { "Current capabilities", "Transfer surface", }); return responseBuilder.build(); }
JSON
请注意,下面的 JSON 描述的是 webhook 请求。
{ "responseId": "94b74485-cd7a-4b3b-b96a-fec15f3a496c-712767ed", "queryResult": { "queryText": "actions_intent_NEW_SURFACE", "parameters": {}, "allRequiredParamsPresent": true, "fulfillmentText": "Webhook failed for intent: Transfer Surface - NEW_SURFACE", "fulfillmentMessages": [ { "text": { "text": [ "Webhook failed for intent: Transfer Surface - NEW_SURFACE" ] } } ], "outputContexts": [ { "name": "projects/df-surface-caps-kohler/agent/sessions/ABwppHEfQy-JgH7nmiW5gHWiDEyvqNRSPv9zkd3qTVF7F8G8YXJFI2_yal335Co0Z-_N5oUBTmVO_DJUlQONqd5lUgZz-Q/contexts/actions_capability_screen_output" }, { "name": "projects/df-surface-caps-kohler/agent/sessions/ABwppHEfQy-JgH7nmiW5gHWiDEyvqNRSPv9zkd3qTVF7F8G8YXJFI2_yal335Co0Z-_N5oUBTmVO_DJUlQONqd5lUgZz-Q/contexts/actions_capability_web_browser" }, { "name": "projects/df-surface-caps-kohler/agent/sessions/ABwppHEfQy-JgH7nmiW5gHWiDEyvqNRSPv9zkd3qTVF7F8G8YXJFI2_yal335Co0Z-_N5oUBTmVO_DJUlQONqd5lUgZz-Q/contexts/actions_capability_audio_output" }, { "name": "projects/df-surface-caps-kohler/agent/sessions/ABwppHEfQy-JgH7nmiW5gHWiDEyvqNRSPv9zkd3qTVF7F8G8YXJFI2_yal335Co0Z-_N5oUBTmVO_DJUlQONqd5lUgZz-Q/contexts/actions_capability_media_response_audio" }, { "name": "projects/df-surface-caps-kohler/agent/sessions/ABwppHEfQy-JgH7nmiW5gHWiDEyvqNRSPv9zkd3qTVF7F8G8YXJFI2_yal335Co0Z-_N5oUBTmVO_DJUlQONqd5lUgZz-Q/contexts/actions_capability_account_linking" }, { "name": "projects/df-surface-caps-kohler/agent/sessions/ABwppHEfQy-JgH7nmiW5gHWiDEyvqNRSPv9zkd3qTVF7F8G8YXJFI2_yal335Co0Z-_N5oUBTmVO_DJUlQONqd5lUgZz-Q/contexts/google_assistant_input_type_voice" }, { "name": "projects/df-surface-caps-kohler/agent/sessions/ABwppHEfQy-JgH7nmiW5gHWiDEyvqNRSPv9zkd3qTVF7F8G8YXJFI2_yal335Co0Z-_N5oUBTmVO_DJUlQONqd5lUgZz-Q/contexts/actions_intent_new_surface", "parameters": { "NEW_SURFACE": { "@type": "type.googleapis.com/google.actions.v2.NewSurfaceValue", "status": "OK" }, "text": "" } } ], "intent": { "name": "projects/df-surface-caps-kohler/agent/intents/9db3798d-bdac-4dc8-a8e7-52349a3af0e8", "displayName": "Transfer Surface - NEW_SURFACE" }, "intentDetectionConfidence": 1, "languageCode": "en" }, "originalDetectIntentRequest": { "source": "google", "version": "2", "payload": { "user": { "locale": "en-US", "userVerificationStatus": "VERIFIED" }, "conversation": { "conversationId": "ABwppHEfQy-JgH7nmiW5gHWiDEyvqNRSPv9zkd3qTVF7F8G8YXJFI2_yal335Co0Z-_N5oUBTmVO_DJUlQONqd5lUgZz-Q", "type": "ACTIVE", "conversationToken": "[]" }, "inputs": [ { "intent": "actions.intent.NEW_SURFACE", "rawInputs": [ { "inputType": "VOICE" } ], "arguments": [ { "name": "NEW_SURFACE", "extension": { "@type": "type.googleapis.com/google.actions.v2.NewSurfaceValue", "status": "OK" } }, { "name": "text" } ] } ], "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" } ] }, "availableSurfaces": [ { "capabilities": [ { "name": "actions.capability.SCREEN_OUTPUT" }, { "name": "actions.capability.WEB_BROWSER" }, { "name": "actions.capability.AUDIO_OUTPUT" } ] } ] } }, "session": "projects/df-surface-caps-kohler/agent/sessions/ABwppHEfQy-JgH7nmiW5gHWiDEyvqNRSPv9zkd3qTVF7F8G8YXJFI2_yal335Co0Z-_N5oUBTmVO_DJUlQONqd5lUgZz-Q" }
JSON
请注意,下面的 JSON 描述的是 webhook 请求。
{ "user": { "locale": "en-US", "userVerificationStatus": "VERIFIED" }, "conversation": { "conversationId": "ABwppHENAOzBH5swn9iKb5QgUliTw4JLu5f86gS373tGtNvYcz1C3qHdorjcIb77o_PUleXGzIEFdPsl3-kmIAARvx67A7Ym", "type": "NEW" }, "inputs": [ { "intent": "actions.intent.NEW_SURFACE", "rawInputs": [ { "inputType": "VOICE" } ], "arguments": [ { "name": "NEW_SURFACE", "extension": { "@type": "type.googleapis.com/google.actions.v2.NewSurfaceValue", "status": "OK" } }, { "name": "text" } ] } ], "surface": { "capabilities": [ { "name": "actions.capability.SCREEN_OUTPUT" }, { "name": "actions.capability.ACCOUNT_LINKING" }, { "name": "actions.capability.MEDIA_RESPONSE_AUDIO" }, { "name": "actions.capability.AUDIO_OUTPUT" }, { "name": "actions.capability.WEB_BROWSER" } ] }, "availableSurfaces": [ { "capabilities": [ { "name": "actions.capability.WEB_BROWSER" }, { "name": "actions.capability.AUDIO_OUTPUT" }, { "name": "actions.capability.SCREEN_OUTPUT" } ] } ] }