Saltar al contenido principal
Las extensiones de servicio de notificaciones te permiten interceptar y modificar notificaciones push antes de que se muestren al usuario. Esto habilita el manejo de datos en segundo plano, estilos personalizados, archivos adjuntos de medios enriquecidos, entrega confirmada y opciones de botones de acción.
Puedes acceder a los datos de tus notificaciones push enviadas desde OneSignal a través de la clase OSNotification

Extensión de servicio de notificaciones de Android

Te permite procesar la notificación antes de que se muestre al usuario. Los casos de uso más comunes incluyen:
  • Recibir datos en segundo plano con o sin mostrar una notificación.
  • Anular configuraciones específicas de notificación según la lógica del lado del cliente, como el color de énfasis personalizado, el patrón de vibración u otras opciones de NotificationCompat disponibles.
Para más detalles, consulta la documentación de Android sobre las opciones de NotificationCompat.

Paso 1: Crear una clase para la extensión de servicio

Crea una clase que implemente INotificationServiceExtension e implementa el método onNotificationReceived. El parámetro del método onNotificationReceived es event de tipo INotificationReceivedEvent.
package your.package.name

import androidx.annotation.Keep;
import com.onesignal.notifications.IActionButton;
import com.onesignal.notifications.IDisplayableMutableNotification;
import com.onesignal.notifications.INotificationReceivedEvent;
import com.onesignal.notifications.INotificationServiceExtension;

@Keep // Keep is required to prevent minification from renaming or removing your class
public class NotificationServiceExtension implements INotificationServiceExtension {

     @Override
     public void onNotificationReceived(INotificationReceivedEvent event) {
        IDisplayableMutableNotification notification = event.getNotification();

        if (notification.getActionButtons() != null) {
           for (IActionButton button : notification.getActionButtons()) {
              // you can modify your action buttons here
           }
        }

     /* Add customizations here. See examples below for additional methods to modify the notification*/
     }
}

La anotación @Keep es necesaria para evitar que ProGuard o R8 renombre o elimine tu clase durante la minificación.

Paso 2: Personalizar la notificación

Los siguientes ejemplos muestran personalizaciones comunes que puedes implementar en la clase de extensión de servicio de notificaciones.
Usa event.preventDefault() para suprimir la visualización de la notificación. Luego puedes llamar a event.getNotification().display() para mostrarla más tarde, o no llamarla nunca para descartarla silenciosamente.
event.preventDefault();

//Do some async work, then decide to show or dismiss
new Thread(() -> {
    try {
        Thread.sleep(1000);
    } catch (InterruptedException ignored) {}

    //Manually show the notification
    event.getNotification().display();
}).start();
Llamar a event.preventDefault() sin llamar nunca a display() descartará la notificación silenciosamente. Para más información, consulta Notificaciones duplicadas.

Paso 3: Agregar la extensión de servicio a tu AndroidManifest.xml

Agrega el nombre de la clase y el valor como meta-data dentro del archivo AndroidManifest.xml en la etiqueta de la aplicación. Ignora cualquier advertencia de “no utilizado”.
XML
<application>
  <meta-data
    android:name="com.onesignal.NotificationServiceExtension"
    android:value="com.onesignal.example.NotificationServiceExtension" />
</application>
Reemplaza com.onesignal.example.NotificationServiceExtension con el nombre completamente calificado de tu clase.

Extensión de servicio de notificaciones de iOS

La UNNotificationServiceExtension te permite modificar el contenido de las notificaciones push antes de que se muestren al usuario y es necesaria para otras funciones importantes como: Probablemente ya lo configuraste si seguiste nuestras instrucciones de configuración del SDK móvil para tu aplicación, pero esta sección explicará cómo acceder a los datos del payload de notificación de OneSignal y solucionar cualquier problema que puedas tener.

Obtener el payload push de iOS

