推播通知 (Dialogflow)

在 Dialogflow 中探索

點選「繼續」,在 Dialogflow 中匯入通知範例。接著,請按照 部署及測試範例的步驟:

  1. 輸入虛擬服務專員名稱,並為範例建立新的 Dialogflow 代理程式。
  2. 代理程式匯入完畢後,按一下「Go to agent」
  3. 在主要導覽選單中,前往「Fulfillment」(執行要求)
  4. 啟用「Inline Editor」(內嵌編輯器),然後按一下 [Deploy] (部署)。編輯器包含範例 再也不是件繁重乏味的工作
  5. 在主要導覽選單中,前往「Integrations」(整合),然後按一下「Google」 Google 助理
  6. 在出現的互動視窗中,啟用「自動預覽變更」,然後按一下「測試」 以開啟動作模擬工具
  7. 在模擬工具中輸入 Talk to my test app 即可測試範例!
繼續

您的動作可視需要向使用者推送通知,例如: 接近工作的到期日時收到提醒。

在本指南中,我們使用 Actions on Google 提示範例 ,說明如何為動作設定推播通知。 使用者叫用這項動作時,系統會詢問是否要聽取提示 瞭解如何規劃自己的動作使用者可以 選擇特定或隨機選取的小費類別,或是 選擇聽取最新提示

支援的平台

Android 和 iOS 裝置皆可使用推播通知 (iOS 裝置必須 必須安裝「Google 助理」應用程式以接收推播通知)。他們不是 目前支援聲控喇叭、智慧螢幕或其他介面。

必要條件

您的 Actions 專案中至少要有一個動作設為 觸發意圖;當使用者輕觸收到的訊息來源時,系統就會叫用這個意圖 。

無法設定動作,透過推播通知觸發預設歡迎意圖。

控制台設定

如何為動作新增推播通知:

  1. 前往動作控制台,然後進行瀏覽 即可建立 >動作

  2. 按一下與您要新增的其他觸發意圖相符的動作 啟用推播通知。

    針對 Actions on Google 提示,請選取「tell_latest_tip」。

  3. 向下捲動至「使用者參與度」部分並開啟 你想傳送推播通知嗎?

  4. 輸入內容標題

    如需 Actions on Google 提示的範例,可以使用「新增提示」標題。

  5. 按一下 [儲存]

匯入

至於後續章節的用途,在執行要求程式碼中您將 需要宣告下列匯入作業:

Dialogflow
const {
  dialogflow,
  UpdatePermission,
  Suggestions,
} = require('actions-on-google');
敬上
動作 SDK
const {
  actionssdk,
  UpdatePermission,
  Suggestions,
} = require('actions-on-google');

選擇啟用的使用者

傳送推播通知給使用者前,您必須先要求他們啟用接收功能。 例如向對方顯示建議方塊,請對方授予他們權限。 對方授予權限後,您會收到更新的使用者 ID。 傳送推播通知給該使用者

顯示開放啟用的建議方塊

在使用者收到您的動作的推播通知之前,您必須先 建議方塊,邀請他們啟用推播通知。

下列程式碼片段會將「建議新提示」通知使用者建議 方塊和文字回應

Dialogflow Node.js
conv.ask('I can send you push notifications. Would you like that?');
conv.ask(new Suggestions('Send notifications'));
敬上
動作 SDK Node.js
conv.ask(' I can send you push notifications. Would you like that?');
conv.ask(new Suggestions('Send notifications'));
敬上
Dialogflow Java
responseBuilder
    .add("I can send you push notifications. Would you like that?")
    .addSuggestions(new String[] {
        "Send notifications"
    });
敬上
動作 SDK Java
responseBuilder
    .add("I can send you push notifications. Would you like that?")
    .addSuggestions(new String[] {
        "Send notifications"
    });
敬上
Dialogflow JSON

請注意,下列 JSON 會說明 Webhook 回應。

{
  "payload": {
    "google": {
      "expectUserResponse": true,
      "richResponse": {
        "items": [
          {
            "simpleResponse": {
              "textToSpeech": "Hi! Welcome to Push Notifications!"
            }
          },
          {
            "simpleResponse": {
              "textToSpeech": "I can send you push notifications. Would you like that?"
            }
          }
        ],
        "suggestions": [
          {
            "title": "Send notifications"
          }
        ]
      }
    }
  }
}
敬上
動作 SDK JSON

