在 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 手机) 功能:
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');
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");
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');
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 描述的是 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 描述的是 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 账号与来源平台相同。
const screenAvailable =
conv.available.surfaces.capabilities.has(
'actions.capability.SCREEN_OUTPUT');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;
}
}
}const screenAvailable =
conv.available.surfaces.capabilities.has(
'actions.capability.SCREEN_OUTPUT');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 描述的是 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 描述的是 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 将 需要询问用户是否要转移对话。
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',
]));
};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();
}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',
]));
};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 描述的是 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 描述的是 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
因此您应使用 相应的处理程序。在处理程序代码中,您应该 检查转移是否成功。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',
]));
});@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();
}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',
]));
});@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 描述的是 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 描述的是 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"
}
]
}
]
}