La anulación de didReceive(_:withContentHandler:) llama a OneSignalExtension.didReceiveNotificationExtensionRequest, que pasa el bestAttemptContent a OneSignal antes de que se muestre al usuario. Puedes leer o modificar bestAttemptContent antes de que se llame a ese método. En este ejemplo, enviamos una notificación con los siguientes datos:
JSON
{
  "app_id": "YOUR_APP_ID",
  "target_channel": "push",
  "headings": {"en": "The message title"},
  "contents": {"en": "The message contents"},
  "data":{
    "additional_data_key_1":"value_1",
    "additional_data_key_2":"value_2"
    },
  "include_subscription_ids": ["SUBSCRIPTION_ID_1"]
}
Accede a estos data adicionales dentro de la OneSignalNotificationServiceExtension a través de la clave a dentro del diccionario custom de userInfo:
if let bestAttemptContent = bestAttemptContent {

    if let customData = bestAttemptContent.userInfo["custom"] as? [String: Any],
       let additionalData = customData["a"] as? [String: Any] {

        if let jsonData = try? JSONSerialization.data(withJSONObject: additionalData, options: .prettyPrinted),
           let jsonString = String(data: jsonData, encoding: .utf8) {
            print("The additionalData dictionary in JSON format:\n\(jsonString)")
        } else {
            print("Failed to convert additionalData to JSON format.")
        }
    }

    if let messageData = bestAttemptContent.userInfo["aps"] as? [String: Any],
       let apsData = messageData["alert"] as? [String: Any],
       let body = apsData["body"] as? String,
       let title = apsData["title"] as? String {
        print("The message contents is: \(body), message headings is: \(title)")
    } else {
        print("Unable to retrieve apsData")
    }

    OneSignalExtension.didReceiveNotificationExtensionRequest(self.receivedRequest,
                                                              with: bestAttemptContent,
                                                              withContentHandler: self.contentHandler)
}
Ejemplo de salida en consola:
The additionalData dictionary in JSON format:
{
  "additional_data_key_1" : "value_1",
  "additional_data_key_2" : "value_2"
}
The message contents is: The message contents, message headings is: The message title

Solución de problemas de la extensión de servicio de notificaciones de iOS

Esta guía es para depurar problemas con imágenes, botones de acción o entregas confirmadas que no aparecen en aplicaciones móviles de iOS.

Verifica tu configuración de Xcode

En General > Targets, asegúrate de que tu target de aplicación principal y el target OneSignalNotificationServiceExtension tengan los mismos valores correctos de:
  • Supported Destinations
  • Minimum Deployment (iOS 14.5 o superior)
Si usas Cocoapods, asegúrate de que coincidan con tu target principal en el Podfile para evitar errores de compilación.
Xcode General tab showing Supported Destinations and Minimum Deployment for the main app target
Xcode General tab showing Supported Destinations and Minimum Deployment for the notification service extension target
Continuando en la pestaña OneSignalNotificationServiceExtension > Info, expande la clave NSExtension. Asegúrate de ver:
XML
 <dict>
   <key>NSExtensionPointIdentifier</key>
   <string>com.apple.usernotifications.service</string>
   <key>NSExtensionPrincipalClass</key>
   <string>$(PRODUCT_MODULE_NAME).NotificationService</string>
 </dict>
Ejemplo:
Xcode Info tab showing the NSExtension dictionary with NSExtensionPointIdentifier and NSExtensionPrincipalClass keys
Si usas Objective-C, en lugar de $(PRODUCT_MODULE_NAME).NotificationService usa NotificationService.

Desactiva “Copy only when installing”

Selecciona tu target de aplicación principal > Build Phases > Embed App Extensions. Asegúrate de que “Copy only when installing” NO esté marcado. Desmárcalo si lo está:
Xcode Build Phases tab showing Embed App Extensions with Copy only when installing unchecked

Depuración de la extensión de servicio de notificaciones de iOS

Sigue estos pasos para verificar que la extensión de servicio de notificaciones esté configurada correctamente.

1. Actualizar el código OneSignalNotificationServiceExtension

Abre NotificationService.m o NotificationService.swift y reemplaza todo el contenido del archivo con el código a continuación. Esto agrega registros para ayudar a verificar que la extensión se está ejecutando. Reemplaza YOUR_BUNDLE_ID con tu Bundle ID real.
import UserNotifications
import OneSignalExtension
import os.log

class NotificationService: UNNotificationServiceExtension {

    var contentHandler: ((UNNotificationContent) -> Void)?
    var receivedRequest: UNNotificationRequest!
    var bestAttemptContent: UNMutableNotificationContent?