請注意,下列 JSON 會說明 Webhook 回應。

{
  "expectUserResponse": true,
  "expectedInputs": [
    {
      "possibleIntents": [
        {
          "intent": "actions.intent.TEXT"
        }
      ],
      "inputPrompt": {
        "richInitialPrompt": {
          "items": [
            {
              "simpleResponse": {
                "textToSpeech": "Hi! Welcome to Push Notifications!"
              }
            },
            {
              "simpleResponse": {
                "textToSpeech": " I can send you push notifications. Would you like that?"
              }
            }
          ],
          "suggestions": [
            {
              "title": "Send notifications"
            }
          ]
        }
      }
    }
  ]
}

使用者輕觸方塊後,你必須要求 UPDATE 權限。 以下程式碼顯示如何使用 askForUpdatePermission 執行此操作 函式。

Dialogflow Node.js
  1. 在 Dialogflow 控制台中開啟代理程式,然後選取要為更新的意圖進行設定。
  2. 向下捲動至「回應」,然後開啟「Google 助理」分頁。
  3. 按一下「新增訊息內容」,然後選取「建議方塊」
  4. 將方塊文字設為邀請使用者選擇加入的文字。在 Actions on Google 提示範例,我們已將方塊設為「傳送新提示快訊」
  5. 新增另一個名為 setup_push 的 Dialogflow 意圖,然後 設定對應的動作,例如 setup.push。 這個意圖的使用者運算式必須與選擇訂閱方塊的文字相符。 中的「快訊通知我新提示」範例。
,瞭解如何調查及移除這項存取權。 下列程式碼片段說明如何使用動作要求權限 ,在適用於 Node.js 的 Google 用戶端程式庫中完成以下步驟:
app.intent('Subscribe to Notifications', (conv) => {
  conv.ask(new UpdatePermission({
    intent: 'Notification',
  }));
});
敬上
動作 SDK Node.js

您應該設定 NLU 解決方案,觸發會要求 如果使用者表達內容與推播通知的值相符 詢問意願選項。以下是非常基本的字串比對範例:

conv.ask(new UpdatePermission({
  intent: 'Notification',
}));
敬上
Dialogflow Java
  1. 在 Dialogflow 控制台中開啟代理程式,然後選取要為更新的意圖進行設定。
  2. 向下捲動至「回應」,然後開啟「Google 助理」分頁。
  3. 按一下「新增訊息內容」,然後選取「建議方塊」
  4. 將方塊文字設為邀請使用者選擇加入的文字。在 Actions on Google 提示範例,我們已將方塊設為「傳送新提示快訊」
  5. 新增另一個名為 setup_push 的 Dialogflow 意圖,然後 設定對應的動作,例如 setup.push。 這個意圖的使用者運算式必須與選擇訂閱方塊的文字相符。 中的「快訊通知我新提示」範例。
,瞭解如何調查及移除這項存取權。 下列程式碼片段說明如何使用動作要求權限 ,前往 Google Java/Kotlin 用戶端程式庫:
@ForIntent("Subscribe to Notifications")
public ActionResponse subscribeToNotifications(ActionRequest request) {
  ResponseBuilder responseBuilder = getResponseBuilder(request);
  responseBuilder.add(new UpdatePermission().setIntent("Notification"));
  return responseBuilder.build();
}
敬上
動作 SDK Java

您應該設定 NLU 解決方案,觸發會要求 如果使用者表達內容與推播通知的值相符 詢問意願選項。以下是非常基本的字串比對範例:

ResponseBuilder responseBuilder = getResponseBuilder(request);
responseBuilder.add(new UpdatePermission().setIntent("Notification"));
return responseBuilder.build();
敬上
Dialogflow JSON

請注意,以下 JSON 會說明使用 Dialogflow 的 Webhook 回應。

