Jelajahi di Dialogflow
Klik Continue untuk mengimpor contoh Notifikasi di Dialogflow. Kemudian, ikuti langkah-langkah di bawah ini untuk men-deploy dan menguji sampel:
- Masukkan nama agen dan buat agen Dialogflow baru untuk contoh.
- Setelah agen selesai mengimpor, klik Buka agen.
- Dari menu navigasi utama, buka Fulfillment.
- Aktifkan Inline Editor, lalu klik Deploy. Editor berisi kode contoh.
- Dari menu navigasi utama, buka Integrations, lalu klik Google Assistant.
- Di jendela modal yang muncul, aktifkan Perubahan pratinjau otomatis, lalu klik Uji untuk membuka simulator Action.
- Pada simulator, masukkan
Talk to my test app
untuk menguji sampel.
Action Anda dapat mengirim notifikasi kepada pengguna kapan pun relevan, seperti mengirim pengingat saat batas waktu tugas sudah dekat.
Dalam panduan ini, kami menggunakan contoh tips Actions on Google sebagai referensi untuk menunjukkan cara menyiapkan notifikasi push untuk Action Anda. Saat pengguna memanggil Action ini, ia akan menanyakan apakah mereka ingin mendengar tips tentang mengembangkan Action mereka sendiri. Pengguna dapat memilih kategori spesifik atau dipilih secara acak untuk tips, atau mereka dapat memilih untuk mendengar tips terbaru.
Platform yang didukung
Notifikasi push tersedia di perangkat Android dan iOS (perangkat iOS harus menginstal aplikasi Asisten untuk menerima notifikasi push). Fitur tersebut saat ini tidak didukung di speaker yang diaktifkan dengan suara, layar smart, atau platform lainnya.
Prasyarat
Setidaknya satu Action dalam project Action Anda harus dikonfigurasi sebagai intent pemicu yang akan dipanggil saat pengguna mengetuk notifikasi yang diterima dari Asisten.
Action Anda tidak dapat dikonfigurasi untuk memicu Intent Selamat Datang Default dari notifikasi push.
Penyiapan konsol
Untuk menambahkan dukungan notifikasi push ke Action Anda:
Buka Konsol Actions, lalu buka Build > Actions.
Klik Action yang cocok dengan intent pemicu tambahan yang ingin Anda aktifkan notifikasi pushnya.
Untuk contoh tips Actions on Google, Anda akan memilih "tell_latest_tip".
Scroll ke bawah ke bagian Engagement pengguna, lalu aktifkan Apakah Anda ingin mengirim notifikasi push.
Masukkan Judul konten.
Untuk contoh tips Actions on Google, judulnya dapat berupa "Tips baru ditambahkan".
Klik Simpan.
Impor
Untuk tujuan bagian berikutnya, dalam kode fulfillment, Anda harus mendeklarasikan impor berikut:
const { dialogflow, UpdatePermission, Suggestions, } = require('actions-on-google');
const { actionssdk, UpdatePermission, Suggestions, } = require('actions-on-google');
Pengguna yang ikut serta
Sebelum dapat mengirim notifikasi push kepada pengguna, Anda harus meminta mereka untuk memilih ikut serta. Anda dapat melakukannya dengan menampilkan chip saran untuk meminta izin mereka. Saat pengguna memberikan izin, Anda akan menerima pembaruan ID pengguna untuk mengirim notifikasi push kepada pengguna tersebut.
Tampilkan chip saran untuk keikutsertaan
Sebelum pengguna dapat menerima notifikasi push dari Action, Anda harus menampilkan chip saran untuk mengundang mereka agar memilih ikut serta dalam notifikasi push.
Cuplikan kode berikut mengirimkan chip saran 'Beri tahu saya tentang tips baru' bersama respons teks.
conv.ask('I can send you push notifications. Would you like that?'); conv.ask(new Suggestions('Send notifications'));
conv.ask(' I can send you push notifications. Would you like that?'); conv.ask(new Suggestions('Send notifications'));
responseBuilder .add("I can send you push notifications. Would you like that?") .addSuggestions(new String[] { "Send notifications" });
responseBuilder .add("I can send you push notifications. Would you like that?") .addSuggestions(new String[] { "Send notifications" });
Perhatikan bahwa JSON di bawah menjelaskan respons 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" } ] } } } }
Perhatikan bahwa JSON di bawah menjelaskan respons 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" } ] } } } ] }
Setelah mereka mengetuk chip, Anda harus meminta izin UPDATE
.
Kode berikut menunjukkan cara melakukannya dengan fungsi askForUpdatePermission
library klien Node.js.
- Buka agen di konsol Dialogflow dan pilih intent yang dikonfigurasi untuk update.
- Scroll ke bawah ke Response lalu buka tab Google Assistant.
- Klik Tambahkan konten pesan, lalu pilih Chip saran.
- Setel teks chip ke sesuatu yang mengundang pengguna untuk ikut serta. Dalam contoh tips Actions on Google, kami menetapkan chip ke Beri tahu saya tentang tips baru.
- Tambahkan intent Dialogflow lain, yang disebut setup_push, lalu tetapkan tindakan yang sesuai, misalnya setup.push. Ekspresi pengguna intent ini harus cocok dengan teks chip keikutsertaan, dalam contoh kami Alert me of new tips.
app.intent('Subscribe to Notifications', (conv) => { conv.ask(new UpdatePermission({ intent: 'Notification', })); });
Anda harus mengonfigurasi solusi NLU untuk memicu fungsi yang meminta izin jika ekspresi pengguna cocok dengan nilai perintah keikutsertaan notifikasi push. Berikut adalah contoh yang sangat mendasar berdasarkan pencocokan string:
conv.ask(new UpdatePermission({ intent: 'Notification', }));
- Buka agen di konsol Dialogflow dan pilih intent yang dikonfigurasi untuk update.
- Scroll ke bawah ke Response lalu buka tab Google Assistant.
- Klik Tambahkan konten pesan, lalu pilih Chip saran.
- Setel teks chip ke sesuatu yang mengundang pengguna untuk ikut serta. Dalam contoh tips Actions on Google, kami menetapkan chip ke Beri tahu saya tentang tips baru.
- Tambahkan intent Dialogflow lain, yang disebut setup_push, lalu tetapkan tindakan yang sesuai, misalnya setup.push. Ekspresi pengguna intent ini harus cocok dengan teks chip keikutsertaan, dalam contoh kami Alert me of new tips.
@ForIntent("Subscribe to Notifications") public ActionResponse subscribeToNotifications(ActionRequest request) { ResponseBuilder responseBuilder = getResponseBuilder(request); responseBuilder.add(new UpdatePermission().setIntent("Notification")); return responseBuilder.build(); }
Anda harus mengonfigurasi solusi NLU untuk memicu fungsi yang meminta izin jika ekspresi pengguna cocok dengan nilai perintah keikutsertaan notifikasi push. Berikut adalah contoh yang sangat mendasar berdasarkan pencocokan string:
ResponseBuilder responseBuilder = getResponseBuilder(request); responseBuilder.add(new UpdatePermission().setIntent("Notification")); return responseBuilder.build();
Perhatikan bahwa JSON di bawah ini menjelaskan respons webhook menggunakan Dialogflow.
{ "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" } } } } } }
Perhatikan bahwa JSON di bawah menjelaskan respons webhook menggunakan Actions SDK.
{ "expectUserResponse": true, "expectedInputs": [ { "possibleIntents": [ { "intent": "actions.intent.PERMISSION", "inputValueData": { "@type": "type.googleapis.com/google.actions.v2.PermissionValueSpec", "permissions": [ "UPDATE" ], "updatePermissionValueSpec": { "intent": "tell_latest_tip" } } } ] } ] }
Menyelesaikan langganan
Untuk menyelesaikan langganan dari webhook Node.js, Anda harus menyimpan ID notifikasi pengguna dan intent yang mereka pilih. Keduanya diteruskan sebagai argumen jika pengguna memberikan izin.
Jika Action Anda di-build dengan Dialogflow, Anda harus:
- Tambahkan intent yang menangani
actions_intent_PERMISSION
. - Tentukan nama Action intent ke sesuatu yang dapat difilter untuk selanjutnya oleh webhook Anda.
Kode berikut menunjukkan cara menangani intent Dialogflow dengan intent
bernama finish_push_setup
dengan nama Action finish.push.setup
:
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.`); } });
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.`); } });
@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(); }
@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(); }
Perhatikan bahwa JSON di bawah menjelaskan permintaan ke 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" }
Perhatikan bahwa JSON di bawah menjelaskan permintaan ke 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" } ] } ] }
Kirim notifikasi
Anda dapat mengirim notifikasi push kepada pengguna menggunakan Actions API. Untuk menggunakan API ini, Anda perlu mengaktifkan API di project Google Cloud serta menyiapkan dan mendownload kunci akun layanan JSON. Lihat langkah #8 dalam petunjuk dalam contoh kode di sini.
Selanjutnya, Anda dapat menggunakan library klien Google OAuth2 untuk menukar kunci akun layanan dengan token akses, dan menggunakan token tersebut untuk mengautentikasi permintaan Anda ke Actions API.
Dapatkan kunci akun layanan
- Buka URL ini dan ganti "example-project-1" di akhir dengan project ID Anda di konsol Actions: https://console.developers.google.com/apis/api/actions.googleapis.com/overview?project=example-project-1
- Jika Anda melihat tombol Aktifkan, klik tombol tersebut. Jika tidak, lanjutkan ke langkah 3.
- Buka URL ini, lalu ganti "example-project-1" di bagian akhir dengan project ID Anda di konsol Actions: https://console.developers.google.com/apis/credentials?project=example-project-1
- Klik Create credentials > Service Account Key.
- Klik kotak Pilih di bagian Akun Layanan, lalu klik Akun Layanan Baru.
- Beri nama Akun Layanan seperti "notifikasi" dan Peran Project Owner.
- Pilih jenis kunci JSON, lalu klik Create. Kunci akun layanan JSON didownload ke komputer lokal Anda.
Tukar kunci dengan token akses dan kirim notifikasi
Untuk mengirim notifikasi melalui Actions API, Anda perlu menukar kunci akun layanan dengan token akses. Sebaiknya gunakan library klien Google API untuk hal ini. Dalam serangkaian cuplikan kode berikut, kita menggunakan library klien Node.js Google API.
- Instal permintaan dan library klien Google API:
npm install googleapis request --save
- Gunakan kode berikut untuk mendapatkan token akses dari kunci akun layanan dan mengirim notifikasi push:
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}`); }); } });
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}`); }); } });
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); }
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); }