Notifiche push (Dialogflow)

Esplora in Dialogflow

Fai clic su Continua per importare il nostro campione di notifiche in Dialogflow. Poi segui le passaggi di seguito per eseguire il deployment e testare l'esempio:

  1. Inserisci il nome di un agente e crea un nuovo agente Dialogflow per il campione.
  2. Al termine dell'importazione, fai clic su Vai all'agente.
  3. Nel menu di navigazione principale, vai a Fulfillment.
  4. Attiva l'editor incorporato e fai clic su Esegui il deployment. L'editor contiene l'esempio le API nel tuo codice.
  5. Nel menu di navigazione principale, vai a Integrazioni, quindi fai clic su Google Assistente.
  6. Nella finestra modale che viene visualizzata, attiva Anteprima automatica delle modifiche e fai clic su Test. per aprire il simulatore delle azioni.
  7. Nel simulatore, inserisci Talk to my test app per testare il campione.
Continua

L'azione può inviare notifiche push agli utenti quando sono pertinenti, ad esempio l'invio un promemoria quando si avvicina la data di scadenza per un'attività.

In questa guida, utilizziamo gli esempi di suggerimenti per Actions on Google. come riferimento per mostrarti come configurare le notifiche push per la tua Azione. Quando gli utenti richiamano questa azione, viene chiesto se vogliono ascoltare un suggerimento sullo sviluppo di una propria Azione. Gli utenti possono scegliere una categoria specifica o una selezione casuale per il suggerimento oppure scegli di ascoltare il suggerimento più recente.

Piattaforme supportate

Le notifiche push sono disponibili su dispositivi Android e iOS (i dispositivi iOS devono avere installato l'app dell'assistente per ricevere notifiche push). Non sono attualmente supportata su speaker con attivazione vocale, smart display o altre piattaforme.

Prerequisiti

Almeno una delle azioni nel progetto Actions deve essere configurata come intent di attivazione che verrà richiamato quando l'utente tocca una notifica ricevuta l'assistente.

Le azioni non possono essere configurate per attivare l'intent di benvenuto predefinito da una notifica push.

Configurazione della console

Per aggiungere il supporto delle notifiche push all'Azione:

  1. Vai alla console Actions e vai su Crea > Azioni.

  2. Fai clic sull'azione che corrisponde all'intento di attivazione aggiuntivo che vuoi abilita le notifiche push per.

    Per l'esempio di suggerimenti per Actions on Google, devi selezionare "tell_latest_tip".

  3. Scorri verso il basso fino alla sezione Coinvolgimento degli utenti e attiva l'opzione Vuoi inviare notifiche push.

  4. Inserisci un Titolo contenuti.

    Per l'esempio di suggerimenti di Actions on Google, il titolo potrebbe essere "Nuovo suggerimento aggiunto".

  5. Fai clic su Salva.

Importazioni

Ai fini delle sezioni successive, nel codice di evasione degli ordini dovrai devi dichiarare le seguenti importazioni:

Dialogflow
di Gemini Advanced.
const {
  dialogflow,
  UpdatePermission,
  Suggestions,
} = require('actions-on-google');
SDK Actions
const {
  actionssdk,
  UpdatePermission,
  Suggestions,
} = require('actions-on-google');

Utenti che hanno attivato l'opzione

Prima di poter inviare notifiche push agli utenti, devi chiederne l'attivazione. A questo scopo, puoi mostrare loro un chip di suggerimento in cui chiedere l'autorizzazione. Quando il proprietario concede l'autorizzazione, riceverai un ID utente da inviare notifiche push a quell'utente.

Mostra chip di suggerimenti per l'attivazione

Prima che gli utenti possano ricevere notifiche push dall'azione, devi mostrare loro un chip di suggerimento per invitarli ad attivare le notifiche push.

Il seguente snippet di codice invia all'utente il messaggio "Avvisami di nuovi suggerimenti" suggerimento insieme a un testo di risposta.

