建構 Google Chat 應用程式的首頁

本頁說明如何使用 Google Chat 應用程式建立即時訊息的首頁。首頁在 Google Chat API 中稱為應用程式首頁,是可自訂的資訊卡介面,會顯示在使用者與 Chat 應用程式之間即時訊息聊天室的「首頁」分頁中。

含有兩個小工具的應用程式主畫面資訊卡。
圖 1:在 Chat 應用程式中透過即時訊息顯示的首頁範例。

您可以透過應用程式首頁分享與 Chat 應用程式互動或讓使用者透過 Chat 存取及使用外部服務或工具的訣竅。


使用資訊卡建構工具設計及預覽 Chat 應用程式的訊息和使用者介面:

開啟資訊卡建立工具

必要條件

Node.js

已啟用互動功能的 Google Chat 應用程式。如要使用 HTTP 服務建立互動式 Chat 應用程式,請完成這個快速入門導覽課程

Python

已啟用互動功能的 Google Chat 應用程式。如要使用 HTTP 服務建立互動式 Chat 應用程式,請完成這個快速入門導覽課程

Java

已啟用互動功能的 Google Chat 應用程式。如要使用 HTTP 服務建立互動式 Chat 應用程式,請完成這個快速入門導覽課程

Apps Script

已啟用互動功能的 Google Chat 應用程式。如要在 Apps Script 中建立互動式 Chat 應用程式,請完成快速入門導覽課程

設定 Chat 應用程式首頁

如要支援應用程式首頁,您必須設定 Chat 應用程式,以便接收 APP_HOME 互動事件。每當使用者透過 Chat 應用程式傳送即時訊息,點選「首頁」分頁時,Chat 應用程式就會收到這項事件。

如要在 Google Cloud 控制台中更新設定,請按照下列步驟操作:

  1. 在 Google Cloud 控制台中,依序前往「選單」>「更多產品」>「Google Workspace」>「產品目錄」>「Google Chat API」

    前往 Google Chat API

  2. 依序按一下「管理」和「設定」分頁標籤。

  3. 在「互動功能」下方,前往「功能」專區設定應用程式首頁:

    1. 勾選「接收 1:1 訊息」核取方塊。
    2. 勾選「支援應用程式首頁」核取方塊。
  4. 如果 Chat 應用程式使用 HTTP 服務,請前往「連線設定」,然後在「應用程式首頁網址」欄位中指定端點。您可以使用在「HTTP 端點網址」欄位中指定的網址。

  5. 按一下 [儲存]

建構應用程式首頁資訊卡

當使用者開啟應用程式主畫面時,Chat 應用程式必須透過傳回 pushCard 導覽和 CardRenderActions 例項,處理 APP_HOME 互動事件。如要建立互動式體驗,資訊卡可以包含互動式小工具 (例如按鈕或文字輸入內容),方便 Chat 應用程式處理及回應其他資訊卡或對話方塊。

在下列範例中,Chat 應用程式會顯示初始應用程式首頁資訊卡,其中顯示資訊卡建立時間和按鈕。使用者按下按鈕後,Chat 應用程式會傳回更新後的資訊卡,顯示資訊卡的建立時間。

Node.js

node/app-home/index.js
app.post('/', async (req, res) => {
  let event = req.body.chat;

  let body = {};
  if (event.type === 'APP_HOME') {
    // App home is requested
    body = { action: { navigations: [{
      pushCard: getHomeCard()
    }]}}
  } else if (event.type === 'SUBMIT_FORM') {
    // The update button from app home is clicked
    commonEvent = req.body.commonEventObject;
    if (commonEvent && commonEvent.invokedFunction === 'updateAppHome') {
      body = updateAppHome()
    }
  }

  return res.json(body);
});

// Create the app home card
function getHomeCard() {
  return { sections: [{ widgets: [
    { textParagraph: {
      text: "Here is the app home 🏠 It's " + new Date().toTimeString()
    }},
    { buttonList: { buttons: [{
      text: "Update app home",
      onClick: { action: {
        function: "updateAppHome"
      }}
    }]}}
  ]}]};
}