{
  "payload": {
    "google": {
      "expectUserResponse": true,
      "systemIntent": {
        "intent": "actions.intent.PERMISSION",
        "data": {
          "@type": "type.googleapis.com/google.actions.v2.PermissionValueSpec",
          "permissions": [
            "UPDATE"
          ],
          "updatePermissionValueSpec": {
            "intent": "tell_latest_tip"
          }
        }
      }
    }
  }
}
敬上
動作 SDK JSON

請注意,以下 JSON 會說明使用 Actions SDK 的 Webhook 回應。

{
  "expectUserResponse": true,
  "expectedInputs": [
    {
      "possibleIntents": [
        {
          "intent": "actions.intent.PERMISSION",
          "inputValueData": {
            "@type": "type.googleapis.com/google.actions.v2.PermissionValueSpec",
            "permissions": [
              "UPDATE"
            ],
            "updatePermissionValueSpec": {
              "intent": "tell_latest_tip"
            }
          }
        }
      ]
    }
  ]
}
敬上

完成訂閱

如要從 Node.js Webhook 完成訂閱,您必須儲存 使用者的通知 ID 和他們選取的意圖。兩者都會以 。

如果您的 Action 是以 Dialogflow 建構,則必須執行以下作業:

  • 新增可處理 actions_intent_PERMISSION 的意圖。
  • 請指定意圖的「Action」名稱,做為 Webhook 使用的名稱 篩選結果。

以下程式碼顯示如何使用意圖處理 Dialogflow 意圖 動作名稱為 finish_push_setup,動作名稱為 finish.push.setup

Dialogflow Node.js
app.intent('Confirm Notifications Subscription', (conv) => {
  if (conv.arguments.get('PERMISSION')) {
    const updatesUserId = conv.arguments.get('UPDATES_USER_ID');
    // Store user ID in database for later use
    conv.close(`Ok, I'll start alerting you.`);
  } else {
    conv.close(`Ok, I won't alert you.`);
  }
});
敬上
動作 SDK Node.js
app.intent('actions.intent.PERMISSION', (conv) => {
  if (conv.arguments.get('PERMISSION')) {
    const updatesUserId = conv.arguments.get('UPDATES_USER_ID');
    // Store user ID in database for later use
    conv.close(`Ok, I'll start alerting you.`);
  } else {
    conv.close(`Ok, I won't alert you.`);
  }
});
敬上
Dialogflow Java
@ForIntent("Confirm Notifications Subscription")
public ActionResponse confirmNotificationsSubscription(ActionRequest request) {
  // Verify the user has subscribed for push notifications
  ResponseBuilder responseBuilder = getResponseBuilder(request);
  if (request.isPermissionGranted()) {
    Argument userId = request.getArgument(ConstantsKt.ARG_UPDATES_USER_ID);
    if (userId != null) {
      // Store the user's ID in the database
    }
    responseBuilder.add("Ok, I'll start alerting you.");
  } else {
    responseBuilder.add("Ok, I won't alert you.");
  }
  responseBuilder.endConversation();
  return responseBuilder.build();
}
敬上
動作 SDK Java
@ForIntent("actions.intent.PERMISSION")
public ActionResponse confirmNotificationsSubscription(ActionRequest request) {
  // Verify the user has subscribed for push notifications
  ResponseBuilder responseBuilder = getResponseBuilder(request);
  if (request.isPermissionGranted()) {
    Argument userId = request.getArgument(ConstantsKt.ARG_UPDATES_USER_ID);
    if (userId != null) {
      // Store the user's ID in the database
    }
    responseBuilder.add("Ok, I'll start alerting you.");
  } else {
    responseBuilder.add("Ok, I won't alert you.");
  }
  responseBuilder.endConversation();
  return responseBuilder.build();
}
敬上
Dialogflow JSON

請注意,以下 JSON 描述了對 Webhook 的要求。

