> For the complete documentation index, see [llms.txt](https://cmp.docs.sirdata.net/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://cmp.docs.sirdata.net/applications-mobiles-sdk-natif/mobile-sdk/react-native-setup.md).

# React Native — Installation

`@sirdata/react-native-cmp` est une fine couche JavaScript au-dessus des SDK natifs Sirdata CMP pour Android et iOS. L'interface de consentement, la décision d'affichage et les signaux IAB vivent tous dans les SDK natifs : le consentement est écrit dans le stockage natif, si bien que les SDK publicitaires et analytics de votre application le lisent exactement comme dans une application native. L'API JavaScript sert à votre propre logique : décider quand afficher l'interface, et lire le résultat.

Cette page décrit la version 2.0.2 du paquet. 2.0.1 a corrigé un plantage de 2.0.0 sur iOS (section 2), et 2.0.2 ajoute un mode de réouverture pour votre écran de réglages (section 6). Les trois versions utilisent les SDK natifs 2.0.0, et partagent les autres limites que décrit cette page. « La prochaine version » désigne la prochaine version des SDK natifs et de ce paquet, pas encore publiée.

## 1. Prérequis

|               | Minimum                                                                                          |
| ------------- | ------------------------------------------------------------------------------------------------ |
| React Native  | Aucun déclaré (`peerDependencies` vaut `*`) ; 2.0.2 a été vérifié avec 0.86.3                    |
| iOS           | 15.0, y compris le `platform :ios` de votre `Podfile`                                            |
| Android       | API 23 (le module hérite du `minSdkVersion` de votre application)                                |
| Build Android | JDK 17 et Android Gradle Plugin 8.2 ou plus                                                      |
| Expo          | Un development build ; 2.0.2 a été vérifié avec le SDK 57. Expo Go ne peut pas charger le module |

* **React Native.** Le paquet ne déclare aucune version minimale de React Native. 2.0.2 a été vérifié de bout en bout dans une application Expo SDK 57 (React Native 0.86.3, New Architecture), sur un émulateur Android 17 et sur un simulateur iOS 26.5. Avec React Native 0.87.1, seule l'installation de 2.0.0 a été vérifiée : le paquet s'installe, et ses dépendances natives se résolvent, sur iOS et sur Android. Les versions plus anciennes de React Native n'ont pas été testées.
* **New Architecture.** Le module est écrit avec l'API classique des modules natifs (`ReactContextBaseJavaModule` sur Android, `RCTEventEmitter` sur iOS). React Native charge ces modules sur la New Architecture par sa couche d'interopérabilité : il n'y a rien à activer ni à configurer.
* **iOS.** Les deux pods qu'apporte le paquet exigent iOS 15.0. Le `Podfile` d'un projet React Native 0.76 ou plus récent utilise `platform :ios, min_ios_version_supported`, qui vaut 15.1 : il convient déjà, comme celui d'un projet Expo SDK 57, qui cible iOS 16.4. Si votre `Podfile` indique une version plus basse, relevez-la :

  ```ruby
  platform :ios, '15.0'
  ```
* **Android.** Le cœur du SDK est en bytecode Java 21, construit et dexé avec l'Android Gradle Plugin 8.2.2 ; les plugins plus anciens ne sont pas testés. L'activité qui affiche votre interface React Native doit être une `ComponentActivity`, ce qu'est la `ReactActivity` de React Native.
* **Expo.** Le paquet contient du code natif : il lui faut un development build (`npx expo run:ios`, `npx expo run:android`, ou EAS Build). Il n'a besoin d'aucun plugin de configuration, car Expo le lie automatiquement (section 2). Dans Expo Go, chaque appel échoue avec une erreur de liaison (section 12).

Il vous faut aussi un **partner ID** et un **config ID**, disponibles dans la [Console Sirdata](https://cmp.sirdata.io). Ils désignent la configuration éditeur que le SDK télécharge au démarrage : textes, thème, finalités, partenaires et capping. Livrer votre application exige un abonnement valide et en cours à la Sirdata Consent Management Platform (section 10).

## 2. Installer

Avec npm (avec Yarn, lancez plutôt `yarn add @sirdata/react-native-cmp`) :

```bash
npm install @sirdata/react-native-cmp
```

Installez ensuite les pods iOS et reconstruisez l'application native — un rechargement Metro ne suffit pas après l'ajout de code natif. Depuis la racine du projet (`npx pod-install` fait la même chose) :

```bash
cd ios && pod install
```

Le module est lié automatiquement (autolinking) sur les deux plateformes : `pod install` installe les pods `sirdata-cmp-react-native` et `SirdataCMP`, et Gradle prend en compte le module Android.

**Avec Expo**, installez le paquet avec `npx expo install` :

```bash
npx expo install @sirdata/react-native-cmp
```

Reconstruisez ensuite l'application. Un projet Expo n'a en général pas de dossier `ios` où lancer `pod install` : `npx expo run:ios` génère les projets natifs (prebuild) et installe les pods, `npx expo run:android` fait de même pour Android, et EAS Build s'en charge sur ses serveurs. Le module ne demande aucun plugin de configuration, ni aucune entrée dans `app.json`.

Ce que le paquet apporte :

|         | Dépendance                                                                                                                                                                 | Provenance                          |
| ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------- |
| iOS     | `sirdata-cmp-react-native`, le pont                                                                                                                                        | Vos `node_modules`, par autolinking |
| iOS     | `SirdataCMP` `~> 2.0`, dont dépend le pont : le SDK natif et son interface de consentement SwiftUI                                                                         | Trunk CocoaPods                     |
| iOS     | `React-Core`, dont dépend aussi le pont                                                                                                                                    | Votre installation de React Native  |
| Android | `com.sirdata.cmp:android-sdk:2.0.0`, qui apporte `com.sirdata.cmp:shared` et `shared-android`                                                                              | Maven Central                       |
| Android | `kotlinx-coroutines-android` 1.8.0 et `androidx.activity` 1.8.2, déclarées par le pont. Gradle retient pour chacune la version la plus haute que demande votre application | Maven Central, Google               |

Il n'y a rien à ajouter à la main : pas de ligne `pod`, pas de dépendance Gradle, pas d'entrée de manifeste, pas de règle ProGuard. Le SDK Android déclare les permissions `INTERNET` et `ACCESS_NETWORK_STATE` et son activité de consentement dans son propre manifeste, que Gradle fusionne avec celui de votre application.

Les deux plateformes suivent les versions différemment. Sur iOS, le pont accepte n'importe quel `SirdataCMP` 2.x (`~> 2.0`) : votre `Podfile.lock` fige ce que `pod install` a résolu, et `pod update` peut apporter une 2.x ultérieure. Sur Android, le pont est figé sur `android-sdk` 2.0.0.

**Mise à jour depuis 2.0.0 ou 2.0.1.** Utilisez 2.0.2, qu'obtient toute nouvelle installation.

* Sur iOS, 2.0.0 fait planter l'application dès l'appel de `shouldCollectConsent()`, `acceptAll()` ou `rejectAll()`, même après la résolution d'`initialize()` : le `startConsent()` de la section 3 la fait donc planter au premier lancement. React Native appelle les méthodes de ce module hors du fil principal, et le SDK natif n'accepte ces trois appels que sur le fil principal. 2.0.1 les fait sur le fil principal.
* 2.0.2 permet de retirer un choix enregistré depuis une entrée de réglages : dès qu'un choix est enregistré, `showConsentUI()` ouvre le mode de réouverture, avec un bouton « Tout refuser » (section 6).

Les SDK natifs ne changent pas et l'API reste compatible : il n'y a rien à migrer, votre entrée de réglages comprise. Mettez à jour le paquet, puis installez les pods et reconstruisez l'application sur les deux plateformes, puisque le code natif du module change en 2.0.2.

```bash
npm install @sirdata/react-native-cmp@2.0.2
```

Avec Expo, lancez `npx expo install @sirdata/react-native-cmp@2.0.2`, puis `npx expo run:ios` et `npx expo run:android`, ou un nouveau build EAS.

## 3. Initialiser

Initialisez une fois, au démarrage, et **attendez la fin de l'initialisation avant tout autre appel** :

```ts
// consent.ts
import SirDataCMP from '@sirdata/react-native-cmp';

let started: Promise<void> | null = null;

// Sans risque depuis plusieurs endroits : le travail ne s'exécute qu'une fois par session JavaScript.
export function startConsent(): Promise<void> {
  if (started === null) {
    started = (async () => {
      await SirDataCMP.initialize({
        partnerId: 1020, // ID d'exemple : utilisez votre propre partner ID
        configId: 'hmDnl', // ID d'exemple : utilisez votre propre config ID
      });
      if (await SirDataCMP.shouldCollectConsent()) {
        await SirDataCMP.showConsentUI();
      }
    })();
  }
  return started;
}
```

Appelez `startConsent()` depuis le premier effet (`useEffect`) de votre composant racine, une fois votre premier écran monté : `showConsentUI()` a besoin d'un écran depuis lequel présenter. `1020` et `'hmDnl'` sont les valeurs d'exemple utilisées dans ces pages : remplacez-les par les identifiants de votre application, disponibles dans la Console Sirdata.

La promesse unique partagée compte : le Strict Mode de React exécute les effets deux fois en développement, et deux appels simultanés à `showConsentUI()` présenteraient l'interface de consentement deux fois.

**Attendez d'abord `initialize()`.** Avant qu'elle soit résolue, `showConsentUI()` fait planter l'application sur les deux plateformes, et `acceptAll()` et `rejectAll()` la font planter sur iOS (le SDK natif n'est pas encore là, et sur iOS une erreur levée dans son cœur Kotlin termine le processus). Les getters, eux, sont sans risque à tout moment. Dans la prochaine version (non publiée), sur iOS, `showConsentUI()` affiche à la place un message avec un bouton Fermer, et `acceptAll()` / `rejectAll()` sont rejetées ; sur Android, `showConsentUI()` plante toujours.

Ce que fait `initialize()` :

* elle écrit `IABTCF_CmpSdkID` (92) dans le stockage natif avant d'être résolue, puis charge la configuration éditeur et les listes de partenaires en arrière-plan ;
* une fois la configuration chargée, avant tout choix, le SDK écrit aussi `IABTCF_gdprApplies`, `IABTCF_PolicyVersion`, `IABTCF_PublisherCC`, `IABTCF_PurposeOneTreatment`, `IABTCF_UseNonStandardTexts` et les chaînes de bits éditeur, et, pour un utilisateur sous le régime US, les clés GPP avec la section US. La chaîne TC et les consentements par finalité et par partenaire n'apparaissent qu'une fois un choix enregistré. D'ici là, les chaînes de bits éditeur portent les valeurs par défaut du SDK ; à partir de la prochaine version, elles aussi attendent un choix ;
* elle est **idempotente au sein d'un processus**. Un rechargement JavaScript (Fast Refresh, rechargement depuis Metro) relance votre code de démarrage : le second appel est résolu sans réinitialiser, et ignore ses options. Changer de `partnerId` ou de `configId` exige donc un redémarrage de l'application.

Démarrez les SDK publicitaires et analytics que vous pilotez depuis JavaScript après sa résolution : au premier lancement, les clés IAB n'existent pas avant son exécution.

### Options

| Option                                      | Type                         | En 2.0.0 à 2.0.2                                                                                                                                                                                                            |
| ------------------------------------------- | ---------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `partnerId`                                 | `number`, obligatoire        | Votre partner ID. Sans lui, la promesse est rejetée avec `E_INIT`                                                                                                                                                           |
| `configId`                                  | `string`, obligatoire        | Votre config ID. Sans lui, la promesse est rejetée avec `E_INIT`                                                                                                                                                            |
| `gdprDefaultApplies`                        | `boolean`, par défaut `true` | Ce que répond `isGdprApplies()` avant le chargement de la configuration, quand le pays de l'appareil ne peut pas être déterminé. Une fois la configuration là, c'est le serveur qui décide                                  |
| `apiRoot`, `cacheApiRoot`, `consentApiRoot` | `string`                     | Remplacent les trois hôtes. Laissez-les vides pour utiliser `https://api.consentframework.com/api/v1/public`, `https://choices.consentframework.com/api/v1/public` et `https://mychoice.consentframework.com/api/v1/public` |
| `language`                                  | `string`                     | Acceptée, mais **sans effet**                                                                                                                                                                                               |
| `debugMode`                                 | `boolean`                    | **Ne la renseignez pas sur Android** — voir ci-dessous                                                                                                                                                                      |

**La langue et l'apparence de l'interface ne sont pas des options.** L'interface de consentement utilise la langue que fixe votre configuration Sirdata, si elle en fixe une, sinon la langue de l'appareil, sinon la langue par défaut de la configuration, sinon l'anglais. Son thème (couleurs, position, boutons) vient lui aussi de la configuration, et le mode sombre retient les couleurs sombres de la configuration quand elle en a.

**`debugMode` : ne la renseignez pas.** En 2.0.0 à 2.0.2, le pont Android appelle le `initialize` natif hors du fil principal. Avec `debugMode: true`, le SDK natif en fait une erreur : `initialize()` est rejetée avec `E_INIT` et le SDK n'est pas initialisé. Sans elle, Logcat affiche un avertissement par lancement sous le tag `SirDataCMP`, qui commence par `[CMP] SirDataCMP.initialize() was called off the main thread`. C'est un problème connu du pont Android en 2.0.0 à 2.0.2, et il n'y a rien à changer dans votre application. Sur iOS, le pont appelle déjà `initialize` sur le fil principal : l'option n'y a rien à attraper non plus.

## 4. Afficher l'interface de consentement

Laissez le SDK décider s'il faut l'afficher, comme le fait `startConsent()` ci-dessus (*fragment*, à l'intérieur d'une fonction `async`) :

```ts
if (await SirDataCMP.shouldCollectConsent()) {
  await SirDataCMP.showConsentUI();
}
```

Ne testez pas la chaîne TC vous-même : un consentement partiel doit rouvrir la bannière, une fenêtre de capping active doit la garder fermée, et ni l'un ni l'autre ne se lit dans la chaîne.

**`shouldCollectConsent()`** applique la même cascade que la CMP web : applicabilité du RGPD, consentement stocké, cookie wall, fenêtres de capping, et si le choix stocké couvre encore chaque finalité et chaque partenaire actifs. Elle **attend d'abord la configuration éditeur** : vous pouvez donc l'appeler juste après `initialize()`. Sur un réseau qui ne répond pas, cette attente dure jusqu'à l'expiration des timeouts HTTP (plusieurs dizaines de secondes), et la réponse est alors provisoire : `true` quand rien n'est stocké et que le RGPD semble s'appliquer d'après l'appareil. Ne bloquez pas un écran de démarrage dessus.

Ce qu'elle répond dans les cas courants :

* **premier lancement** dans un pays RGPD : `true` ;
* **choix stocké et toujours complet** : `false`. Selon le réglage de capping de votre configuration, la bannière peut revenir une fois sa fenêtre de capping écoulée ;
* **cookie wall** configuré : `true` à chaque lancement tant que la finalité 1 n'est pas accordée ;
* **« Me le redemander plus tard »** choisi dans la bannière, sans rien de stocké : `false` pendant une heure ;
* **le RGPD ne s'applique pas**, utilisateurs américains compris : `false` (section 7).

**`showConsentUI()`** présente l'interface de consentement native (bannière, finalités, partenaires) dans le workflow que choisit la cascade — un choix qui ne manque qu'au niveau des partenaires l'ouvre en mode « appliquer les choix », qui ne demande que ce qui reste. Sur Android, elle ouvre l'activité de consentement du SDK par-dessus la vôtre ; sur iOS, elle présente la vue de consentement en plein écran par-dessus le contrôleur de vue le plus haut de React Native, une présentation que l'utilisateur ne peut pas faire glisser vers le bas.

La promesse **est résolue à la fermeture de l'interface**, quelle qu'en soit la cause : un choix, la croix de fermeture, ou le bouton retour d'Android. Le bouton retour la ferme sans rien enregistrer : la bannière revient donc à la décision suivante. Relisez ce dont vous avez besoin après la résolution de la promesse.

Elle est rejetée avec :

| Code                  | Plateforme | Cause                                                              |
| --------------------- | ---------- | ------------------------------------------------------------------ |
| `E_NO_ACTIVITY`       | Android    | React Native n'a pas d'activité courante depuis laquelle présenter |
| `E_ACTIVITY_TYPE`     | Android    | L'activité courante n'est pas une `ComponentActivity`              |
| `E_SHOW`              | Android    | Le lancement de l'activité de consentement a échoué                |
| `E_NO_VIEWCONTROLLER` | iOS        | Aucun contrôleur de vue depuis lequel présenter                    |

`shouldCollectConsent()` est rejetée avec `E_SHOULD_COLLECT` si la décision native échoue.

**Problème connu de 2.0.0 à 2.0.2, iOS.** Si la configuration n'a pas pu être chargée à ce lancement (pas de réseau, par exemple), l'interface de consentement n'affiche qu'un indicateur de chargement, sans aucun moyen de la fermer. `showConsentUI()` la présente en plein écran, où elle ne peut pas non plus être glissée vers le bas : elle reste donc à l'écran et sa promesse n'est pas résolue tant que l'application n'est pas redémarrée, car le SDK ne retente pas le chargement pendant le lancement. `startConsent()` y tombe lors d'un premier lancement hors ligne dans un pays RGPD, où `shouldCollectConsent()` répond `true`. Sur Android, le bouton retour ferme l'interface de consentement. Ces versions ne donnent à JavaScript aucun signal d'échec du chargement : sur iOS, n'appelez pas `showConsentUI()` quand vous savez l'appareil hors ligne. Corrigé dans la prochaine version (non publiée) : l'interface de consentement affiche un message et un bouton Fermer, qui résout la promesse.

## 5. Lire le consentement

Chaque getter renvoie une promesse, lit le même stockage natif que les SDK partenaires, et ne lève jamais d'erreur faute de choix : avant le premier choix, la chaîne TC, les champs de bits de consentement et la chaîne US Privacy sont vides. Sous le régime US, la chaîne GPP porte déjà la section US une fois la configuration chargée (section 3).

```ts
import SirDataCMP from '@sirdata/react-native-cmp';

export async function readConsent(): Promise<{ device: boolean; google: boolean }> {
  const device = await SirDataCMP.hasPurposeConsent(1); // finalité 1 : stocker ou accéder à des informations sur un appareil
  const google = await SirDataCMP.hasVendorConsent(755); // 755 = Google dans la Global Vendor List
  return { device, google };
}
```

| Getter                                           | Renvoie                                                                                                                                   |
| ------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------- |
| `getTcString()`                                  | `IABTCF_TCString`                                                                                                                         |
| `getPurposeConsents()` / `getVendorConsents()`   | `IABTCF_PurposeConsents` / `IABTCF_VendorConsents`, des chaînes de bits où le caractère *n* correspond à la finalité ou au partenaire *n* |
| `hasPurposeConsent(id)` / `hasVendorConsent(id)` | Si le bit `id` (à partir de 1) est positionné dans ces chaînes                                                                            |
| `getGppString()`                                 | `IABGPP_HDR_GppString`                                                                                                                    |
| `getUspString()`                                 | `IABUSPrivacy_String` : vide tant qu'un utilisateur américain n'a pas enregistré l'écran US                                               |
| `getAddtlConsent()`                              | `IABTCF_AddtlConsent`, la chaîne Additional Consent de Google                                                                             |
| `isGdprApplies()`                                | La réponse du serveur une fois la configuration chargée ; avant, une estimation d'après le pays de l'appareil                             |
| `isCcpaApplies()`                                | La même chose, pour le régime US                                                                                                          |

### Réagir aux changements

```ts
import SirDataCMP from '@sirdata/react-native-cmp';
import type { ConsentSnapshot, Subscription } from '@sirdata/react-native-cmp';

export function watchConsent(onChange: (s: ConsentSnapshot) => void): Subscription {
  let lastSeen: string | null = null; // un par abonnement, jamais partagé
  Promise.all([SirDataCMP.getTcString(), SirDataCMP.getGppString(), SirDataCMP.getUspString()])
    .then((v) => {
      if (lastSeen === null) lastSeen = v.join('|'); // partir des valeurs stockées
    })
    .catch(() => {}); // sans elles, le premier événement passe : sans conséquence
  return SirDataCMP.addConsentChangeListener((s) => {
    // Comparez les valeurs : sur Android, l'événement part aussi quand rien de stocké n'a changé.
    const key = [s.tcString, s.gppString, s.uspString].join('|');
    if (key === lastSeen) return;
    lastSeen = key;
    onChange(s);
  });
}

// Quand vous n'en avez plus besoin :
// const sub = watchConsent(applyGating);
// sub.remove();
```

L'événement porte un instantané des valeurs stockées (`tcString`, `purposeConsents`, `vendorConsents`, `gppString`, `uspString`, `addtlConsent`, `gdprApplies`), mais les deux plateformes ne l'émettent pas aux mêmes moments. **Comparez les valeurs plutôt que de compter les événements** :

|                     | Android                                                                                                                                                                                                             | iOS                                                                                                                                                                                                                           |
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Émis                | À chaque mise à jour de l'état de consentement du SDK : pendant le chargement de la configuration, à chaque bascule dans l'interface de consentement avant que l'utilisateur enregistre, et à chaque enregistrement | Seulement quand `IABTCF_TCString`, `IABUSPrivacy_String` ou `IABGPP_HDR_GppString` change réellement dans `UserDefaults`, ce qui, pour un utilisateur sous le régime US, inclut le chargement de la configuration (section 3) |
| Écran US enregistré | Pas émis en 2.0.0 à 2.0.2 : un choix US ne fait pas avancer le compteur de mises à jour qu'observe le pont. Émis à partir de la prochaine version                                                                   | Émis                                                                                                                                                                                                                          |

À cause de la dernière ligne, relisez les valeurs dont vous dépendez à la résolution de `showConsentUI()`, plutôt que de vous fier au seul écouteur. Les deux plateformes commencent à émettre une fois `initialize()` résolue.

**Problème connu de 2.0.0 à 2.0.2, Android.** Les événements s'arrêtent quand l'activité qui héberge React Native est détruite alors que le côté JavaScript continue de tourner : retour sur l'écran racine sous Android 11 et antérieur, ou changement de langue ou de taille de police du système. Ils ne reprennent qu'au prochain appel à `initialize()`, ce qui avec `startConsent()` signifie un nouveau processus ou un rechargement JavaScript. Relisez les valeurs dont vous dépendez quand l'application redevient active (`AppState` `'active'`), ainsi qu'à la résolution de `showConsentUI()`.

`addConsentUIClosedListener(() => …)` est émis à la fermeture d'une interface de consentement ouverte par `showConsentUI()`, au moment où sa promesse est résolue. Les deux écouteurs renvoient un abonnement : appelez `remove()` dessus quand vous avez terminé.

## 6. Rouvrir depuis un écran de réglages

Le RGPD exige que les choix restent modifiables à tout moment. Donnez à l'utilisateur un point d'entrée qui appelle de nouveau `showConsentUI()` :

```ts
import SirDataCMP from '@sirdata/react-native-cmp';

// par exemple, le onPress d'un bouton « Gérer les cookies » dans votre écran de réglages
export async function onManageConsentPress(): Promise<void> {
  await SirDataCMP.showConsentUI();
  // relisez et réappliquez ici ce que vous conditionnez au consentement
}
```

À partir de 2.0.2, `showConsentUI()` décide comment s'ouvrir comme le fait la CMP web. Quand l'interface de consentement est due, c'est-à-dire quand `shouldCollectConsent()` répondrait `true`, elle s'ouvre dans le workflow que choisit la décision d'affichage : c'est ce dont `startConsent()` a besoin. Sinon (un choix complet est enregistré, une fenêtre de capping est active, ou le RGPD ne s'applique pas), l'ouverture vient de votre application : elle s'ouvre alors dans le mode de réouverture des SDK natifs (`MANUAL_DISPLAY`), comme `displayUI()` sur le web, avec une croix de fermeture en haut et un bouton « Tout refuser » quelle que soit l'option de refus que fixe votre configuration, pour que l'utilisateur puisse retirer son consentement d'un seul geste. La réouverture relance la fenêtre de capping et compte comme une réouverture dans les statistiques Sirdata. Passez `{ reopen: true }` pour ouvrir le mode de réouverture même quand l'interface est due, par exemple quand un choix n'est que partiel.

La croix de fermeture du mode de réouverture ne change aucun choix. Là où le serveur applique les règles de la CNIL, en France notamment, elle enregistre les choix affichés en se fermant, comme sur le web : la TC string est alors réécrite et l'écouteur de changements peut se déclencher (section 5).

**Avant 2.0.2**, `showConsentUI()` s'ouvre toujours dans le workflow que choisit la décision d'affichage : une entrée de réglages rouvre donc la bannière comme lors d'une première visite, bouton de refus compris, et ce bouton ne retire pas toujours un choix enregistré. Le bouton affiché dépend de l'option de refus que votre configuration fixe dans la Console Sirdata :

| Option de refus         | Le bouton de refus de la bannière rouverte, quand un choix est enregistré                                                                           |
| ----------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| Tout refuser et fermer  | « Tout refuser » refuse toutes les finalités et tous les partenaires, et l'enregistre : le consentement est retiré                                  |
| Continuer sans accepter | « Continuer sans accepter » enregistre les choix affichés, c'est-à-dire ceux qui sont enregistrés : un « Tout accepter » antérieur reste enregistré |
| Me demander plus tard   | « Me demander plus tard » ferme la bannière et n'enregistre rien                                                                                    |
| Bouton de fermeture     | Il n'y a pas de bouton de refus. La croix de fermeture, si votre configuration en affiche une, laisse le choix enregistré tel quel                  |

L'option qui s'applique est celle que le serveur sert pour le pays de l'utilisateur, qui peut différer du réglage de la Console : en France, par exemple, « Me demander plus tard » est servi comme « Continuer sans accepter ». Avec 2.0.0 ou 2.0.1, l'utilisateur peut retirer son consentement par **Paramétrer vos choix**, puis **Tout refuser**, qui enregistre le refus et ferme l'interface, ou par une entrée de votre application qui appelle `rejectAll()`, qui l'enregistre sans afficher d'interface (section 11).

Sur iOS, si la configuration n'a pas pu être chargée à ce lancement, l'interface rouverte ne peut pas être fermée (problème connu, section 4).

## 7. Utilisateurs américains

Le RGPD ne s'applique pas aux utilisateurs américains : `shouldCollectConsent()` répond donc `false` et aucune bannière n'apparaît d'elle-même. Quand le régime US s'applique, `showConsentUI()` présente l'**écran US** à la place de la bannière TCF : l'utilisateur peut s'y opposer, et l'enregistrer écrit `IABUSPrivacy_String` et les sections US de la chaîne GPP.

```ts
import SirDataCMP from '@sirdata/react-native-cmp';

// Une fois startConsent() résolue : la réponse du serveur si la configuration est chargée,
// sinon une estimation d'après le pays de l'appareil.
export async function showsUsPrivacyEntry(): Promise<boolean> {
  return SirDataCMP.isCcpaApplies();
}
```

Proposez aux utilisateurs américains un point d'entrée dans vos réglages, par exemple intitulé « Your Privacy Choices », qui appelle `showConsentUI()`. Le serveur décide du régime d'après le pays et l'État américain où il situe la connexion, une fois la configuration chargée ; avant, `isCcpaApplies()` est une estimation d'après le pays de l'appareil. Il n'y a pas de `setCcpaOptOut` en JavaScript : l'opposition passe par l'écran US. En 2.0.0 à 2.0.2, l'enregistrer n'émet pas `addConsentChangeListener` sur Android (section 5) : relisez `getUspString()` et `getGppString()` à la résolution de `showConsentUI()`. À partir de la prochaine version, l'événement est émis sur les deux plateformes, et son instantané porte `uspString` et `gppString`.

## 8. SDK partenaires

La plupart des SDK partenaires d'une application React Native sont des SDK natifs enveloppés par un plugin, et ils lisent le consentement dans le stockage natif comme dans une application native. Il n'y a rien à passer depuis JavaScript, et les règles de [Transmission du consentement aux SDK partenaires](/applications-mobiles-sdk-natif/mobile-sdk/sharing-consent.md) s'appliquent telles quelles :

* les SDK conformes IAB (Google Mobile Ads et d'autres) n'ont besoin de rien ;
* les adaptateurs de consentement (Firebase Analytics, AppsFlyer, Adjust, Branch) cherchent les classes natives du partenaire à l'exécution, comme dans une application native : ils s'appliquent donc à un SDK partenaire qu'un plugin React Native lie dans votre application ;
* il faut encore dire à AppsFlyer de lire les clés IAB : utilisez l'option que son plugin React Native expose pour cela (voir la documentation du plugin) ;
* les SDK qui ne lisent pas les clés IAB, comme celui de Meta, sont à conditionner par vous : démarrez-les depuis JavaScript selon `hasPurposeConsent(...)` / `hasVendorConsent(...)`, et réévaluez à chaque changement (section 5).

Collectez le consentement avant de charger la première publicité.

## 9. Tester et vérifier

Utilisez votre propre configuration pour tester. Si vous commencez avec les identifiants d'exemple de ces pages, passez aux vôtres avant la release, et effacez alors les données de l'application (voir le dernier point ci-dessous).

Pour rejouer un premier lancement, désinstallez l'application, ou sur Android effacez ses données (remplacez `com.example.myapp` par votre `applicationId`) :

```bash
adb shell pm clear com.example.myapp
```

Vérifiez, sur chaque plateforme :

1. **Les dépendances natives.** iOS : `pod install` installe `sirdata-cmp-react-native (2.0.2)` et `SirdataCMP` (2.0.0, ou une 2.x ultérieure). Android :

   ```bash
   cd android && ./gradlew :app:dependencies --configuration releaseRuntimeClasspath | grep com.sirdata.cmp
   ```

   liste `android-sdk`, `shared` et `shared-android` en 2.0.0.
2. **Premier lancement** (depuis un pays RGPD) : `shouldCollectConsent()` est résolue à `true` et la bannière apparaît.
3. **Après « Tout accepter »** : `getTcString()` n'est pas vide et `hasPurposeConsent(1)` vaut `true`. Pour un utilisateur hors des États-Unis, `getUspString()` reste vide.
4. **Relance** : pas de bannière.
5. **Entrée de réglages** : dès qu'un choix est enregistré, `showConsentUI()` ouvre l'interface avec une croix de fermeture en haut et un bouton « Tout refuser », et est résolue à sa fermeture. Après « Tout accepter », « Tout refuser » y laisse `hasPurposeConsent(1)` à `false`.
6. **Écran US** : depuis une connexion que le serveur situe dans un État américain couvert (la Californie, par exemple), `isCcpaApplies()` vaut `true`, `showConsentUI()` affiche l'écran US, et après l'avoir enregistré, `getUspString()` n'est plus vide.
7. **Build de release** : la bannière apparaît toujours dans un build de release Android minifié et dans un build Release iOS.

Un utilitaire réservé au développement :

```ts
import SirDataCMP from '@sirdata/react-native-cmp';

export async function logConsentState(): Promise<void> {
  if (!__DEV__) return; // le consentement décrit les choix d'un utilisateur : gardez-le hors des logs de production
  const [initialized, gdpr, us, tc, gpp, usp] = await Promise.all([
    SirDataCMP.isInitialized(),
    SirDataCMP.isGdprApplies(),
    SirDataCMP.isCcpaApplies(),
    SirDataCMP.getTcString(),
    SirDataCMP.getGppString(),
    SirDataCMP.getUspString(),
  ]);
  console.log({ initialized, gdpr, us, tc, gpp, usp });
}
```

Pour lire les clés brutes sur Android, dans un build débogable :

```bash
adb shell run-as com.example.myapp cat shared_prefs/com.example.myapp_preferences.xml
```

`IABTCF_CmpSdkID` vaut `92` dès qu'`initialize()` est résolue.

Sur Android, Logcat affiche les lignes du SDK sous les tags `SirDataCMP` et `SirDataCMPManager`, dont `Config load failed: …` quand la configuration ne peut pas être chargée. Sur iOS, la console Xcode affiche des lignes commençant par `[CMP]`. Voir [Logs](/applications-mobiles-sdk-natif/mobile-sdk/logging.md).

**Changer de partner ID ou de config ID** exige un redémarrage de l'application (section 3), et le consentement stocké appartient à la configuration qui l'a collecté : effacez les données de l'application ou réinstallez-la quand vous changez. Il n'y a pas de `clearConsent()` en JavaScript.

## 10. Builds de release

* **Minification Android.** Rien à ajouter : les règles R8 du SDK sont livrées avec lui (consumer rules) et s'appliquent à votre build de release minifié, adaptateurs de consentement compris. Les règles `-keep class com.sirdata.cmp.**` copiées d'anciennes instructions ne sont pas nécessaires.
* **`debugMode`.** Ne la renseignez pas (section 3).
* **Manifeste de confidentialité Apple.** Ni le pod `SirdataCMP` 2.0.0 ni ce paquet (2.0.0 à 2.0.2) ne livrent de manifeste de confidentialité (`PrivacyInfo.xcprivacy`). Le SDK stocke le consentement dans `UserDefaults`, qu'Apple range parmi les required reason APIs (catégorie `NSPrivacyAccessedAPICategoryUserDefaults`, vérifié sur developer.apple.com le 2026-10-05). Dans une application Expo SDK 57, le manifeste que génère le prebuild déclare déjà cette catégorie, avec la raison `CA92.1`. Apple explique qui déclare quoi dans [Describing use of required reason API](https://developer.apple.com/documentation/bundleresources/describing-use-of-required-reason-api) : lisez-la pour votre application avant de soumettre.
* **Mentions d'attribution.** Le paquet contient `LICENSE`, `NOTICE-android`, `NOTICE-ios` et `THIRD-PARTY-LICENSES/` (dans `node_modules/@sirdata/react-native-cmp/`). Les builds Android et iOS embarquent des composants tiers différents, d'où deux fichiers de mentions : les deux utilisent des composants sous Apache License 2.0, le build Android utilise aussi slf4j sous licence MIT, et le build iOS un composant sous Boost Software License 1.0. Si vous distribuez votre application, mettez à la disposition de vos utilisateurs, par exemple dans l'écran des licences open source, le fichier de mentions de chaque plateforme que vous livrez (`NOTICE-android`, `NOTICE-ios`) et les textes de licence de `THIRD-PARTY-LICENSES/` : c'est exigé par la section 26.1(b) du `LICENSE`, et par l'Apache License 2.0 (section 4) pour les composants qu'elle couvre.
* **Licence.** Livrer votre application exige un abonnement valide et en cours à la Sirdata Consent Management Platform ; un abonnement pris par la Console Sirdata suffit, et aucun accord signé n'est requis (section 25.1 du `LICENSE`). Sans abonnement, la licence est une licence d'évaluation de 90 jours : évaluation interne, développement, tests et intégration seulement, sans distribution à des tiers ni sur un store d'applications (section 1.4). Abonnements : [sirdata.com](https://sirdata.com) ; questions sur la licence : <legal@sirdata.com>.

## 11. Référence de l'API

Importez l'export par défaut. Le paquet exporte aussi les types `SirDataCMPInitOptions`, `ShowConsentUIOptions` (à partir de 2.0.2), `ConsentSnapshot` et `Subscription`.

```ts
import SirDataCMP from '@sirdata/react-native-cmp';
```

Chaque méthode, sauf les deux écouteurs, renvoie une promesse. Une promesse rejetée porte l'un des codes ci-dessous dans sa propriété `code`.

### Cycle de vie

```ts
initialize(options: SirDataCMPInitOptions): Promise<void>;
```

Initialise le SDK natif (section 3). Rejetée avec `E_INIT` quand `partnerId` ou `configId` manque, et sur Android quand le `initialize` natif lève une erreur, ce qui inclut `debugMode: true` en 2.0.0 à 2.0.2. Sur iOS, le pont évite les deux cas où l'appel natif lève une erreur (déjà initialisé, hors du fil principal). Quand le SDK est déjà initialisé, elle est résolue sans réinitialiser.

```ts
interface SirDataCMPInitOptions {
  partnerId: number;
  configId: string;
  language?: string; // sans effet en 2.0.0 à 2.0.2
  apiRoot?: string;
  cacheApiRoot?: string;
  consentApiRoot?: string;
  debugMode?: boolean; // à ne pas renseigner sur Android en 2.0.0 à 2.0.2
  gdprDefaultApplies?: boolean;
}
```

```ts
isInitialized(): Promise<boolean>;
```

`true` dès que le `initialize` natif s'est exécuté. Cela ne signifie pas que la configuration est chargée : `shouldCollectConsent()` l'attend.

### Affichage

```ts
shouldCollectConsent(): Promise<boolean>;
```

Attend la configuration éditeur, puis répond s'il faut afficher l'interface de consentement maintenant (section 4). Rejetée avec `E_SHOULD_COLLECT`.

```ts
showConsentUI(options?: ShowConsentUIOptions): Promise<void>;

interface ShowConsentUIOptions {
  reopen?: boolean; // toujours le mode de réouverture (section 6). false par défaut
}
```

Présente l'interface de consentement et est résolue à sa fermeture : quand l'interface est due, dans le workflow que choisit la cascade (section 4) ; sinon, et toujours avec `{ reopen: true }`, dans le mode de réouverture pour un écran de réglages (section 6). Les deux à partir de 2.0.2 : avant, toujours dans le workflow que choisit la cascade. Rejetée avec `E_NO_ACTIVITY`, `E_ACTIVITY_TYPE`, `E_SHOW` (Android) ou `E_NO_VIEWCONTROLLER` (iOS). Attendez d'abord `initialize()`.

### Choix programmatiques

```ts
acceptAll(): Promise<void>;
rejectAll(): Promise<void>;
```

Acceptent ou refusent chaque finalité, partenaire et fonctionnalité, et enregistrent le choix — pour un écran de consentement à vous. Un choix se fait sur les listes de partenaires qu'apporte la configuration : en 2.0.0 à 2.0.2, appelez-les donc après la résolution de `shouldCollectConsent()`. Appelées pendant que la configuration se charge encore, ou après l'échec de son chargement, elles enregistrent une chaîne TC valide mais vide, sans finalité ni partenaire, et sont résolues : un « Tout accepter » est alors stocké comme un refus. Elles sont rejetées avec `E_ACCEPT_ALL` / `E_REJECT_ALL` seulement quand l'appel natif lève une erreur (sur Android, par exemple, avant `initialize()` ; sur iOS, ce cas fait planter l'application, et est rejeté dans la prochaine version). Une soumission que le SDK natif signale comme échouée est quand même résolue. Pour être sûr qu'un choix a été enregistré, relisez-le : `getTcString()` n'est pas vide, et après `acceptAll()`, `getPurposeConsents()` contient un `1`.

À partir de la prochaine version, elles attendent la configuration pendant son chargement, puis enregistrent le choix sur les vraies listes. Elles sont rejetées, sans rien enregistrer, quand elle n'a pas pu être chargée, et chaque fois que le SDK natif signale la soumission comme échouée.

### Getters

```ts
getTcString(): Promise<string>;
getPurposeConsents(): Promise<string>;
getVendorConsents(): Promise<string>;
getGppString(): Promise<string>;
getUspString(): Promise<string>;
getAddtlConsent(): Promise<string>;
hasPurposeConsent(purposeId: number): Promise<boolean>;
hasVendorConsent(vendorId: number): Promise<boolean>;
isGdprApplies(): Promise<boolean>;
isCcpaApplies(): Promise<boolean>;
```

Voir le tableau de la section 5. Sur Android, ils sont rejetés avec `E_CMP` si l'appel natif lève une erreur ; sur iOS, ils ne sont jamais rejetés.

### Événements

```ts
addConsentChangeListener(listener: (snapshot: ConsentSnapshot) => void): Subscription;
addConsentUIClosedListener(listener: () => void): Subscription;

interface ConsentSnapshot {
  tcString: string;
  purposeConsents: string;
  vendorConsents: string;
  gppString: string;
  uspString: string;
  addtlConsent: string;
  gdprApplies: boolean;
}

interface Subscription {
  remove(): void;
}
```

Voir la section 5 pour savoir quand chaque événement est émis sur chaque plateforme.

### Non disponible depuis JavaScript en 2.0.0 à 2.0.2

| Fonctionnalité native                                                                                                                                  | À la place                                                                                                                |
| ------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------- |
| Le workflow et la raison de la décision d'affichage (`awaitConsentDisplayDecision`)                                                                    | `shouldCollectConsent()` donne le oui ou le non ; `showConsentUI()` choisit lui-même le workflow                          |
| `saveConsent()`, `submitConsent()`, `recordAskLater()`                                                                                                 | Les boutons de l'interface de consentement elle-même, ou `acceptAll()` / `rejectAll()`                                    |
| `setCcpaOptOut()`, `isCcpaOptedOut()`                                                                                                                  | L'écran US via `showConsentUI()`, puis `getUspString()` (section 7)                                                       |
| `clearConsent()`, `shutdown()`                                                                                                                         | Effacez les données de l'application ou réinstallez-la ; redémarrez l'application pour changer d'identifiants (section 9) |
| Les API de commandes TCF, GPP et USP (`tcfApi()`, `gppApi()`, `uspApi()`)                                                                              | Les SDK partenaires lisent le stockage natif ; utilisez les getters pour votre propre logique                             |
| L'état Google Consent Mode et les adaptateurs de consentement (`getGoogleConsentState()`, `getLastForwardedConsentState()`, `getRegisteredAdapters()`) | Les adaptateurs tournent en natif sans aucun appel (section 8)                                                            |
| L'état et les erreurs d'initialisation (`getConsentState()`, `getInitError()`, `getLastTcStringError()`)                                               | Android : Logcat, tag `SirDataCMPManager`. iOS : non observable depuis JavaScript                                         |
| `certificatePins` sur Android                                                                                                                          | Non configurable depuis JavaScript                                                                                        |

## 12. Dépannage

| Symptôme                                                                                                                                                                                                                                                                                   | Cause et correction                                                                                                                                                                                                                                                                                                                                                                            |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `The package '@sirdata/react-native-cmp' doesn't seem to be linked` à chaque appel. Sur iOS, aussi une `Invariant Violation` (`` `new NativeEventEmitter()` requires a non-null argument ``) quand vous vous abonnez à un événement ; sur Android, l'abonnement réussit mais n'émet jamais | Le module natif n'est pas dans l'application qui tourne : c'est Expo Go, ou l'application n'a pas été reconstruite après l'installation du paquet. Utilisez un development build, reconstruit après l'installation du paquet : avec Expo, `npx expo run:ios` ou `npx expo run:android` (section 2) ; sinon, lancez `pod install` sur iOS, puis reconstruisez l'application                     |
| `pod install` : « required a higher minimum deployment target »                                                                                                                                                                                                                            | Le `platform :ios` de votre `Podfile` est inférieur à 15.0. Relevez-le à `'15.0'` au moins                                                                                                                                                                                                                                                                                                     |
| `pod install` : « Unable to find a specification » ou « could not find compatible versions » pour `SirdataCMP`                                                                                                                                                                             | Vos specs CocoaPods locales sont périmées : lancez `pod install --repo-update`. Si cela persiste, supprimez `ios/Pods` et `ios/Podfile.lock`, puis lancez `npx pod-install`                                                                                                                                                                                                                    |
| Metro : `Unable to resolve "react-native"` depuis `…/react-native-cmp/src/index.js`                                                                                                                                                                                                        | Le paquet a été installé depuis un chemin local (`file:` ou `npm link`), que npm lie par un lien symbolique que Metro résout hors de votre projet. Installez-le depuis npm, ou faites pointer les `watchFolders` et `extraNodeModules` de Metro vers les `react` et `react-native` de votre projet et le dossier du paquet                                                                     |
| `initialize()` est rejetée avec `E_INIT` et un message « called off the main thread »                                                                                                                                                                                                      | `debugMode: true` sur Android en 2.0.0 à 2.0.2. Retirez l'option (section 3)                                                                                                                                                                                                                                                                                                                   |
| Logcat avertit `SirDataCMP.initialize() was called off the main thread`                                                                                                                                                                                                                    | Attendu avec le pont Android de 2.0.0 à 2.0.2 (section 3)                                                                                                                                                                                                                                                                                                                                      |
| iOS : l'application plante sur `shouldCollectConsent()`, `acceptAll()` ou `rejectAll()`, même après la résolution d'`initialize()` ; le rapport de plantage montre `SirDataCmp.shouldCollectConsent` (ou `acceptAll`, `rejectAll`) appelant `Kotlin_ObjCExport_createContinuationArgument` | Version 2.0.0 du paquet. Passez à 2.0.2 (section 2)                                                                                                                                                                                                                                                                                                                                            |
| L'application plante à l'ouverture de l'interface de consentement, ou sur `acceptAll()` / `rejectAll()` sur iOS                                                                                                                                                                            | Appelé avant la résolution d'`initialize()`. Attendez-la d'abord (section 3). Corrigé sur iOS dans la prochaine version                                                                                                                                                                                                                                                                        |
| Après `acceptAll()`, `getPurposeConsents()` ne contient aucun `1`                                                                                                                                                                                                                          | En 2.0.0 à 2.0.2, `acceptAll()` appelée avant le chargement de la configuration enregistre un choix vide : appelez-la après la résolution de `shouldCollectConsent()` (section 11). À partir de la prochaine version, elle attend la configuration, et est rejetée avec « Configuration not loaded: the choice was not recorded » quand la configuration n'a pas pu être chargée               |
| L'interface de consentement apparaît deux fois                                                                                                                                                                                                                                             | Deux appels simultanés à `showConsentUI()`, souvent le Strict Mode de React qui exécute deux fois votre effet de démarrage. Partagez une seule promesse (section 3)                                                                                                                                                                                                                            |
| Pas de bannière pour un utilisateur américain                                                                                                                                                                                                                                              | Attendu : le RGPD ne s'applique pas. Proposez l'écran US depuis vos réglages (section 7)                                                                                                                                                                                                                                                                                                       |
| L'entrée de réglages affiche la bannière de première visite                                                                                                                                                                                                                                | En 2.0.0 et 2.0.1, attendu : elles n'ont pas de mode de réouverture. Passez à 2.0.2 (section 6). En 2.0.2, l'interface est due à ce moment, un choix manquant ou n'étant que partiel : passez `{ reopen: true }` pour ouvrir quand même le mode de réouverture                                                                                                                                 |
| Depuis l'entrée de réglages, « Continuer sans accepter » laisse enregistré un « Tout accepter » antérieur                                                                                                                                                                                  | 2.0.0 et 2.0.1 rouvrent la bannière de première visite, dont le bouton de refus ne retire pas un choix enregistré, sauf si l'option de refus est « Tout refuser et fermer ». Passez à 2.0.2 : l'entrée de réglages affiche alors « Tout refuser ». Avec 2.0.0 ou 2.0.1, proposez une entrée qui appelle `rejectAll()`, ou indiquez **Paramétrer vos choix**, puis **Tout refuser** (section 6) |
| Changer de `partnerId` ou de `configId` n'a aucun effet                                                                                                                                                                                                                                    | Le SDK est déjà initialisé dans ce processus. Redémarrez l'application, et effacez ses données pour que le consentement de l'ancienne configuration ne soit pas réutilisé (section 9)                                                                                                                                                                                                          |
| `showConsentUI()` est rejetée avec `E_NO_ACTIVITY`                                                                                                                                                                                                                                         | React Native n'avait pas d'activité courante. Appelez-la depuis un écran affiché, pas depuis une tâche en arrière-plan                                                                                                                                                                                                                                                                         |
| iOS : l'interface de consentement n'affiche qu'un indicateur de chargement qui ne disparaît jamais, et `showConsentUI()` n'est jamais résolue                                                                                                                                              | La configuration n'a pas pu être chargée à ce lancement (problème connu de 2.0.0 à 2.0.2, section 4). Redémarrez l'application avec une connexion réseau. Corrigé dans la prochaine version                                                                                                                                                                                                    |
| Android : `addConsentChangeListener` cesse d'émettre                                                                                                                                                                                                                                       | L'activité qui héberge React Native a été détruite alors que JavaScript continuait de tourner (problème connu de 2.0.0 à 2.0.2, section 5). Relisez les valeurs quand l'application redevient active                                                                                                                                                                                           |
| iOS 27 : une application Expo SDK 57 construite avec Xcode 27 plante au lancement, avant toute exécution de JavaScript ; le rapport de plantage montre `_UIApplicationEvaluateRuntimeIssueForNoSceneLifecycleAdoption`                                                                     | Ne vient pas de ce paquet : iOS 27 arrête une application qui n'adopte pas le cycle de vie `UIScene`, et l'app delegate que génère Expo SDK 57 ne l'adopte pas. Une application Expo SDK 57 vierge, sans ce paquet, plante de la même façon (vérifié le 2026-10-07 sur un simulateur iOS 27), et le même build tourne sur iOS 26. Suivez la prise en charge d'iOS 27 par Expo                  |

Pour tout le reste, voir [Dépannage](/applications-mobiles-sdk-natif/mobile-sdk/troubleshooting.md), et indiquez la version du SDK, la plateforme, votre partner ID et votre config ID quand vous contactez Sirdata.

## Pour continuer

* [Transmission du consentement aux SDK partenaires](/applications-mobiles-sdk-natif/mobile-sdk/sharing-consent.md) — comment les SDK publicitaires lisent le consentement collecté
* [Installation Android](/applications-mobiles-sdk-natif/mobile-sdk/setup.md) et [Installation iOS](/applications-mobiles-sdk-natif/mobile-sdk/setup-1.md) — les SDK natifs en dessous


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://cmp.docs.sirdata.net/applications-mobiles-sdk-natif/mobile-sdk/react-native-setup.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