Nodo Dialogflow.js
di Gemini Advanced.
conv.ask('I can send you push notifications. Would you like that?');
conv.ask(new Suggestions('Send notifications'));
SDK Actions Node.js
di Gemini Advanced.
conv.ask(' I can send you push notifications. Would you like that?');
conv.ask(new Suggestions('Send notifications'));
Java Dialogflow
di Gemini Advanced.
responseBuilder
    .add("I can send you push notifications. Would you like that?")
    .addSuggestions(new String[] {
        "Send notifications"
    });
SDK Actions SDK
di Gemini Advanced.
responseBuilder
    .add("I can send you push notifications. Would you like that?")
    .addSuggestions(new String[] {
        "Send notifications"
    });
JSON Dialogflow

Tieni presente che il codice JSON seguente descrive una risposta 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"
          }
        ]
      }
    }
  }
}
.
.
JSON SDK Actions

Tieni presente che il codice JSON seguente descrive una risposta 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"
            }
          ]
        }
      }
    }
  ]
}

Dopo che avrà toccato il chip, devi chiedere l'autorizzazione UPDATE. Il seguente codice ti mostra come eseguire questa operazione con askForUpdatePermission della libreria client Node.js.

Nodo Dialogflow.js
  1. Apri l'agente nella console Dialogflow e seleziona l'intent che stai configurando per gli aggiornamenti.
  2. Scorri verso il basso fino a Risposta e apri la scheda Assistente Google.
  3. Fai clic su Aggiungi contenuto del messaggio e seleziona Chip di suggerimento.
  4. Imposta il testo del chip su un elemento che inviti l'utente all'attivazione. Nella Esempio di suggerimenti di Actions on Google in cui abbiamo impostato il chip su Avvisami di nuovi suggerimenti.
  5. Aggiungere un altro intent Dialogflow, ad esempio setup_push. Imposta un'azione corrispondente, ad esempio setup.push. L'espressione utente di questo intent deve corrispondere al testo del chip di attivazione. nel nostro esempio Avvisami di nuovi suggerimenti.
di Gemini Advanced. Lo snippet seguente mostra come richiedere l'autorizzazione utilizzando le azioni nella libreria client di Google per Node.js:
app.intent('Subscribe to Notifications', (conv) => {
  conv.ask(new UpdatePermission({
    intent: 'Notification',
  }));
});
SDK Actions Node.js

Devi configurare la soluzione NLU per attivare una funzione che richiede se l'espressione utente corrisponde al valore delle notifiche push di attivazione/disattivazione. Ecco un esempio molto semplice basato sulla corrispondenza delle stringhe:

conv.ask(new UpdatePermission({
  intent: 'Notification',
}));
.
.
Java Dialogflow
  1. Apri l'agente nella console Dialogflow e seleziona l'intent che stai configurando per gli aggiornamenti.
  2. Scorri verso il basso fino a Risposta e apri la scheda Assistente Google.
  3. Fai clic su Aggiungi contenuto del messaggio e seleziona Chip di suggerimento.
  4. Imposta il testo del chip su un elemento che inviti l'utente all'attivazione. Nella Esempio di suggerimenti di Actions on Google in cui abbiamo impostato il chip su Avvisami di nuovi suggerimenti.
  5. Aggiungere un altro intent Dialogflow, ad esempio setup_push. Imposta un'azione corrispondente, ad esempio setup.push. L'espressione utente di questo intent deve corrispondere al testo del chip di attivazione. nel nostro esempio Avvisami di nuovi suggerimenti.
di Gemini Advanced. Lo snippet seguente mostra come richiedere l'autorizzazione utilizzando le azioni nella libreria client Java/Kotlin di Google:
@ForIntent("Subscribe to Notifications")
public ActionResponse subscribeToNotifications(ActionRequest request) {
  ResponseBuilder responseBuilder = getResponseBuilder(request);
  responseBuilder.add(new UpdatePermission().setIntent("Notification"));
  return responseBuilder.build();
}
SDK Actions SDK

