Surface 功能 (Dialogflow)

在 Dialogflow 中探索

点击继续,将我们的 Surface 功能示例导入 Dialogflow。然后,按照 部署和测试示例的步骤如下:

  1. 输入代理名称并为示例创建新的 Dialogflow 代理。
  2. 代理导入完成后,点击转到代理 (Go to agent)。
  3. 在主导航菜单中,前往 Fulfillment
  4. 启用内嵌编辑器,然后点击部署。编辑器包含示例 代码。
  5. 在主导航菜单中,前往 Integrations(集成),然后点击 Google Google 助理
  6. 在显示的模态窗口中,启用 Auto-preview changes(自动预览更改),然后点击 Test(测试) 打开 Actions 模拟器。
  7. 在模拟器中,输入 Talk to my test app 以测试该示例!
<ph type="x-smartling-placeholder"></ph> 继续

你的 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 转移流程的工作原理如下:

  1. 检查用户是否有可用的界面

    在网络钩子处理程序中,您可以查询用户是否具有 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"
           
    }
         
    ]
       
    }
     
    ]
    }
  2. 请求将用户转移到新 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!"
             
    }
           
    }
         
    ]
       
    }
     
    ]
    }
  3. 处理用户的响应

    根据用户对您的请求做出的响应,您的 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"
           
    }
         
    ]
       
    }
     
    ]
    }