Notificaciones push (Dialogflow)

Explorar en Dialogflow

Haz clic en Continuar para importar nuestra muestra de notificaciones en Dialogflow. Luego, sigue los pasos que se indican a continuación para implementar y probar la muestra:

  1. Ingresa un nombre de agente y crea un agente de Dialogflow nuevo para la muestra.
  2. Una vez que el agente termine de importar, haz clic en Ir al agente (Go to agent).
  3. En el menú de navegación principal, ve a Entrega.
  4. Habilita el Editor intercalado y, luego, haz clic en Implementar. El editor contiene el código de muestra.
  5. En el menú de navegación principal, ve a Integraciones y, luego, haz clic en Asistente de Google.
  6. En la ventana modal que aparece, habilita Auto-preview changes y haz clic en Test para abrir el simulador de Actions.
  7. En el simulador, ingresa Talk to my test app para probar la muestra.
Continuar

Tu Acción puede enviar notificaciones push a los usuarios cuando sea relevante, como enviarles un recordatorio cuando se acerque la fecha de vencimiento de una tarea.

En esta guía, usamos la muestra de sugerencias de Actions on Google como referencia para mostrarte cómo configurar notificaciones push para tu Acción. Cuando los usuarios invocan esta acción, se pregunta si quieren escuchar una sugerencia sobre el desarrollo de su propia acción. Los usuarios pueden elegir una categoría específica o seleccionada al azar para la propina, o bien pueden elegir escuchar la sugerencia más reciente.

Superficies compatibles

Las notificaciones push están disponibles en dispositivos iOS y Android (los dispositivos iOS deben tener la app de Asistente instalada para recibir notificaciones push). Por el momento, no son compatibles con bocinas activadas por voz, pantallas inteligentes ni otras plataformas.

Requisitos previos

Al menos una de las acciones de tu proyecto de acciones debe configurarse como un intent de activación que se invocará cuando el usuario presione una notificación recibida de Asistente.

Tus acciones no se pueden configurar para activar el intent de bienvenida predeterminado desde una notificación push.

Configuración de la consola

Para agregar compatibilidad con notificaciones push a tu acción, haz lo siguiente:

  1. Ve a la Consola de Actions y navega a Build > Actions.

  2. Haz clic en la acción que coincida con el intent de activación adicional para el que deseas habilitar las notificaciones push.

    Para la muestra de sugerencias de Actions on Google, selecciona "tell_latest_tip".

  3. Desplázate hacia abajo hasta la sección Participación de los usuarios y activa ¿Quieres enviar notificaciones push?

  4. Ingresa un Título del contenido.

    Para el ejemplo de sugerencias de Actions on Google, el título podría ser "Se agregó una sugerencia nueva".

  5. Haz clic en Guardar.

Importaciones

Para los fines de las siguientes secciones, en tu código de entrega, deberás declarar las siguientes importaciones:

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

Habilitar a los usuarios

Antes de poder enviar notificaciones push a los usuarios, debes pedirles que las habiliten. Para ello, muéstrales un chip de sugerencias para pedirles permiso. Cuando otorguen el permiso, recibirás una actualización del ID de usuario para enviarle notificaciones push a ese usuario.

Mostrar chips de sugerencias para habilitar

Antes de que los usuarios puedan recibir notificaciones push de tu Acción, debes mostrarles un chip de sugerencias para invitarlos a habilitar las notificaciones push.

El siguiente fragmento de código envía al usuario el chip de sugerencias “Alertarme sobre nuevas sugerencias” junto con una respuesta de texto.

Dialogflow para Node.js
conv.ask('I can send you push notifications. Would you like that?');
conv.ask(new Suggestions('Send notifications'));
SDK de Actions para 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 de Actions SDK para Java
responseBuilder
    .add("I can send you push notifications. Would you like that?")
    .addSuggestions(new String[] {
        "Send notifications"
    });
JSON de Dialogflow

Ten en cuenta que el siguiente JSON describe una respuesta de 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 del SDK de Actions

Ten en cuenta que el siguiente JSON describe una respuesta de 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"
            }
          ]
        }
      }
    }
  ]
}

Después de que presione el chip, deberás pedirle el permiso UPDATE. En el siguiente código, se muestra cómo hacerlo con la función askForUpdatePermission de la biblioteca cliente de Node.js.

Dialogflow para Node.js
  1. Abre tu agente en la consola de Dialogflow y selecciona el intent que estás configurando para actualizaciones.
  2. Desplázate hacia abajo hasta Respuesta y abre la pestaña del Asistente de Google.
  3. Haz clic en Agregar contenido del mensaje y selecciona Chips de sugerencias.
  4. Establece el texto del chip en un elemento que invite al usuario a aceptar. En la muestra de sugerencias de Actions on Google, configuramos el chip para Alertarme sobre sugerencias nuevas.
  5. Agrega otro intent de Dialogflow, llamado por ejemplo setup_push, y configura la acción correspondiente, como setup.push. La expresión del usuario de este intent debe coincidir con el texto del chip de habilitación, como se muestra en nuestro ejemplo Alerta de sugerencias nuevas.
