> ## Documentation Index
> Fetch the complete documentation index at: https://documentation.onesignal.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Notifications en double

> Résolvez les problèmes de notifications push en double causés par des conflits de SDK, des nouvelles tentatives côté serveur, des environnements multi-applications et des bugs spécifiques à la plateforme.

Les notifications en double se produisent lorsque le même appareil reçoit le même contenu de message plus d'une fois. Ce guide couvre les causes les plus courantes et comment les résoudre.

Si le même utilisateur voit la notification sur plusieurs appareils (téléphone, tablette, ordinateur), il s'agit du comportement attendu en fonction de votre configuration de ciblage (segments, ID externes, etc.). Pour les messages in-app en double, consultez le guide de [dépannage des messages in-app](./in-app-message-troubleshooting#duplicated-in-app-messages).

<Info>
  Apple a reconnu un bug dans iOS 17 qui provoquait des doublons. Cela a été corrigé dans iOS 17.3. [En savoir plus](https://forums.developer.apple.com/forums/thread/747044).
</Info>

## Commencer ici

Choisissez la section qui correspond le mieux à votre situation :

* Votre serveur relance des appels API échoués ou votre pipeline backend peut envoyer en double → [Même message envoyé plusieurs fois](#même-message-envoyé-plusieurs-fois)
* Votre application utilise Firebase ou un autre SDK push aux côtés de OneSignal → [Gestionnaires de notifications tiers](#gestionnaires-de-notifications-tiers)
* Votre application Android personnalise les notifications dans le code (extension de service ou listener en premier plan) → [Gestionnaires de notifications Android](#gestionnaires-de-notifications-android)
* Votre application iOS implémente son propre `UNUserNotificationCenterDelegate` → [Gestionnaire en premier plan iOS](#gestionnaire-en-premier-plan-ios)
* Vous voyez des doublons uniquement sur les builds de développement ou avec plusieurs installations → [Plusieurs instances d'application](#plusieurs-instances-dapplication)

## Même message envoyé plusieurs fois

La cause la plus courante est l'envoi de la même charge utile de notification plus d'une fois via l'API OneSignal. Raisons courantes :

* Votre serveur relance les requêtes sans vérifier si la première a réussi.
* Une logique dupliquée dans votre pipeline backend envoie la même notification deux fois.
* Vous migrez vers OneSignal mais envoyez toujours des notifications depuis un fournisseur précédent. Évitez d'envoyer depuis les deux systèmes en même temps.

<Card title="Requêtes API idempotentes" icon="rotate" href="/reference/idempotent-notification-requests">
  Évitez les messages en double en réutilisant des clés d'idempotence lors des nouvelles tentatives.
</Card>

## Gestionnaires de notifications tiers

Des doublons peuvent se produire lorsque d'autre code dans votre application traite la charge utile push de OneSignal et affiche sa propre notification en plus de celle de OneSignal. Cela inclut :

* D'autres SDK de push distant (par exemple, Firebase Cloud Messaging) qui reçoivent la même charge utile.
* Des gestionnaires de messages personnalisés tels qu'un `FirebaseMessagingService` sur Android ou un `UNUserNotificationCenterDelegate` sur iOS qui lisent la charge utile entrante et construisent une notification locale à partir de celle-ci.

Le SDK OneSignal filtre automatiquement les charges utiles OneSignal lorsqu'il est le seul gestionnaire. Le code tiers ne sait pas les filtrer à moins que vous ne le lui indiquiez.

### Identification des notifications OneSignal

Chaque notification OneSignal inclut un objet `custom` avec une clé `i` contenant l'UUID de la notification OneSignal :

```json JSON theme={null}
{
  "custom": {
    "i": "the-notification-id"
  }
}
```

Pour la référence complète de la charge utile, consultez [Structure de charge utile personnalisée OneSignal](./osnotification-payload#custom-onesignal-payload-structure).

### Filtrage des notifications OneSignal dans les gestionnaires tiers

Dans tout gestionnaire non-OneSignal, vérifiez la clé `custom.i` et retournez en avance lorsqu'elle est présente. OneSignal gère alors ses propres charges utiles tandis que votre autre code continue de traiter les siennes.

<Tabs>
  <Tab title="Android">
    Dans un `FirebaseMessagingService` personnalisé ou un autre gestionnaire de messages distants :

    ```kotlin Kotlin theme={null}
    override fun onMessageReceived(remoteMessage: RemoteMessage) {
        val customJson = remoteMessage.data["custom"]
        if (customJson != null) {
            try {
                val custom = JSONObject(customJson)
                if (custom.has("i")) {
                    // Notification OneSignal — laisser le SDK OneSignal la gérer
                    return
                }
            } catch (e: JSONException) {
                // Pas une charge utile OneSignal, continuer
            }
        }

        // Gérer votre propre notification ici
    }
    ```
  </Tab>

  <Tab title="iOS">
    Dans votre `UNUserNotificationCenterDelegate` ou un gestionnaire de notifications personnalisé :

    ```swift Swift theme={null}
    func userNotificationCenter(_ center: UNUserNotificationCenter,
                                willPresent notification: UNNotification,
                                withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        let userInfo = notification.request.content.userInfo

        if let custom = userInfo["custom"] as? [String: Any], custom["i"] != nil {
            // Notification OneSignal — laisser le SDK OneSignal la gérer
            completionHandler([])
            return
        }

        // Gérer votre propre notification ici
    }
    ```
  </Tab>
</Tabs>

<Tip>
  Si vous contrôlez la structure de la charge utile envoyée par votre autre fournisseur, ajoutez une clé marqueur distincte (par exemple, `my_app_notification: true`) et filtrez dans les deux sens — gérez uniquement les notifications contenant votre marqueur dans votre propre code, et laissez OneSignal gérer les notifications contenant la clé `custom.i`.
</Tip>

## Gestionnaires de notifications Android

OneSignal expose deux callbacks Android qui vous permettent d'intercepter et de personnaliser une notification avant qu'elle ne s'affiche :

* `onNotificationReceived` dans une [extension de service de notification](./service-extensions) — s'exécute pour chaque push, y compris lorsque l'application est en arrière-plan.
* `onWillDisplay` dans un [listener de cycle de vie en premier plan](./mobile-sdk-reference#addforegroundlifecyclelistener-push) — s'exécute uniquement lorsque l'application est en premier plan.

Des doublons se produisent lorsque ces callbacks affichent la notification en plus de l'affichage automatique de OneSignal.

### La règle `preventDefault()` et `display()`

OneSignal affiche chaque notification automatiquement à moins que vous ne la supprimiez avec `event.preventDefault()`. Deux erreurs courantes provoquent des doublons :

* Appeler `event.getNotification().display()` sans d'abord appeler `event.preventDefault()` — affiche la notification deux fois.
* Publier une notification séparée avec [`NotificationManagerCompat.notify()`](https://developer.android.com/reference/androidx/core/app/NotificationManagerCompat) tandis que OneSignal affiche également l'originale.

Un seul chemin d'affichage doit être actif — soit `display()` de OneSignal, soit votre propre `NotificationManagerCompat.notify()`, jamais les deux.

<CodeGroup>
  ```kotlin Kotlin theme={null}
  override fun onNotificationReceived(event: INotificationReceivedEvent) {
      event.preventDefault()

      val notification = event.notification
      notification.setExtender { builder ->
          builder.setColor(0xFF0000FF.toInt())
      }
      notification.display()
  }
  ```

  ```java Java theme={null}
  @Override
  public void onNotificationReceived(INotificationReceivedEvent event) {
      event.preventDefault();

      IDisplayableMutableNotification notification = event.getNotification();
      notification.setExtender(builder ->
          builder.setColor(0xFF0000FF)
      );
      notification.display();
  }
  ```
</CodeGroup>

La même règle s'applique dans `onWillDisplay` dans un listener de cycle de vie en premier plan :

```kotlin Kotlin theme={null}
OneSignal.Notifications.addForegroundLifecycleListener(object : INotificationLifecycleListener {
    override fun onWillDisplay(event: INotificationWillDisplayEvent) {
        event.preventDefault()

        // Affichez votre propre interface ou appelez event.notification.display() pour afficher la notification OneSignal
    }
})
```

<Warning>
  Si vous appelez `preventDefault()` mais n'appelez jamais `display()`, la notification est silencieusement abandonnée et l'utilisateur ne la voit pas. Chaque chemin de code doit soit appeler `display()` une fois, soit intentionnellement supprimer la notification.
</Warning>

<Warning>
  Si vous utilisez à la fois une extension de service de notification et un listener de cycle de vie en premier plan, assurez-vous qu'un seul gestionnaire affiche la notification pour un état d'application donné. Appeler `display()` depuis les deux produit des doublons.
</Warning>

### Travail asynchrone dans les callbacks

Lorsque vous effectuez un travail en arrière-plan (appels réseau, recherches en base de données) avant l'affichage, appelez `preventDefault()` de manière synchrone dans le callback et appelez `display()` uniquement après la fin du travail asynchrone. Retourner du callback sans `preventDefault()` permet à OneSignal d'afficher la notification, et un appel ultérieur à `display()` produit un doublon.

## Gestionnaire en premier plan iOS

OneSignal se définit comme le `UNUserNotificationCenterDelegate` lors de l'initialisation du SDK. Si votre application implémente également la gestion des notifications en premier plan, la notification peut s'afficher deux fois — une fois depuis OneSignal et une fois depuis votre code.

Schémas courants qui provoquent des doublons :

* Implémenter votre propre `UNUserNotificationCenterDelegate` sans transférer les appels à OneSignal, puis appeler `completionHandler([.banner, .sound])` et afficher une alerte in-app personnalisée depuis la même méthode.
* Planifier une notification locale (`UNUserNotificationCenter.current().add(...)`) en réponse à un push entrant que OneSignal affiche également.

Pour contrôler l'affichage en premier plan sans provoquer de doublons, utilisez le [listener de cycle de vie en premier plan](./mobile-sdk-reference#addforegroundlifecyclelistener-push) de OneSignal et appelez `event.preventDefault()` lorsque vous souhaitez afficher la notification vous-même :

```swift Swift theme={null}
OneSignal.Notifications.addForegroundLifecycleListener(self)

func onWillDisplay(event: OSNotificationWillDisplayEvent) {
    event.preventDefault()

    // Affichez votre propre interface ou appelez event.notification.display() pour afficher la notification OneSignal
}
```

## Plusieurs instances d'application

<Tabs>
  <Tab title="Android">
    Des doublons peuvent se produire lorsque vous avez à la fois les versions de production et de développement de votre application installées. Chaque application a un nom de package unique et reçoit son propre jeton push.

    Appuyez longuement sur la notification pour confirmer quelle instance d'application l'a envoyée.
  </Tab>

  <Tab title="iOS">
    Si deux enregistrements d'appareil dans OneSignal partagent le même jeton push, l'appareil peut recevoir deux notifications. Cela peut se produire lorsque le même jeton est importé ou enregistré plusieurs fois. OneSignal inclut des vérifications pour empêcher cela, mais des cas limites peuvent les contourner.
  </Tab>

  <Tab title="Web">
    Les doublons de web push sont causés par l'abonnement à plusieurs origines utilisant le même ID d'application OneSignal. Une [origine](https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy) est la combinaison de schéma, d'hôte et de port que le navigateur utilise pour délimiter les abonnements push.

    Par exemple, un utilisateur abonné à `https://example.com` et `https://sub.example.com` compte comme deux abonnements, et un envoi utilisant le même ID d'application atteint les deux.

    Pour corriger cela :

    1. [Réinitialisez les données du navigateur et les autorisations push](./troubleshooting-web-push) par origine.
    2. Si de nombreux utilisateurs sont concernés, créez une nouvelle application OneSignal et utilisez le nouvel ID d'application dans le code d'initialisation de votre site.
    3. Demandez aux utilisateurs de revisiter le site et de se réabonner.

    S'abonner sur plusieurs navigateurs ou profils de navigateur entraîne également plusieurs notifications.
  </Tab>
</Tabs>

## Conseils de diagnostic

Pour déboguer les doublons plus rapidement, collectez et envoyez les éléments suivants au support OneSignal :

* ID d'abonnement OneSignal de l'appareil ayant reçu les doublons
* ID du message OneSignal ou un lien vers le message dans le tableau de bord
* Liste des autres bibliothèques ou plugins dans votre application
* [Journal de débogage reproduisant le problème](./capturing-a-debug-log)
* Étapes de reproduction détaillées

## FAQ

### Que se passe-t-il si j'ai deux SDK de notification dans mon application ?

Les deux SDK peuvent traiter et afficher indépendamment la même notification. OneSignal filtre ses propres notifications automatiquement, mais les autres SDK ne le font pas. Filtrez les charges utiles OneSignal des gestionnaires de votre autre SDK en vérifiant la clé `custom.i`. Consultez [Gestionnaires de notifications tiers](#gestionnaires-de-notifications-tiers) pour des exemples de code.

### Comment envoyer des push depuis un fournisseur précédent et OneSignal en même temps ?

Vous pouvez faire la transition progressivement, mais évitez d'envoyer le même message depuis les deux fournisseurs.

* **Android** : Supprimez l'ancien code de gestion des notifications du SDK lors de l'intégration de OneSignal et de la publication de l'application. Au fur et à mesure que les utilisateurs mettent à jour, ils cesseront de recevoir des push de l'ancien fournisseur.
* **iOS** : Vous pouvez continuer à envoyer depuis l'ancien fournisseur temporairement pendant que les utilisateurs mettent à jour. Une fois la transition complète, envoyez uniquement depuis OneSignal pour éviter les doublons.

### Comment éviter plusieurs notifications pour des mises à jour qui changent rapidement ?

Utilisez un [`collapse_id`](/reference/push-notification#body-parameters) dans l'API [Créer une notification](/reference/push-notification) pour remplacer les notifications précédentes plutôt que de les empiler. Lorsque plusieurs notifications partagent le même `collapse_id`, chaque nouvelle remplace la précédente dans la barre de notifications. Cela est utile pour les mises à jour de cours boursiers, les scores en direct, les ETA de livraison et les mises à jour fréquentes similaires.

## Pages associées

<Columns cols={2}>
  <Card title="Dépannage du SDK mobile" icon="mobile" href="./mobile-troubleshooting">
    Résolvez les problèmes courants liés à la livraison des notifications push sur iOS et Android.
  </Card>

  <Card title="Dépannage du web push" icon="browser" href="./troubleshooting-web-push">
    Déboguez les problèmes d'abonnement, de service worker et de livraison du web push.
  </Card>

  <Card title="Dépannage des messages in-app" icon="message" href="./in-app-message-troubleshooting">
    Corrigez les problèmes d'affichage, de déclencheurs et de doublons des messages in-app.
  </Card>

  <Card title="Extensions de service mobiles" icon="gear" href="./service-extensions">
    Interceptez et personnalisez les notifications push avant l'affichage sur iOS et Android.
  </Card>

  <Card title="Notifications non affichées (web)" icon="bell-slash" href="./notifications-not-shown-web-push">
    Résolvez les problèmes de notifications web push envoyées mais non affichées.
  </Card>
</Columns>