Devi configurare la soluzione NLU per attivare una funzione che richiede se l'espressione utente corrisponde al valore delle notifiche push di attivazione/disattivazione. Ecco un esempio molto semplice basato sulla corrispondenza delle stringhe:

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

Tieni presente che il codice JSON seguente descrive una risposta webhook utilizzando 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"
          }
        }
      }
    }
  }
}
.
.
JSON SDK Actions

Tieni presente che il codice JSON seguente descrive una risposta webhook utilizzando l'SDK Actions.

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

Finalizza l'abbonamento

Per finalizzare la sottoscrizione dal webhook Node.js, devi salvare il l'ID notifiche dell'utente e l'intent che ha selezionato. Entrambi vengono passati come se l'utente concede l'autorizzazione.

Se l'azione è creata con Dialogflow, devi:

  • Aggiungi un intent che gestisca actions_intent_PERMISSION.
  • Specifica il nome dell'azione dell'intent in base a qualcosa che il webhook può fare. filtra per dopo.

Il codice seguente mostra come gestire un intent Dialogflow con un intent denominata finish_push_setup con il nome dell'azione finish.push.setup:

Nodo Dialogflow.js
di Gemini Advanced.
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 Actions Node.js
di Gemini Advanced.
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.`);
  }
});
Java Dialogflow
di Gemini Advanced.
@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 Actions SDK
di Gemini Advanced.
@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();
}
JSON Dialogflow

Tieni presente che il codice JSON seguente descrive una richiesta al 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"
}
.
.
JSON SDK Actions

Tieni presente che il codice JSON seguente descrive una richiesta al 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"
        }
      ]
    }
  ]
}

Invia notifiche

Puoi inviare notifiche push agli utenti utilizzando l'API Actions. Per utilizzare questa API, attivare l'API nel progetto Google Cloud, configurare e scaricare Chiave dell'account di servizio JSON. Vedi il passaggio 8 nelle istruzioni in questo esempio di codice.

Potrai quindi utilizzare la libreria client OAuth2 di Google per scambiare la chiave dell'account di servizio un token di accesso e utilizzalo per autenticare le richieste all'API Actions.

Generazione di una chiave dell'account di servizio

  1. Vai a questo URL, sostituendo "example-project-1" alla fine con l'ID progetto nella console Actions: https://console.developers.google.com/apis/api/actions.googleapis.com/overview?project=example-project-1
  2. Fai clic sul pulsante Attiva, se presente. In caso contrario, vai al passaggio 3.
  3. Vai a questo URL, sostituendo "example-project-1" alla fine con l'ID progetto nella console Actions: https://console.developers.google.com/apis/credentials?project=example-project-1
  4. Fai clic su Crea credenziali > Chiave account di servizio.
  5. Fai clic sulla casella Seleziona in Account di servizio e fai clic su Nuovo servizio. Account.
  6. Assegna all'account di servizio un nome, ad esempio "notifiche" e il Ruolo di Proprietario progetto.
  7. Seleziona il tipo di chiave JSON e fai clic su Crea. Una chiave dell'account di servizio JSON scaricati sul computer locale.

Scambia la chiave con un token di accesso e invia una notifica

Per inviare una notifica tramite l'API Actions, devi scambiare la chiave dell'account di servizio per un token di accesso. Ti consigliamo di utilizzare un client API di Google libreria per questo argomento. Nella serie di snippet di codice che segue, utilizziamo libreria client Node.js dell'API di Google.

  1. Installa la libreria client dell'API di Google e richiedi: npm install googleapis request --save
  2. Usa il seguente codice per ottenere un token di accesso dalla chiave dell'account di servizio e invia una notifica push:
di Gemini Advanced.
.
Dialogflow Node.js
di Gemini Advanced.
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 Actions Node.js
di Gemini Advanced.
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}`);
    });
  }
});
Java Dialogflow
di Gemini Advanced.
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 Actions SDK
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);
}