    override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
        self.receivedRequest = request
        self.contentHandler = contentHandler
        self.bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)

        let userInfo = request.content.userInfo
        let custom = userInfo["custom"]
        print("Running NotificationServiceExtension: userInfo = \(userInfo.description)")
        print("Running NotificationServiceExtension: custom = \(custom.debugDescription)")
        os_log("%{public}@", log: OSLog(subsystem: "YOUR_BUNDLE_ID", category: "OneSignalNotificationServiceExtension"), type: OSLogType.debug, userInfo.debugDescription)

        if let bestAttemptContent = bestAttemptContent {
            print("Running NotificationServiceExtension")
            bestAttemptContent.body = "[Modified] " + bestAttemptContent.body

            OneSignalExtension.didReceiveNotificationExtensionRequest(self.receivedRequest, with: bestAttemptContent, withContentHandler: self.contentHandler)
        }
    }

    override func serviceExtensionTimeWillExpire() {
        if let contentHandler = contentHandler, let bestAttemptContent =  bestAttemptContent {
            OneSignalExtension.serviceExtensionTimeWillExpireRequest(self.receivedRequest, with: self.bestAttemptContent)
            contentHandler(bestAttemptContent)
        }
    }

}

Los tipos de registro de depuración deben habilitarse en la Consola mediante Action > Include Debug Messages.

2. Cambiar tu esquema activo

Establece tu esquema activo en OneSignalNotificationServiceExtension.
Xcode toolbar showing the active scheme dropdown set to OneSignalNotificationServiceExtension

3. Compilar y ejecutar el proyecto

Compila y ejecuta el proyecto en Xcode en un dispositivo real.

4. Abrir la consola

En Xcode, selecciona Window > Devices and Simulators.
Xcode menu showing the Window dropdown with Devices and Simulators selected
Deberías ver tu dispositivo conectado. Selecciona Open Console.
Xcode Devices window showing the Open Console button for a connected device

5. Verificar la consola

En la consola:
  1. Selecciona Action > Include Debug Messages
  2. Busca OneSignalNotificationServiceExtension como CATEGORY
  3. Selecciona Start
macOS Console app showing the category filter and Start button for debugging the notification service extension
Envía a este dispositivo una notificación con un mensaje (usa la propiedad contents si envías desde la API Crear notificación). En este ejemplo, el payload es:
cURL
curl --request POST \
 --url 'https://api.onesignal.com/notifications' \
 --header 'Authorization: Key YOUR_API_KEY' \
 --header 'accept: application/json' \
 --header 'content-type: application/json' \
 --data '
{
"app_id": "YOUR_APP_ID",
"target_channel": "push",
"headings": {"en": "The message title"},
"contents": {"en": "The message contents"},
"data":{"additional_data_key_1":"value_1","additional_data_key_2":"value_2"},
"include_subscription_ids": [
"SUBSCRIPTION_ID_1"
]
}'
Deberías ver un mensaje registrado con la aplicación en ejecución y sin ejecución.
macOS Console app showing debug log output from the OneSignalNotificationServiceExtension
Si no ves un mensaje, elimina OneSignal de tu aplicación y sigue la Configuración del SDK móvil nuevamente para verificar la integración.

Preguntas frecuentes

¿Por qué no se ejecuta mi extensión de servicio de notificaciones en iOS? La extensión solo se ejecuta cuando mutable-content está configurado en el payload de la notificación. OneSignal lo configura automáticamente para notificaciones con archivos adjuntos o botones de acción. Verifica que tu configuración de Xcode coincida con la sección de solución de problemas. ¿Puedo evitar que se muestre una notificación en Android? Sí. Llama a event.preventDefault() para suprimir la visualización. Luego llama a event.getNotification().display() para mostrarla más tarde, o no la llames nunca para descartarla silenciosamente. Consulta Notificaciones duplicadas para más información. ¿Necesito la anotación @Keep en Android? Sí. Evita que ProGuard o R8 renombre o elimine tu clase que implementa INotificationServiceExtension durante la minificación.

Páginas relacionadas

Configuración del SDK móvil

Instala y configura el SDK de OneSignal para iOS y Android.

Imágenes y medios enriquecidos

Adjunta imágenes, GIFs y videos a las notificaciones push.

Entrega confirmada

Rastrea la entrega confirmada de notificaciones a dispositivos.

Notificaciones duplicadas

Soluciona notificaciones push duplicadas en todas las plataformas.