En el siguiente fragmento, se muestra cómo solicitar el permiso con la biblioteca cliente de Actions on Google para Node.js:
app.intent('Subscribe to Notifications', (conv) => {
  conv.ask(new UpdatePermission({
    intent: 'Notification',
  }));
});
SDK de Actions para Node.js

Debes configurar tu solución de CLN para activar una función que solicite el permiso si la expresión del usuario coincide con el valor de la solicitud de habilitación de las notificaciones push. Aquí hay un ejemplo muy básico basado en la coincidencia de cadenas:

conv.ask(new UpdatePermission({
  intent: 'Notification',
}));
Dialogflow Java
  1. Abre tu agente en la consola de Dialogflow y selecciona el intent que estás configurando para actualizaciones.
  2. Desplázate hacia abajo hasta Respuesta y abre la pestaña del Asistente de Google.
  3. Haz clic en Agregar contenido del mensaje y selecciona Chips de sugerencias.
  4. Establece el texto del chip en un elemento que invite al usuario a aceptar. En la muestra de sugerencias de Actions on Google, configuramos el chip para Alertarme sobre sugerencias nuevas.
  5. Agrega otro intent de Dialogflow, llamado por ejemplo setup_push, y configura la acción correspondiente, como setup.push. La expresión del usuario de este intent debe coincidir con el texto del chip de habilitación, como se muestra en nuestro ejemplo Alerta de sugerencias nuevas.
En el siguiente fragmento, se muestra cómo solicitar el permiso mediante la biblioteca cliente de Actions on Google para 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 de Actions para Java

Debes configurar tu solución de CLN para activar una función que solicite el permiso si la expresión del usuario coincide con el valor de la solicitud de habilitación de las notificaciones push. Aquí hay un ejemplo muy básico basado en la coincidencia de cadenas:

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

Ten en cuenta que el siguiente JSON describe una respuesta de webhook mediante 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 del SDK de Actions

Ten en cuenta que el siguiente JSON describe una respuesta de webhook con el SDK de 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"
            }
          }
        }
      ]
    }
  ]
}

Finaliza la suscripción

Para finalizar la suscripción desde tu webhook de Node.js, debes guardar el ID de notificaciones del usuario y el intent que seleccionó. Ambos se pasan como argumentos si el usuario otorga el permiso.

Si tu Acción está compilada con Dialogflow, debes hacer lo siguiente:

  • Agrega un intent que controle actions_intent_PERMISSION.
  • Especifica el nombre de la Action del intent en algo que tu webhook pueda filtrar más adelante.

En el siguiente código, se muestra cómo controlar un intent de Dialogflow con un intent llamado finish_push_setup con el nombre de acción finish.push.setup:

Dialogflow para 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 de Actions para 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 de Actions SDK para 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();
}
JSON de Dialogflow

Ten en cuenta que el siguiente JSON describe una solicitud 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 del SDK de Actions

Ten en cuenta que el siguiente JSON describe una solicitud 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"
        }
      ]
    }
  ]
}

Envíe notificaciones

Puedes enviar notificaciones push a los usuarios mediante la API de Actions. Para usar esta API, debes activarla en tu proyecto de Google Cloud, configurar y descargar una clave de cuenta de servicio JSON. Consulta el paso 8 de las instrucciones que se indican en la muestra de código aquí.

Luego, puedes usar la biblioteca cliente de Google OAuth2 para intercambiar la clave de la cuenta de servicio por un token de acceso y usar el token para autenticar tus solicitudes a la API de Actions.

Obtener una clave de cuenta de servicio

  1. Ve a esta URL y reemplaza “example-project-1” al final por tu ID del proyecto en la Consola de Actions: https://console.developers.google.com/apis/api/actions.googleapis.com/overview?project=example-project-1.
  2. Si ves el botón Habilitar, haz clic en él. De lo contrario, continúa con el paso 3.
  3. Ve a esta URL y reemplaza “example-project-1” al final por tu ID del proyecto en la Consola de Actions: https://console.developers.google.com/apis/credentials?project=example-project-1.
  4. Haz clic en Crear credenciales > Clave de cuenta de servicio.
  5. Haz clic en el cuadro Seleccionar debajo de Cuenta de servicio y, luego, en Cuenta de servicio nueva.
  6. Asígnale un nombre a la cuenta de servicio, como “notificaciones” y la Función de Propietario del proyecto.
  7. Selecciona el tipo de clave JSON y haz clic en Crear. Se descarga una clave de cuenta de servicio JSON en tu máquina local.

Intercambia la clave por un token de acceso y envía una notificación

Para enviar una notificación a través de la API de Actions, debes intercambiar la clave de la cuenta de servicio por un token de acceso. Para ello, recomendamos usar una biblioteca cliente de la API de Google. En la serie de fragmentos de código que siguen, usamos la biblioteca cliente de Node.js de la API de Google.

  1. Instala la biblioteca cliente de la API de Google y solicita: npm install googleapis request --save.
  2. Usa el siguiente código para obtener un token de acceso de la clave de la cuenta de servicio y enviar una notificación push:
Dialogflow para 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 de Actions para 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 de Actions SDK para 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);
}