Python

python/app-home/main.py
@app.route('/', methods=['POST'])
def post() -> Mapping[str, Any]:
  """Handle requests from Google Chat

  Returns:
      Mapping[str, Any]: the response
  """
  event = request.get_json()
  match event['chat'].get('type'):

    case 'APP_HOME':
      # App home is requested
      body = { "action": { "navigations": [{
        "pushCard": get_home_card()
      }]}}

    case 'SUBMIT_FORM':
      # The update button from app home is clicked
      event_object = event.get('commonEventObject')
      if event_object is not None:
        if 'update_app_home' == event_object.get('invokedFunction'):
          body = update_app_home()

    case _:
      # Other response types are not supported
      body = {}

  return json.jsonify(body)


def get_home_card() -> Mapping[str, Any]:
  """Create the app home card

  Returns:
      Mapping[str, Any]: the card
  """
  return { "sections": [{ "widgets": [
    { "textParagraph": {
      "text": "Here is the app home 🏠 It's " +
        datetime.datetime.now().isoformat()
    }},
    { "buttonList": { "buttons": [{
      "text": "Update app home",
      "onClick": { "action": {
        "function": "update_app_home"
      }}
    }]}}
  ]}]}

Java

java/app-home/src/main/java/com/google/chat/app/home/App.java
// Process Google Chat events
@PostMapping("/")
@ResponseBody
public GenericJson onEvent(@RequestBody JsonNode event) throws Exception {
  switch (event.at("/chat/type").asText()) {
    case "APP_HOME":
      // App home is requested
      GenericJson navigation = new GenericJson();
      navigation.set("pushCard", getHomeCard());

      GenericJson action = new GenericJson();
      action.set("navigations", List.of(navigation));

      GenericJson response = new GenericJson();
      response.set("action", action);
      return response;
    case "SUBMIT_FORM":
      // The update button from app home is clicked
      if (event.at("/commonEventObject/invokedFunction").asText().equals("updateAppHome")) {
        return updateAppHome();
      }
  }

  return new GenericJson();
}

// Create the app home card
GoogleAppsCardV1Card getHomeCard() {
  return new GoogleAppsCardV1Card()
    .setSections(List.of(new GoogleAppsCardV1Section()
      .setWidgets(List.of(
        new GoogleAppsCardV1Widget()
          .setTextParagraph(new GoogleAppsCardV1TextParagraph()
            .setText("Here is the app home 🏠 It's " + new Date())),
        new GoogleAppsCardV1Widget()
          .setButtonList(new GoogleAppsCardV1ButtonList().setButtons(List.of(new GoogleAppsCardV1Button()
            .setText("Update app home")
            .setOnClick(new GoogleAppsCardV1OnClick()
              .setAction(new GoogleAppsCardV1Action()
                .setFunction("updateAppHome"))))))))));
}

Apps Script

實作會在所有 APP_HOME 互動事件後呼叫的 onAppHome 函式:

這個範例會傳回 卡片 JSON,藉此傳送卡片訊息。您也可以使用 Apps Script 卡服務

apps-script/app-home/app-home.gs
/**
 * Responds to a APP_HOME event in Google Chat.
 */
function onAppHome() {
  return { action: { navigations: [{
    pushCard: getHomeCard()
  }]}};
}

/**
 * Returns the app home card.
 */
function getHomeCard() {
  return { sections: [{ widgets: [
    { textParagraph: {
      text: "Here is the app home 🏠 It's " + new Date().toTimeString()
    }},
    { buttonList: { buttons: [{
      text: "Update app home",
      onClick: { action: {
        function: "updateAppHome"
      }}
    }]}}
  ]}]};
}

回應應用程式主畫面互動