{
  "responseId": "ee9e7ed5-fa1a-48c6-aac7-f9fbe94f1f58-712767ed",
  "queryResult": {
    "queryText": "actions_intent_PERMISSION",
    "action": "confirm.subscription",
    "parameters": {},
    "allRequiredParamsPresent": true,
    "fulfillmentMessages": [
      {
        "text": {
          "text": [
            ""
          ]
        }
      }
    ],
    "outputContexts": [
      {
        "name": "projects/PROJECT_ID/agent/sessions/ABwppHGIgmmU3zBcYMF_vWoHaM4JUo3wniYBHdbUF25l63G7EQWjRnlne8Ar7AOcRHWn1lrEKGy8qdP0UXLcWDBq93k/contexts/actions_capability_screen_output"
      },
      {
        "name": "projects/PROJECT_ID/agent/sessions/ABwppHGIgmmU3zBcYMF_vWoHaM4JUo3wniYBHdbUF25l63G7EQWjRnlne8Ar7AOcRHWn1lrEKGy8qdP0UXLcWDBq93k/contexts/actions_capability_account_linking"
      },
      {
        "name": "projects/PROJECT_ID/agent/sessions/ABwppHGIgmmU3zBcYMF_vWoHaM4JUo3wniYBHdbUF25l63G7EQWjRnlne8Ar7AOcRHWn1lrEKGy8qdP0UXLcWDBq93k/contexts/actions_capability_media_response_audio"
      },
      {
        "name": "projects/PROJECT_ID/agent/sessions/ABwppHGIgmmU3zBcYMF_vWoHaM4JUo3wniYBHdbUF25l63G7EQWjRnlne8Ar7AOcRHWn1lrEKGy8qdP0UXLcWDBq93k/contexts/actions_capability_audio_output"
      },
      {
        "name": "projects/PROJECT_ID/agent/sessions/ABwppHGIgmmU3zBcYMF_vWoHaM4JUo3wniYBHdbUF25l63G7EQWjRnlne8Ar7AOcRHWn1lrEKGy8qdP0UXLcWDBq93k/contexts/actions_capability_web_browser"
      },
      {
        "name": "projects/PROJECT_ID/agent/sessions/ABwppHGIgmmU3zBcYMF_vWoHaM4JUo3wniYBHdbUF25l63G7EQWjRnlne8Ar7AOcRHWn1lrEKGy8qdP0UXLcWDBq93k/contexts/google_assistant_input_type_keyboard"
      },
      {
        "name": "projects/PROJECT_ID/agent/sessions/ABwppHGIgmmU3zBcYMF_vWoHaM4JUo3wniYBHdbUF25l63G7EQWjRnlne8Ar7AOcRHWn1lrEKGy8qdP0UXLcWDBq93k/contexts/actions_intent_permission",
        "parameters": {
          "PERMISSION": true,
          "text": "yes",
          "UPDATES_USER_ID": "ABwppHHssyPbvEBF1mgN7Ddwb7mkhiVohW9PZ--I_svqy7zFElA4DHkf9pn04UBd5gwZo26_RfXCQ8otcztyIfe6MCQ"
        }
      }
    ],
    "intent": {
      "name": "projects/PROJECT_ID/agent/intents/c7f7b30b-5b88-4bb5-b0b8-1cd0862d1dd2",
      "displayName": "Confirm Notifications Subscription"
    },
    "intentDetectionConfidence": 1,
    "languageCode": "en"
  },
  "originalDetectIntentRequest": {
    "source": "google",
    "version": "2",
    "payload": {
      "user": {
        "permissions": [
          "UPDATE"
        ],
        "locale": "en-US",
        "userVerificationStatus": "VERIFIED"
      },
      "conversation": {
        "conversationId": "ABwppHGIgmmU3zBcYMF_vWoHaM4JUo3wniYBHdbUF25l63G7EQWjRnlne8Ar7AOcRHWn1lrEKGy8qdP0UXLcWDBq93k",
        "type": "ACTIVE",
        "conversationToken": "[]"
      },
      "inputs": [
        {
          "intent": "actions.intent.PERMISSION",
          "rawInputs": [
            {
              "inputType": "KEYBOARD",
              "query": "yes"
            }
          ],
          "arguments": [
            {
              "name": "PERMISSION",
              "boolValue": true,
              "textValue": "true"
            },
            {
              "name": "text",
              "rawText": "yes",
              "textValue": "yes"
            },
            {
              "name": "UPDATES_USER_ID",
              "textValue": "ABwppHHssyPbvEBF1mgN7Ddwb7mkhiVohW9PZ--I_svqy7zFElA4DHkf9pn04UBd5gwZo26_RfXCQ8otcztyIfe6MCQ"
            }
          ]
        }
      ],
      "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.AUDIO_OUTPUT"
            },
            {
              "name": "actions.capability.SCREEN_OUTPUT"
            },
            {
              "name": "actions.capability.WEB_BROWSER"
            }
          ]
        }
      ]
    }
  },
  "session": "projects/PROJECT_ID/agent/sessions/ABwppHGIgmmU3zBcYMF_vWoHaM4JUo3wniYBHdbUF25l63G7EQWjRnlne8Ar7AOcRHWn1lrEKGy8qdP0UXLcWDBq93k"
}
敬上
動作 SDK JSON

