Dialogflow에서 살펴보기
계속을 클릭하여 Dialogflow에서 응답 샘플을 가져옵니다. 그런 다음 다음 단계에 따라 샘플을 배포하고 테스트합니다.
- 에이전트 이름을 입력하고 샘플의 새 Dialogflow 에이전트를 만듭니다.
- 에이전트 가져오기가 완료되면 Go to agent를 클릭합니다.
- 기본 탐색 메뉴에서 fulfillment로 이동합니다.
- 인라인 편집기를 사용 설정한 다음 배포를 클릭합니다. 편집기에 샘플 파일이 포함되어 있고 있습니다.
- 기본 탐색 메뉴에서 Integrations로 이동한 다음 Google을 클릭합니다. 어시스턴트를 탭합니다.
- 모달 창이 나타나면 변경사항 자동 미리보기를 사용 설정하고 테스트를 클릭합니다. 작업 시뮬레이터를 엽니다.
- 시뮬레이터에서
Talk to my test app
를 입력하여 샘플을 테스트합니다.
시각적 요소를 표시하여 사용자를 향상시키려면 풍부한 응답을 사용합니다. 확인할 수 있습니다. 이러한 시각적 요소를 통해 대화를 이어갈 수 있습니다.
다양한 응답은 화면 전용 또는 오디오 및 화면 환경에 표시될 수 있습니다. 그들은 다음 구성요소를 포함할 수 있습니다.
대화 디자인 가이드라인을 검토하여 작업에 이러한 시각적 요소를 통합하는 방법을 알아보세요.
속성
리치 응답에는 다음과 같은 요구사항이 있으며 선택 사항이 있습니다. 다음과 같은 속성을 지정할 수 있습니다.
actions.capability.SCREEN_OUTPUT
기능이 있는 노출 영역에서 지원됩니다.- 리치 응답의 첫 번째 항목은 단순 응답이어야 합니다.
- 간단한 응답 최대 2개
- 기본 카드 또는
StructuredResponse
는 최대 1개입니다. - 추천 칩은 최대 8개입니다.
FinalResponse
에서는 추천 칩이 허용되지 않습니다.- 스마트 디스플레이에서 웹으로 연결하는 기능은 현재 지원되지 않습니다.
다음 섹션에서는 다양한 유형의 리치 응답을 작성하는 방법을 보여줍니다.
기본 카드
를 통해 개인정보처리방침을 정의할 수 있습니다. <ph type="x-smartling-placeholder">![](https://developers-dot-devsite-v2-prod.appspot.com/static/assistant/conversational/images/basic-card.png?authuser=9&hl=ko)
기본 카드에는 다음과 같은 정보가 표시됩니다.
- 이미지
- 제목
- 부제목
- 텍스트 본문
- 연결 버튼
- 테두리
기본적인 카드는 주로 디스플레이용으로 사용합니다. API는 간결하게 설계되었지만 주요 (또는 요약) 정보를 사용자에게 제공하고 사용자가 원하는 경우 웹링크를 사용하여 추가할 수도 있습니다
대부분의 경우 아래에 추천 칩을 추가해야 합니다. 카드를 사용하여 대화를 계속하거나 방향을 전환할 수 있습니다.
채팅 풍선에서 카드에 표시된 정보를 반복하지 않습니다. 얻을 수 있습니다.
속성
기본 카드 응답 유형에는 다음과 같은 요구사항 및 선택사항이 있습니다. 다음과 같은 속성을 지정할 수 있습니다.
actions.capability.SCREEN_OUTPUT
기능이 있는 노출 영역에서 지원됩니다.- 서식이 지정된 텍스트(이미지가 없는 경우 필수)
<ph type="x-smartling-placeholder">
- </ph>
- 기본적으로 일반 텍스트입니다.
- 링크를 포함해서는 안 됩니다.
- 이미지가 있는 경우 10줄, 이미지가 없는 경우 15줄로 제한됩니다. 이 내용은 500자 (이미지 포함) 또는 750자 (이미지 제외) 소형 화면 휴대전화 큰 화면의 휴대전화보다 텍스트도 잘립니다. 다음 단어가 포함된 경우: 많은 행이 있는 경우 마지막 단어 구분에서 생략 부호로 잘립니다.
- 마크다운의 제한된 하위 집합이 지원됩니다.
<ph type="x-smartling-placeholder">
- </ph>
- 이중 공백이 있고 그 뒤에 오는 새 줄 \n
**bold**
*italics*
- 이미지(서식이 지정된 텍스트가 없는 경우 필수)
<ph type="x-smartling-placeholder">
- </ph>
- 모든 이미지의 높이는 192dp가 되어야 합니다.
- 이미지의 가로세로 비율이 화면과 다르면 가로 또는 세로 가장자리에 회색 막대가 있는 중앙 배치
- 이미지 소스가 URL입니다.
- 모션 GIF를 사용할 수 있습니다.
선택사항
- 제목
- 일반 텍스트
- 고정된 글꼴 및 크기
- 최대 1줄, 초과 문자는 잘립니다.
- 제목을 지정하지 않으면 카드 높이가 접힙니다.
- 부제목
<ph type="x-smartling-placeholder">
- </ph>
- 일반 텍스트
- 고정된 글꼴 및 글꼴 크기입니다.
- 최대 1줄, 초과 문자는 잘립니다.
- 부제목을 지정하지 않으면 카드 높이가 접힙니다.
- 링크 버튼
<ph type="x-smartling-placeholder">
- </ph>
- 링크 제목은 필수 항목입니다.
- 최대 1개의 링크
- 개발자 도메인 외부 사이트로 연결되는 링크는 허용됩니다.
- 링크 텍스트는 오해의 소지가 없어야 합니다. 이는 승인 과정에서 확인됩니다.
- 기본 카드에는 링크가 없으면 상호작용 기능이 없습니다. 탭하는 중 링크는 사용자를 링크로 보내는 반면 비활성 상태로 유지됩니다
- 테두리
<ph type="x-smartling-placeholder">
- </ph>
- 카드와 이미지 컨테이너 사이의 테두리는 기본 카드의 프레젠테이션을 맞춤설정하세요.
- JSON 문자열 속성을 설정하여 구성됨
imageDisplayOptions
드림
![](https://developers-dot-devsite-v2-prod.appspot.com/static/assistant/conversational/images/smart-display/basic-card.png?authuser=9&hl=ko)
샘플 코드
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?'); });
자바
@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?');
자바
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은 웹훅 응답을 설명합니다.
{ "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은 웹훅 응답을 설명합니다.
{ "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?" } } ] } } } ] }
캐러셀 둘러보기
를 통해 개인정보처리방침을 정의할 수 있습니다. <ph type="x-smartling-placeholder">![](https://developers-dot-devsite-v2-prod.appspot.com/static/assistant/conversational/images/browse-carousel.png?authuser=9&hl=ko)
탐색 캐러셀은 사용자가 세로로 스크롤할 수 있는 풍부한 응답입니다. 컬렉션에서 타일을 선택합니다. 캐러셀은 웹 페이지의 콘텐츠를 웹브라우저 (또는 AMP 브라우저)에서 선택한 타일을 열어 (모든 타일이 AMP를 사용하는 경우) 또한 탐색 캐러셀은 사용자의 어시스턴트 표면에 표시됩니다.
속성
탐색 캐러셀 응답 유형에는 다음과 같은 요구사항이 있으며 선택사항입니다. 다음과 같은 속성을 지정할 수 있습니다.
actions.capability.SCREEN_OUTPUT
가 모두 있는 노출 영역에서 지원됨 및actions.capability.WEB_BROWSER
기능. 이 응답 유형: 현재 스마트 디스플레이에서 사용할 수 없습니다- 캐러셀 둘러보기
<ph type="x-smartling-placeholder">
- </ph>
- 최대 10개의 타일이 허용됩니다.
- 타일은 2개 이상이어야 합니다.
- 캐러셀의 타일은 모두 웹 콘텐츠 (AMP 콘텐츠)로 연결되어야 합니다.
권장).
- 사용자가 AMP 뷰어로 이동하려면
urlHintType
'AMP_CONTENT'로 설정해야 합니다.
- 사용자가 AMP 뷰어로 이동하려면
- 캐러셀 타일 탐색
<ph type="x-smartling-placeholder">
- </ph>
- 타일 일관성 (필수):
<ph type="x-smartling-placeholder">
- </ph>
- 탐색 캐러셀의 모든 타일에는 동일한 구성요소가 있어야 합니다. 예를 들어 한 타일에 이미지 필드가 있으면 나머지 타일은 이미지 필드도 있어야 합니다
- 탐색 캐러셀의 모든 타일이 AMP 사용 콘텐츠로 연결되는 경우 사용자는 추가 기능이 있는 AMP 브라우저로 이동합니다. 타일이 AMP가 아닌 콘텐츠로 연결되는 경우 모든 타일이 사용자를 안내함 웹브라우저로 복사하는 거죠.
- 이미지(선택사항)
<ph type="x-smartling-placeholder">
- </ph>
- 이미지가 세로 128dp, 너비 232dp가 되도록 강제됩니다.
- 이미지의 가로세로 비율이 이미지 경계 상자와 일치하지 않으면 이미지가 양쪽에 막대로 중앙에 배치됩니다. 스마트폰에서는 이미지가 둥근 모서리의 정사각형 안에 있습니다.
- 이미지 링크가 깨지면 자리표시자 이미지가 대신 사용됩니다.
- 이미지에 대체 텍스트가 필요합니다.
- 제목 (필수 항목)
<ph type="x-smartling-placeholder">
- </ph>
- 기본 텍스트 카드와 동일한 서식 지정 옵션이 제공됩니다.
- 제목은 고유해야 합니다 (음성 선택을 지원할 수 있도록).
- 텍스트는 최대 2줄입니다.
- 글꼴 크기 16sp.
- 설명(선택사항)
<ph type="x-smartling-placeholder">
- </ph>
- 기본 텍스트 카드와 동일한 서식 지정 옵션이 제공됩니다.
- 텍스트는 최대 4줄까지 허용됩니다.
- 생략 부호로 잘림 (...)
- 글꼴 크기: 14sp, 회색.
- 바닥글(선택사항)
<ph type="x-smartling-placeholder">
- </ph>
- 고정된 글꼴 및 글꼴 크기입니다.
- 텍스트는 최대 1줄입니다.
- 생략 부호로 잘림 (...)
- 하단에 고정되므로 본문 텍스트가 적은 타일은 하위 텍스트 위에 공백이 있습니다.
- 글꼴 크기: 14sp, 회색.
- 타일 일관성 (필수):
<ph type="x-smartling-placeholder">
- 상호작용
<ph type="x-smartling-placeholder">
- </ph>
- 사용자는 세로로 스크롤하여 항목을 볼 수 있습니다.
- 탭 카드: 항목을 탭하면 사용자가 브라우저로 이동하여 링크된 페이지
- 음성 입력
<ph type="x-smartling-placeholder">
- </ph>
- 마이크 동작
<ph type="x-smartling-placeholder">
- </ph>
- 사용자에게 탐색 캐러셀이 전송될 때 마이크가 다시 열리지 않습니다.
- 사용자는 계속해서 마이크를 탭하거나 어시스턴트("Hey Google")를 호출할 수 있습니다. 마이크를 다시 엽니다.
- 마이크 동작
<ph type="x-smartling-placeholder">
안내
기본적으로 마이크는 탐색 캐러셀이 전송된 후에도 닫힌 상태로 유지됩니다. 원하는 경우 추후에 대화를 계속하려면 추천 칩을 추가하는 것이 좋습니다. 를 클릭합니다.
목록에 표시된 옵션을 추천 검색어 칩으로 반복하지 않습니다. 칩 인 이 컨텍스트는 대화를 피벗하는 데 사용됩니다 (선택 항목 선택용이 아님).
목록과 마찬가지로 캐러셀 카드에 표시되는 채팅 풍선은 오디오의 하위 집합 (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', }), ], })); });
자바
@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', }), ], }));
자바
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은 웹훅 응답을 설명합니다.
{ "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은 웹훅 응답을 설명합니다.
{ "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" } ] } ] }
선택한 상품 처리 중
탐색 캐러셀과의 사용자 상호작용에는 후속 처리가 필요하지 않습니다. 캐러셀이 브라우저 핸드오프를 처리하기 때문입니다. 마이크는 사용자가 탐색 캐러셀 항목과 상호작용한 후에는 다시 열리지 않으므로 덧붙이자면 추천 칩을 만듭니다.
추천 칩
를 통해 개인정보처리방침을 정의할 수 있습니다. <ph type="x-smartling-placeholder">![](https://developers-dot-devsite-v2-prod.appspot.com/static/assistant/conversational/images/suggestions.png?authuser=9&hl=ko)
추천 검색어 칩을 사용하여 대답에 힌트를 줌으로써 대화를 계속하거나 방향을 전환할 수 있습니다. 대화 중에 주요 행동 촉구가 나오면 첫 번째 추천 칩에서 사용하겠습니다.
가능한 경우 채팅 중에 핵심 제안 1개를 포함하는 것이 좋습니다. 하지만 응답이나 채팅 대화가 자연스럽게 느껴지는 경우에만 그렇게 하세요.
속성
추천 칩에는 다음과 같은 요구사항 및 선택사항이 있습니다. 다음과 같은 속성을 지정할 수 있습니다.
actions.capability.SCREEN_OUTPUT
기능이 있는 노출 영역에서 지원됩니다.- 추천 검색어 칩을 웹에 연결하려면 표시 경로에도
actions.capability.WEB_BROWSER
기능. 이 기능은 현재 스마트 디스플레이에서 사용할 수 있습니다 - 칩은 최대 8개입니다.
- 최대 텍스트 길이는 25자(영문 기준)입니다.
일반 텍스트만 지원됩니다.
![](https://developers-dot-devsite-v2-prod.appspot.com/static/assistant/conversational/images/smart-display/chips.png?authuser=9&hl=ko)
샘플 코드
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?'); ; });
자바
@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?');
자바
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은 웹훅 응답을 설명합니다.
{ "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은 웹훅 응답을 설명합니다.
{ "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/" } } } } ] }
미디어 응답
를 통해 개인정보처리방침을 정의할 수 있습니다. <ph type="x-smartling-placeholder">![](https://developers-dot-devsite-v2-prod.appspot.com/static/assistant/conversational/images/media.png?authuser=9&hl=ko)
미디어 응답을 사용하면 작업에서 재생 시간이 포함된 오디오 콘텐츠를 재생할 수 있습니다. SSML의 240초 제한을 초과합니다 미디어의 기본 구성요소는 단일 트랙 카드입니다. 카드를 통해 사용자는 있습니다.
- 마지막 10초를 다시 재생합니다.
- 30초 동안 앞으로 건너뜁니다.
- 미디어 콘텐츠의 전체 길이를 확인합니다.
- 오디오 재생 진행률 표시기를 확인합니다.
- 재생 경과 시간을 확인합니다.
미디어 응답은 음성 상호작용을 위해 다음 오디오 컨트롤을 지원합니다.
- “Hey Google, 틀어 줘.”
- “Hey Google, 일시중지해 줘.”
- “Hey Google, 중지해 줘.”
- “Hey Google, 다시 시작해 줘.”
사용자는 "Hey Google, 볼륨 높여 줘"와 같이 말하여 볼륨을 조정할 수도 있습니다. 볼륨 높여 줘." 또는 "Hey Google, 볼륨 50퍼센트로 설정해 줘." 인텐트가 유사한 학습 문구를 처리하는 경우 작업이 우선 적용됩니다. 어시스턴트 허용 특별한 이유가 없다면 이러한 사용자 요청을 처리해야 합니다.
속성
미디어 응답에는 다음과 같은 요구사항 및 선택적 속성이 있습니다. 구성할 수 있습니다.
actions.capability.MEDIA_RESPONSE_AUDIO
가 있는 노출 영역에서 지원됨 배웠습니다- 재생할 오디오는 올바른 형식의
.mp3
파일이어야 합니다. 게시 중 스트리밍은 지원되지 않습니다. - 재생할 미디어 파일은 HTTPS URL로 지정해야 합니다.
- 이미지(선택사항)
<ph type="x-smartling-placeholder">
- </ph>
- 원하는 경우 아이콘이나 이미지를 포함할 수 있습니다.
- 아이콘
- 아이콘이 미디어 오른쪽에 테두리 없는 썸네일로 표시됩니다. 있습니다.
- 크기는 36 x 36dp여야 합니다. 더 큰 이미지는 크기에 맞게 크기가 조정됩니다.
- 이미지
<ph type="x-smartling-placeholder">
- </ph>
- 이미지 컨테이너의 높이는 192dp가 됩니다.
- 이미지가 미디어 플레이어 카드 상단에 표시되며 카드의 전체 너비입니다. 대부분의 이미지는 있습니다.
- 모션 GIF를 사용할 수 있습니다.
- 이미지 소스를 URL로 지정해야 합니다.
- 모든 이미지에 대체 텍스트가 필요합니다.
노출 영역의 동작
미디어 응답은 Android 휴대전화와 Google Home에서 지원됩니다. 이 사용자가 상호작용하는 표면에 따라 달라지는 미디어 응답 확인할 수 있습니다.
Android 휴대전화에서 다음 조건이 충족되면 사용자가 미디어 응답을 볼 수 있습니다. 충족됩니다.
- 포그라운드에 Google 어시스턴트가 있고 휴대전화 화면이 켜져 있습니다.
- 오디오가 재생되는 동안 사용자가 Google 어시스턴트를 나갔다가 다시 돌아오는 경우 재생 완료 후 10분 이내에 Google 어시스턴트를 통해 재생 (으)로 돌아가면 Google 어시스턴트: 사용자에게 미디어 카드와 추천 칩이 표시됩니다.
- 사용자는 어시스턴트를 통해 기기 볼륨을 제어할 수 있습니다. "볼륨 높여 줘"" 또는 "설정하기 50%로 설정합니다. 유사한 학습 문구를 처리하는 인텐트가 있는 경우 인텐트가 우선 적용됩니다 이러한 작업은 어시스턴트가 처리하도록 하는 것이 좋습니다. 사용자의 요청을 처리할 수 없습니다.
휴대전화가 잠겨 있을 때도 미디어 컨트롤을 사용할 수 있습니다. Android의 경우 알림 영역에도 표시됩니다.
<ph type="x-smartling-placeholder">![](https://developers-dot-devsite-v2-prod.appspot.com/static/assistant/conversational/images/smart-display/media.png?authuser=9&hl=ko)
샘플 코드
다음 코드 샘플은 미디어가 포함되지 않습니다.
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'])); });
자바
@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']));
자바
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은 웹훅 응답을 설명합니다.
{ "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은 웹훅 응답을 설명합니다.
{ "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
를 포함합니다. 미디어
단일 미디어 객체를 지원합니다. 미디어 객체에는 콘텐츠가 포함되어야 합니다.
오디오 파일의 URL입니다. 미디어 객체는 선택적으로 이름, 하위 텍스트
(설명), 아이콘 또는 이미지 URL을 포함할 수 있습니다.
휴대전화와 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?'); });
자바
@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?'); });
자바
@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은 웹훅 요청을 설명합니다.
{ "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은 웹훅 요청을 설명합니다.
{ "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개)을 표시합니다. 우선순위와 함께 추가 열과 행을 정의할 수도 있습니다.
표는 수직 목록과 다른 이유는 표는 정적 데이터를 표시하고 목록 요소와 같이 상호작용할 수 없습니다.
를 통해 개인정보처리방침을 정의할 수 있습니다. <ph type="x-smartling-placeholder">![](https://developers-dot-devsite-v2-prod.appspot.com/static/assistant/conversational/images/smart-display/table.png?authuser=9&hl=ko)
속성
표 카드에는 다음과 같은 요구사항 및 가능한 선택적 속성이 있습니다. 구성:
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?'); });
자바
@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?');
자바
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은 웹훅 응답을 설명합니다.
{ "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은 웹훅 응답을 설명합니다.
{ "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?'); });
자바
@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?');
자바
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은 웹훅 응답을 설명합니다.
{ "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은 웹훅 응답을 설명합니다.
{ "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 콘솔에서 개발 > 테마 맞춤설정.
- 다음 중 일부 또는 전체를 설정합니다.
<ph type="x-smartling-placeholder">
- </ph>
- 배경 색상: 카드의 배경으로 사용할 색상입니다. 포함 일반적으로 배경에 밝은 색상을 사용해야 콘텐츠를 읽기 쉽습니다.
- 기본 색상은 카드의 기본 색상입니다. 헤더 텍스트 및 UI 요소 일반적으로 대비를 위해 더 어두운 기본 색상을 사용해야 합니다. 있습니다.
- 글꼴 모음은 제목 및 기타 글꼴에 사용된 글꼴의 유형을 텍스트 요소가 눈에 잘 띄지 않습니다.
- 이미지 모서리 스타일을 변경하면 카드의 모양이 달라질 수 있습니다. 있습니다.
- 배경 이미지는 배경 대신 맞춤 이미지를 사용합니다. color[색상] 광고가 게재될 때는 2개의 다른 이미지를 노출 영역 기기가 각각 가로 모드 또는 세로 모드입니다. 참고: 배경 이미지를 사용할 경우 기본 색상은 흰색으로 설정됩니다.
- 저장을 클릭합니다.
![](https://developers-dot-devsite-v2-prod.appspot.com/static/assistant/conversational/images/theme-customization.png?authuser=9&hl=ko)