如果初始應用程式首頁資訊卡包含互動式小工具 (例如按鈕或選取輸入內容),Chat 應用程式必須透過 updateCard 導覽功能傳回 RenderActions 的執行個體,以處理相關互動事件。如要進一步瞭解如何處理互動式小工具,請參閱「處理使用者輸入的資訊」。

在前述範例中,初始應用程式主畫面資訊卡包含一個按鈕。每當使用者按下按鈕時,CARD_CLICKED 互動事件會觸發函式 updateAppHome,以便重新整理應用程式主畫面資訊卡,如以下程式碼所示:

Node.js

node/app-home/index.js
// Update the app home
function updateAppHome() {
  return { renderActions: { action: { navigations: [{
    updateCard: getHomeCard()
  }]}}}
};

Python

python/app-home/main.py
def update_app_home() -> Mapping[str, Any]:
  """Update the app home

  Returns:
      Mapping[str, Any]: the update card render action
  """
  return { "renderActions": { "action": { "navigations": [{
    "updateCard": get_home_card()
  }]}}}

Java

java/app-home/src/main/java/com/google/chat/app/home/App.java
// Update the app home
GenericJson updateAppHome() {
  GenericJson navigation = new GenericJson();
  navigation.set("updateCard", getHomeCard());

  GenericJson action = new GenericJson();
  action.set("navigations", List.of(navigation));

  GenericJson renderActions = new GenericJson();
  renderActions.set("action", action);

  GenericJson response = new GenericJson();
  response.set("renderActions", renderActions);
  return response;
}

Apps Script

這個範例會傳回 卡片 JSON,藉此傳送卡片訊息。您也可以使用 Apps Script 卡服務

apps-script/app-home/app-home.gs
/**
 * Updates the home app.
 */
function updateAppHome() {
  return { renderActions: { action: { navigations: [{
    updateCard: getHomeCard()
  }]}}};
}

開啟對話方塊

Chat 應用程式也可以開啟對話框,回應應用程式首頁中的互動內容。

對話方塊內含各種不同的小工具。
圖 3:提示使用者新增聯絡人的對話方塊。

如要從應用程式主畫面開啟對話方塊,請使用包含 Card 物件的 updateCard 導覽,傳回 renderActions,藉此處理相關互動事件。在以下範例中,Chat 應用程式會處理 CARD_CLICKED 互動事件並開啟對話方塊,以回應應用程式首頁資訊卡的按鈕點選動作:

{ renderActions: { action: { navigations: [{ updateCard: { sections: [{
  header: "Add new contact",
  widgets: [{ "textInput": {
    label: "Name",
    type: "SINGLE_LINE",
    name: "contactName"
  }}, { textInput: {
    label: "Address",
    type: "MULTIPLE_LINE",
    name: "address"
  }}, { decoratedText: {
    text: "Add to favorites",
    switchControl: {
      controlType: "SWITCH",
      name: "saveFavorite"
    }
  }}, { decoratedText: {
    text: "Merge with existing contacts",
    switchControl: {
      controlType: "SWITCH",
      name: "mergeContact",
      selected: true
    }
  }}, { buttonList: { buttons: [{
    text: "Next",
    onClick: { action: { function: "openSequentialDialog" }}
  }]}}]
}]}}]}}}

如要關閉對話方塊,請處理下列互動事件:

  • CLOSE_DIALOG:關閉對話方塊,並返回 Chat 應用程式的初始應用程式首頁資訊卡。
  • CLOSE_DIALOG_AND_EXECUTE:關閉對話方塊,並重新整理應用程式首頁資訊卡。

下列程式碼範例使用 CLOSE_DIALOG 關閉對話方塊,並返回應用程式首頁資訊卡:

{ renderActions: { action: {
  navigations: [{ endNavigation: { action: "CLOSE_DIALOG" }}]
}}}

如要向使用者收集資訊,您也可以建立連續對話方塊。如要瞭解如何建構依序對話方塊,請參閱「開啟並回應對話方塊」。