請注意,以下 JSON 描述了對 Webhook 的要求。

{
  "user": {
    "permissions": [
      "UPDATE"
    ],
    "locale": "en-US",
    "userVerificationStatus": "VERIFIED"
  },
  "conversation": {
    "conversationId": "ABwppHEP6OAFZHkSGEiZ5HYM9qrlk8YtIH1DQmJ52cxXELSPvM-kSc_tMJ_5O6ITbgVJlY9i2FIsKWjE_HXLke48",
    "type": "NEW"
  },
  "inputs": [
    {
      "intent": "actions.intent.PERMISSION",
      "rawInputs": [
        {
          "inputType": "KEYBOARD",
          "query": "yes"
        }
      ],
      "arguments": [
        {
          "name": "PERMISSION",
          "boolValue": true,
          "textValue": "true"
        },
        {
          "name": "text",
          "rawText": "yes",
          "textValue": "yes"
        },
        {
          "name": "UPDATES_USER_ID",
          "textValue": "ABwppHFvBKC-tMYUsUjJkm3YECgZvd6A3sOc7KuQvO4ZdQX3bGLmyoQ41dh4Zmtlzv_kaOKBt1Sf6eRpNbayynrl"
        }
      ]
    }
  ],
  "surface": {
    "capabilities": [
      {
        "name": "actions.capability.AUDIO_OUTPUT"
      },
      {
        "name": "actions.capability.WEB_BROWSER"
      },
      {
        "name": "actions.capability.SCREEN_OUTPUT"
      },
      {
        "name": "actions.capability.ACCOUNT_LINKING"
      },
      {
        "name": "actions.capability.MEDIA_RESPONSE_AUDIO"
      }
    ]
  },
  "availableSurfaces": [
    {
      "capabilities": [
        {
          "name": "actions.capability.AUDIO_OUTPUT"
        },
        {
          "name": "actions.capability.SCREEN_OUTPUT"
        },
        {
          "name": "actions.capability.WEB_BROWSER"
        }
      ]
    }
  ]
}

傳送通知

您可以使用 Actions API 傳送推播通知給使用者。如要使用這個 API, 您必須在 Google Cloud 專案中啟用 API,並設定並下載 JSON 服務帳戶金鑰。請參閱這裡的程式碼範例操作說明,瞭解步驟 8。

接著,您可以使用 Google OAuth2 用戶端程式庫來交換服務帳戶金鑰 ,並使用該權杖驗證對 Actions API 的要求。

取得服務帳戶金鑰

  1. 前往這個網址,取代「example-project-1」結尾是您的專案 ID 在 Actions 控制台中執行下列操作: https://console.developers.google.com/apis/api/actions.googleapis.com/overview?project=example-project-1
  2. 如果看到「啟用」按鈕,請點選該按鈕。否則,請繼續執行步驟 3。
  3. 前往這個網址,取代「example-project-1」結尾是您的專案 ID 在 Actions 控制台中執行下列操作: https://console.developers.google.com/apis/credentials?project=example-project-1
  4. 按一下「Create credentials」(建立憑證) >服務帳戶金鑰
  5. 按一下服務帳戶下方的選取方塊,然後按一下新服務 帳戶
  6. 為服務帳戶命名,例如「notifications」角色 專案擁有者
  7. 選取 JSON 金鑰類型,然後按一下「建立」。JSON 服務帳戶金鑰 就會下載到本機電腦上

交換存取權杖的金鑰並傳送通知

如要透過 Actions API 傳送通知,您必須交換 存取權杖的服務帳戶金鑰建議使用 Google API 用戶端 程式庫這一系列程式碼片段中的 Google API Node.js 用戶端程式庫。

  1. 安裝 Google API 用戶端程式庫並要求: npm install googleapis request --save
  2. 請使用以下程式碼,從服務帳戶金鑰取得存取權杖 並傳送推播通知:
,瞭解如何調查及移除這項存取權。
Dialogflow Node.js
const {google} = require('googleapis');
const request = require('request');

const jwtClient = new google.auth.JWT(
  serviceAccount.client_email, null, serviceAccount.private_key,
  ['https://www.googleapis.com/auth/actions.fulfillment.conversation'],
  null
);

jwtClient.authorize((err, tokens) => {
  if (!err) {
    request.post('https://actions.googleapis.com/v2/conversations:send', {
      auth: {
        bearer: tokens.access_token,
      },
      json: true,
      body: {
        customPushMessage: {
          userNotification: {
            title: 'Push Notification Title',
          },
          target: {
            userId: '<UPDATES_USER_ID>',
            intent: 'Notification Intent',
          },
        },
        isInSandbox: true,
      },
    }, (err, httpResponse, body) => {
      console.log(`${httpResponse.statusCode}: ${httpResponse.statusMessage}`);
    });
  }
});
敬上
動作 SDK Node.js
const {google} = require('googleapis');
const request = require('request');

const jwtClient = new google.auth.JWT(
  serviceAccount.client_email, null, serviceAccount.private_key,
  ['https://www.googleapis.com/auth/actions.fulfillment.conversation'],
  null
);

jwtClient.authorize((err, tokens) => {
  if (!err) {
    request.post('https://actions.googleapis.com/v2/conversations:send', {
      auth: {
        bearer: tokens.access_token,
      },
      json: true,
      body: {
        customPushMessage: {
          userNotification: {
            title: 'Push Notification Title',
          },
          target: {
            userId: '<UPDATES_ORDER_ID>',
            intent: 'Notification Intent',
          },
        },
        isInSandbox: true,
      },
    }, (err, httpResponse, body) => {
      console.log(`${httpResponse.statusCode}: ${httpResponse.statusMessage}`);
    });
  }
});
敬上
Dialogflow Java
final class Notification {

  private final String title;

  Notification(String title) {
    this.title = title;
  }

  String getTitle() {
    return title;
  }
}

final class Target {

  private final String userId;
  private final String intent;
  private final String locale;

  Target(String userId, String intent, String locale) {
    this.userId = userId;
    this.intent = intent;
    this.locale = locale;
  }

  String getUserId() {
    return userId;
  }

  String getIntent() {
    return intent;
  }

  String getLocale() {
    return locale;
  }
}

final class PushMessage {

  private final Notification userNotification;
  private final Target target;

  PushMessage(Notification userNotification, Target target) {
    this.userNotification = userNotification;
    this.target = target;
  }

  Notification getUserNotification() {
    return userNotification;
  }

  Target getTarget() {
    return target;
  }
}

final class PushNotification {

  private final PushMessage customPushMessage;
  private boolean isInSandbox;

  PushNotification(PushMessage customPushMessage, boolean isInSandbox) {
    this.customPushMessage = customPushMessage;
    this.isInSandbox = isInSandbox;
  }

  PushMessage getCustomPushMessage() {
    return customPushMessage;
  }

  boolean getIsInSandbox() {
    return isInSandbox;
  }
}

private PushNotification createNotification(String title, String userId, String intent, String locale) {
  Notification notification = new Notification(title);
  Target target = new Target(userId, intent, locale);
  PushMessage message = new PushMessage(notification, target);
  boolean isInSandbox = true;
  return new PushNotification(message, isInSandbox);
}

private ServiceAccountCredentials loadCredentials() throws IOException {
  String actionsApiServiceAccountFile =
      this.getClass().getClassLoader().getResource("service-account.json").getFile();
  InputStream actionsApiServiceAccount = new FileInputStream(actionsApiServiceAccountFile);
  ServiceAccountCredentials serviceAccountCredentials =
      ServiceAccountCredentials.fromStream(actionsApiServiceAccount);
  return (ServiceAccountCredentials)
      serviceAccountCredentials.createScoped(
          Collections.singleton(
              "https://www.googleapis.com/auth/actions.fulfillment.conversation"));
}

private String getAccessToken() throws IOException {
  AccessToken token = loadCredentials().refreshAccessToken();
  return token.getTokenValue();
}

public void sendNotification(String title, String userId, String intent, String locale) throws IOException {
  Preconditions.checkNotNull(title, "title cannot be null.");
  Preconditions.checkNotNull(userId, "userId cannot be null.");
  Preconditions.checkNotNull(intent, "intent cannot be null.");
  Preconditions.checkNotNull(locale, "locale cannot be null");
  PushNotification notification = createNotification(title, userId, intent, locale);

  HttpPost request = new HttpPost("https://actions.googleapis.com/v2/conversations:send");

  String token = getAccessToken();

  request.setHeader("Content-type", "application/json");
  request.setHeader("Authorization", "Bearer " + token);

  StringEntity entity = new StringEntity(new Gson().toJson(notification));
  entity.setContentType(ContentType.APPLICATION_JSON.getMimeType());
  request.setEntity(entity);
  HttpClient httpClient = HttpClientBuilder.create().build();
  httpClient.execute(request);
}
敬上
動作 SDK Java
final class Notification {

  private final String title;

  Notification(String title) {
    this.title = title;
  }

  String getTitle() {
    return title;
  }
}

final class Target {

  private final String userId;
  private final String intent;

  Target(String userId, String intent) {
    this.userId = userId;
    this.intent = intent;
  }

  String getUserId() {
    return userId;
  }

  String getIntent() {
    return intent;
  }
}

final class PushMessage {

  private final Notification userNotification;
  private final Target target;

  PushMessage(Notification userNotification, Target target) {
    this.userNotification = userNotification;
    this.target = target;
  }

  Notification getUserNotification() {
    return userNotification;
  }

  Target getTarget() {
    return target;
  }
}

final class PushNotification {

  private final PushMessage customPushMessage;
  private boolean isInSandbox;

  PushNotification(PushMessage customPushMessage, boolean isInSandbox) {
    this.customPushMessage = customPushMessage;
    this.isInSandbox = isInSandbox;
  }

  PushMessage getCustomPushMessage() {
    return customPushMessage;
  }

  boolean getIsInSandbox() {
    return isInSandbox;
  }
}

private PushNotification createNotification(String title, String userId, String intent) {
  Notification notification = new Notification(title);
  Target target = new Target(userId, intent);
  PushMessage message = new PushMessage(notification, target);
  boolean isInSandbox = true;
  return new PushNotification(message, isInSandbox);
}

private ServiceAccountCredentials loadCredentials() throws IOException {
  String actionsApiServiceAccountFile =
      this.getClass().getClassLoader().getResource("service-account.json").getFile();
  InputStream actionsApiServiceAccount = new FileInputStream(actionsApiServiceAccountFile);
  ServiceAccountCredentials serviceAccountCredentials =
      ServiceAccountCredentials.fromStream(actionsApiServiceAccount);
  return (ServiceAccountCredentials)
      serviceAccountCredentials.createScoped(
          Collections.singleton(
              "https://www.googleapis.com/auth/actions.fulfillment.conversation"));
}

private String getAccessToken() throws IOException {
  AccessToken token = loadCredentials().refreshAccessToken();
  return token.getTokenValue();
}

public void sendNotification(String title, String userId, String intent) throws IOException {
  Preconditions.checkNotNull(title, "title cannot be null.");
  Preconditions.checkNotNull(userId, "userId cannot be null.");
  Preconditions.checkNotNull(intent, "intent cannot be null.");
  PushNotification notification = createNotification(title, userId, intent);

  HttpPost request = new HttpPost("https://actions.googleapis.com/v2/conversations:send");

  String token = getAccessToken();

  request.setHeader("Content-type", "application/json");
  request.setHeader("Authorization", "Bearer " + token);

  StringEntity entity = new StringEntity(new Gson().toJson(notification));
  entity.setContentType(ContentType.APPLICATION_JSON.getMimeType());
  request.setEntity(entity);
  HttpClient httpClient = HttpClientBuilder.create().build();
  httpClient.execute(request);
}