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

# SDK Android

> Intégrez le SDK Android de Kameleoon pour exécuter des expériences et activer des feature flags dans des applications Android natives.

Avec le SDK Android de Kameleoon, vous pouvez exécuter des feature flags dans des applications mobiles Android natives. Le SDK Android est compatible à la fois avec Kotlin et Java. Le SDK est facile à intégrer dans vos applications, et son utilisation de la mémoire et du réseau est faible.

**Premiers pas** : Pour obtenir de l'aide pour commencer, consultez le [guide du développeur](#guide-du-développeur).

**Journal des modifications** : Dernière version du SDK Android : 4.24.0 [Journal des modifications](https://github.com/Kameleoon/client-android/blob/master/CHANGELOG.md)

**Méthodes du SDK** : Pour la documentation de référence complète des méthodes du SDK Android, consultez la section [référence](#référence).

## Guide du développeur

Suivez cette section pour installer et configurer le SDK Android dans votre application Android et découvrir les fonctionnalités avancées.

### Premiers pas

Suivez ces étapes pour installer et configurer le SDK Android de Kameleoon dans votre application.

#### Installation

Vous pouvez installer le SDK Android en ajoutant la dépendance suivante au fichier `build.gradle` de votre application Android :

```java theme={null}
dependencies {
  implementation 'com.kameleoon:kameleoon-client-android:4.20.0'
}
```

#### Configuration supplémentaire

Pour personnaliser le comportement du SDK, créez un fichier de configuration `.properties`. Le nom et l'emplacement du fichier de propriétés sont importants :

* Créez le fichier dans le répertoire `assets/` de votre application.
* Nommez le fichier `kameleoon-client.properties`.

Vous pouvez également [télécharger un exemple de configuration](/assets/developer-docs/sdks/mobile-sdks/client-configs/kameleoon-client.properties).

Voici les propriétés disponibles que vous pouvez définir :

| Clé                                                                                            | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              | Valeur par défaut     |
| ---------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------- |
| `refreshIntervalMinute` / `refresh_interval_minute` (*optionnel*)                              | Spécifie l'intervalle de rafraîchissement, en minutes, pour que le SDK récupère la configuration des expériences actives et des feature flags. La valeur détermine le temps maximum nécessaire pour propager les modifications, telles que l'activation ou la désactivation des feature flags ou le lancement des expériences. Si elle n'est pas spécifiée, l'intervalle par défaut est de 60 minutes. De plus, un [mode streaming](/developer-docs/feature-experimentation/technical-reference/technical-considerations/#streaming-premium-option) est disponible qui utilise les server-sent events (SSE) pour pousser automatiquement les nouvelles configurations au SDK et les appliquer en temps réel.                                                                                                                                             | `60` minutes          |
| `dataExpirationIntervalMinute` / `data_expiration_interval_minute` (*optionnel*)               | Désigne la période prédéfinie, en minutes, pendant laquelle le SDK stocke le visiteur et ses données associées. Chaque instance de données est évaluée individuellement, ce qui vous permet de définir la durée pendant laquelle le SDK enregistre les données avant de les supprimer automatiquement. Si aucun intervalle n'est spécifié, le SDK ne supprime pas automatiquement les données de l'appareil.                                                                                                                                                                                                                                                                                                                                                                                                                                             | `Integer.MAX_VALUE`   |
| `defaultTimeoutMillisecond` / `default_timeout_millisecond` (*optionnel*)                      | Spécifie l'intervalle de temps, en millisecondes, nécessaire aux requêtes réseau du SDK pour expirer. Définissez la valeur à `30000` millisecondes (30 secondes) ou plus si vous n'avez pas de connexion stable. Certaines méthodes ont des paramètres supplémentaires pour des délais d'expiration spécifiques à la méthode, mais si vous ne les spécifiez pas explicitement, la valeur par défaut est utilisée.                                                                                                                                                                                                                                                                                                                                                                                                                                        | `10000` millisecondes |
| `trackingIntervalMillisecond` / `tracking_interval_millisecond` (*optionnel*)                  | Spécifie l'intervalle pour les requêtes de suivi, en millisecondes. Tous les visiteurs qui ont été évalués pour un feature flag ou dont les données ont été vidées seront inclus dans cette requête de suivi, qui est effectuée une fois par intervalle. La valeur minimale est `1000` ms et la valeur maximale est `5000` ms.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           | `1000` ms             |
| `environment` / `environment` (*optionnel*)                                                    | Pour les clients utilisant l'expérimentation multi-environnement et les feature flags, cette option spécifie quelle configuration de feature flag utiliser. Par défaut, chaque feature flag dispose des options `production`, `staging` et `development`. Si elle n'est pas spécifiée, la valeur par défaut est `production`. [Plus d'informations](/user-manual/experimentation/feature-experimentation/configure-your-feature-flags/manage-environments).                                                                                                                                                                                                                                                                                                                                                                                              | `nil`                 |
| `isUniqueIdentifier` / `is_unique_identifier` (*optionnel*)                                    | Indique que le `visitorCode` spécifié est un identifiant unique.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         | `false`               |
| `networkDomain` / `network_domain` (*optionnel*)                                               | Domaine personnalisé utilisé par les SDK pour les requêtes sortantes, souvent pour le proxy. Doit être un domaine valide (par ex. example.com ou sub.example.com). Les formats invalides utilisent la valeur par défaut de Kameleoon.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    | `nil`                 |
| `defaultDataFile` / `default_datafile` (*optionnel*)                                           | La fonctionnalité `default_datafile` garantit que le SDK Kameleoon est toujours **READY** en fournissant une configuration de secours lorsqu'aucun fichier de données mis en cache n'existe. Les développeurs peuvent précharger une configuration valide en la récupérant depuis `https://sdk-config.kameleoon.eu/v3/<sitecode>` et en la passant comme `default_datafile` lors de l'initialisation. Lorsqu'un horodatage `dateModified` (en millisecondes) est fourni et qu'il est plus récent que la version mise en cache, le SDK utilisera le datafile par défaut au lieu de la version mise en cache. **Si `dateModified` est omis, le datafile par défaut n'est appliqué que lorsqu'aucune version mise en cache n'existe**. Cela garantit que le SDK a toujours une configuration valide, qu'elle soit par défaut, mise en cache ou mise à jour. | `nil`                 |
| `activityTrackingIntervalMillisecond` / `activity_tracking_interval_millisecond` (*optionnel*) | Définit la fréquence à laquelle le SDK envoie un événement d'activité pour prolonger la session du visiteur. La valeur minimale ainsi que la valeur par défaut sont de `60 000` ms ; toute valeur inférieure non nulle est ignorée et la valeur par défaut est appliquée à la place. Définissez-la à `0` pour désactiver le suivi périodique d'activité ; dans ce cas, un seul événement d'activité est envoyé au démarrage. La modification de cette valeur a des effets secondaires, consultez donc [cette section](#using-activitytrackingintervalmillisecond) au préalable.                                                                                                                                                                                                                                                                          | `60 000` ms           |

<Note>
  Si vous spécifiez un `visitorCode` et définissez le paramètre `isUniqueIdentifier` à `true`, les méthodes du SDK utilisent la valeur `visitorCode` comme identifiant unique du visiteur, ce qui est utile pour l'[expérimentation cross-device](/developer-docs/cross-device-experimentation). Le SDK relie les données vidées au visiteur associé à l'identifiant spécifié.

  `isUniqueIdentifier` peut être utile dans d'autres scénarios particuliers, par exemple lorsque vous ne pouvez pas accéder au `visitorCode` anonyme initialement attribué au visiteur, mais que vous avez accès à un identifiant interne connecté au visiteur anonyme via la fusion de sessions.
</Note>

##### Utilisation de `activityTrackingIntervalMillisecond`

Le paramètre `activityTrackingIntervalMillisecond` permet de réduire l'utilisation du réseau et la consommation de batterie en contrôlant la fréquence à laquelle le SDK envoie un événement d'activité pour prolonger la session du visiteur sur la Data API. La valeur par défaut et la valeur minimale autorisée sont de `60 000` ms (60 secondes) ; toute valeur inférieure non nulle est ignorée et la valeur par défaut est appliquée. Les minuteries sont mises en pause lorsque l'application est en arrière-plan, l'intervalle ne progresse donc effectivement que lorsque l'application est au premier plan.

Examinez son impact sur les fonctionnalités suivantes :

1. **[Déclencheurs de temps écoulé](/user-manual/assets/triggers/create-a-trigger#visiting-behavior)**
   * Si le temps écoulé configuré est plus court que l'intervalle de suivi, le déclencheur ne se déclenchera pas comme prévu.

2. **[Segments de temps écoulé](/user-manual/assets/segments/create-a-segment#visiting-behavior)**
   * Si le temps écoulé est plus court que l'intervalle de suivi, les utilisateurs peuvent ne pas être inclus dans le segment comme prévu.

3. **[Objectifs de temps passé](/user-manual/assets/goals/create-a-goal#time-spent)**
   * Si le temps écoulé est plus court que l'intervalle de suivi, l'objectif peut ne jamais être atteint.

4. **[Temps écoulé depuis la dernière visite dans la page des résultats](/user-manual/experiment-analytics/analyze-results/results-page/results-page-settings#filter-audience)**
   * Les mesures pour le "temps écoulé depuis la dernière visite" deviennent moins précises lorsque le temps écoulé est proche ou inférieur à l'intervalle de suivi.

5. **[Nombre de visites](/user-manual/experiment-analytics/troubleshooting/data-discrepancies#how-visits-and-visitors-are-counted)**
   * Une nouvelle visite est créée après 30 minutes d'inactivité. Si l'intervalle de suivi est plus long que 30 minutes, une nouvelle visite sera créée à chaque intervalle de suivi.

<Warning>
  Définir `activityTrackingIntervalMillisecond` à `0` désactive entièrement le suivi périodique d'activité. Dans cette configuration, un seul événement d'activité est envoyé au démarrage de l'application, ce qui rend toutes les fonctionnalités listées ci-dessus inutilisables.
</Warning>

#### Initialiser le client Kameleoon

Après avoir installé le SDK dans votre application et configuré les propriétés de l'application, vous devez créer le client Kameleoon. Un client est un objet singleton qui agit comme un pont entre votre application et la plateforme Kameleoon. Il inclut toutes les méthodes et propriétés dont vous avez besoin pour exécuter un feature flag.

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    import com.kameleoon.KameleoonClient;
    import com.kameleoon.KameleoonClientConfig;
    import com.kameleoon.KameleoonClientFactory;
    import com.kameleoon.KameleoonException;

    public class MyApplication extends Application
    {
        private KameleoonClient kameleoonClient;
        @Override
        public void onCreate() {
            super.onCreate();
            try {
                KameleoonClientConfig config = new KameleoonClientConfig.Builder()
                    .refreshIntervalMinute(15) // in minutes, 1 hour by default, optional
                    .defaultTimeoutMillisecond(10_000) // in milliseconds, 10 seconds by default, optional
                    .trackingIntervalMillisecond(1000) // in milliseconds, 1000 ms by default, optional
                    .dataExpirationIntervalMinute(1440 * 365) // in minutes, infinity by default, optional
                    .environment("staging") // optional
                    .isUniqueIdentifier(false) // optional, false by default. Set to true if the visitorCode corresponds to your customer's unique userId.
                    .networkDomain("example.com") // optional
                    .defaultDataFile("{...}") // optional
                    .activityTrackingIntervalMillisecond(20_000) // optional, 15_000 milliseconds by default
                    .build();
                String siteCode = "a8st4f59bj";
                String visitorCode = "yourVisitorCode";
                kameleoonClient = KameleoonClientFactory.create(siteCode, visitorCode, config, getApplicationContext());
                // or, if you want, the visitor code will be generated automatically
                kameleoonClient = KameleoonClientFactory.create(siteCode, config, getApplicationContext());
            } catch (KameleoonException.SiteCodeIsEmpty | KameleoonException.VisitorCodeInvalid exception) {
                // Exceptions indicate that provided siteCode is empty or visitorCode is invalid
            } catch (Exception exception) {
                // Recommended (but optional) safeguard for unexpected exceptions from third-party libraries
            }
        }
        public KameleoonClient getKameleoonClient() {
            return kameleoonClient;
        }
    }
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    import com.kameleoon.KameleoonClientConfig
    import com.kameleoon.KameleoonClientFactory
    import com.kameleoon.KameleoonException

    class MyApplication : Application() {
        var kameleoonClient: KameleoonClient? = null
            private set

        override fun onCreate() {
            super.onCreate()
            try {
                val config = KameleoonClientConfig.Builder()
                    .refreshIntervalMinute(15) // in minutes, 1 hour by default, optional
                    .defaultTimeoutMillisecond(10_000) // in milliseconds, 10 seconds by default, optional
                    .trackingIntervalMillisecond(1000) // in milliseconds, 1000 ms by default, optional
                    .dataExpirationIntervalMinute(1440 * 365) // in minutes, infinity by default, optional
                    .environment("staging") // optional
                    .networkDomain("example.com") // optional
                    .defaultDataFile("{...}") // optional
                    .activityTrackingIntervalMillisecond(20_000) // optional, 15_000 milliseconds by default
                    .build()
                val siteCode = "a8st4f59bj"
                val visitorCode = "yourVisitorCode"
                val kameleoonClient = KameleoonClientFactory.create(siteCode, visitorCode, config, applicationContext)
                // or if you want that visitor code will be generated automaticallyd
                kameleoonClient = KameleoonClientFactory.create(siteCode, config, applicationContext)
            } catch (e: KameleoonException.SiteCodeIsEmpty) {
                // Exception indicating that provided siteCode is empty
            } catch (e: KameleoonException.VisitorCodeInvalid) {
                // Exception indicating that provided visitor code is invalid
            } catch (e: Exception) {
                // Recommended (but optional) safeguard for unexpected exceptions from third-party libraries
            }
        }
    }
    ```
  </Tab>
</Tabs>

Lors de son exécution, la méthode `KameleoonClientFactory.create()` initialise le client, mais il n'est pas immédiatement prêt à être utilisé. Ce délai s'explique par le fait que le client Kameleoon doit récupérer la configuration actuelle des feature flags (ainsi que leur répartition du trafic) auprès d'un serveur distant de Kameleoon. Cette récupération nécessite un accès réseau, qui n'est pas toujours disponible. Tant que le client Kameleoon n'est pas entièrement prêt, vous ne devez pas tenter d'exécuter d'autres méthodes dans le SDK Android de Kameleoon. Notez qu'une fois que la première configuration des feature flags est récupérée, elle est ensuite rafraîchie périodiquement, mais même si le rafraîchissement échoue pour une raison quelconque, le client Kameleoon continuera de fonctionner en utilisant la configuration précédente.

Vous pouvez utiliser la méthode [`isReady()`](#isready) pour vérifier si l'initialisation du client Kameleoon est terminée.

Alternativement, un **callback d'assistance** peut encapsuler la logique de déclenchement des feature flags et l'implémentation des variations. La meilleure approche ([`isReady()`](#isready) ou **callback**) dépend des préférences et du cas d'utilisation exact. L'utilisation de [`isReady()`](#isready) est recommandée lorsque le SDK est censé être prêt à être utilisé rapidement. Par exemple, `isReady()` est approprié lors de l'exécution d'un feature flag sur une boîte de dialogue à laquelle les utilisateurs n'accéderont probablement pas pendant les premières secondes ou minutes de navigation dans l'application. Un callback est recommandé lorsqu'il y a une forte probabilité que le SDK soit encore en cours d'initialisation. Par exemple, un feature flag qui apparaît à l'écran au lancement de l'application doit utiliser un callback qui fait attendre l'application jusqu'à ce que le SDK soit prêt ou qu'un délai spécifié soit expiré.

<Note>
  Il est de votre responsabilité, en tant que développeur de l'application, de vous assurer que la logique de votre code d'application est correcte dans le contexte de l'A/B test utilisant Kameleoon. Une bonne pratique est de toujours supposer que l'utilisateur de l'application peut être exclu du feature flag lorsque le client Kameleoon n'est pas encore prêt. Cette exclusion est facile à mettre en œuvre, car elle correspond à l'implémentation de la logique de variation par défaut ou de référence. Les exemples de code du paragraphe suivant montrent des exemples de cette approche.
</Note>

Vous êtes maintenant prêt à implémenter la gestion des fonctionnalités et les feature flags. Consultez la section [Référence](#référence) pour plus de détails sur les méthodes supplémentaires.

#### Bonnes pratiques pour l'initialisation et l'utilisation

* Il est recommandé d'initialiser [`KameleoonClient`](#create) en tant que singleton dès que possible après le démarrage de l'application, car l'initialisation peut prendre un certain temps. Étant donné que l'initialisation est asynchrone, elle ne bloque pas et ne retarde pas le processus de démarrage de l'application.
* Avant d'utiliser `KameleoonClient`, vérifiez qu'il est initialisé en appelant la méthode [`runWhenReady`](#runwhenready). Sinon, les tentatives d'utilisation du client avant qu'il ne soit prêt entraîneront des erreurs.
* ⚠️ La plupart des méthodes clés peuvent lever des exceptions, une gestion appropriée des exceptions est donc requise. Assurez-vous de consulter la documentation de chaque méthode que vous utilisez pour comprendre ses exceptions potentielles.

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    // Initialize `KameleoonClient` on application startup and use it as a singleton later
    try {
        KameleoonClient kameleoonClient = KameleoonClientFactory.create("<siteCode>", getApplicationContext());
    } catch (KameleoonException ignored) {}

    // Example: Apply a discount percentage based on an feature flag variable's value
    void applyDiscountIfApplicable() {
        kameleoonClient.runWhenReady(1000, result -> {
            double discount = 0.0;
            try {
                if (result.getOrThrow()) {
                    Variation variation = kameleoonClient.getVariation("discount");
                    discount = (double) variation.getVariables().get("discount_value").getValue();
                }
            } catch (Exception ignored) { }

            if (discount > 0) {
                applyDiscount(discount);
            }
        });
    }
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    // Initialize `KameleoonClient` on application startup and use it as a singleton later
    try {
        KameleoonClient kameleoonClient = KameleoonClientFactory.create("<siteCode>", applicationContext)
    } catch (ignored: KameleoonException) {}

    // Example: Apply a discount percentage based on a feature flag variable's value
    fun applyDiscountIfApplicable() {
        kameleoonClient.runWhenReady(1000) { result ->
            val discount = runCatching {
                if (result.getOrThrow()) {
                    val variation = kameleoonClient.getVariation("discount")
                    variation.variables["discount_value"]?.value as? Double
                } else {
                    null
                }
            }.getOrNull() ?: 0.0

            if (discount > 0) {
                applyDiscount(discount)
            }
        }
    }
    ```
  </Tab>

  <Tab title="Kotlin (Coroutines)">
    ```kotlin theme={null}
    // Initialize `KameleoonClient` on application startup and use it as a singleton later
    try {
        val kameleoonClient = KameleoonClientFactory.create("<siteCode>", applicationContext)
    } catch (ignored: KameleoonException) {}

    // Example: Apply a discount percentage based on a feature flag variable's value
    suspend fun applyDiscountIfApplicable() {
        kameleoonClient.runWhenReady(1000).getOrNull() ?: return // Exit if initialization fails

        val discount = runCatching {
            val variation = kameleoonClient.getVariation("discount")
            variation.variables["discount_value"]?.value as? Double
        }.getOrNull() ?: 0.0

        if (discount > 0) {
            applyDiscount(discount)
        }
    }
    ```
  </Tab>
</Tabs>

#### Activer un feature flag

##### Récupérer la configuration d'un flag

Pour implémenter un feature flag dans votre code, vous devez d'abord créer le feature flag dans votre compte Kameleoon.

Pour déterminer le statut ou la variation d'un feature flag pour un utilisateur spécifique, vous devez utiliser la méthode [`getVariation()`](#getvariation) ou [`isFeatureActive()`](#isfeatureactive) afin de récupérer la configuration basée sur le `featureKey`.

La méthode `getVariation()` gère à la fois les feature flags simples avec des états ON/OFF et les flags plus complexes avec plusieurs variations. La méthode récupère la variation appropriée pour l'utilisateur en vérifiant les règles de fonctionnalité, en attribuant la variation et en la retournant en fonction du `featureKey` et du `visitorCode`.

La méthode `isFeatureActive()` peut être utilisée si vous souhaitez récupérer la configuration d'un feature flag simple qui n'a qu'un état ON ou OFF, par opposition aux feature flags plus complexes avec plusieurs variations ou options de ciblage.

Si votre feature flag a des variables associées (telles que des comportements spécifiques liés à chaque variation), `getVariation()` vous permet également d'accéder à l'objet [`Variation`](#variation), qui fournit des détails sur la variation attribuée et son expérience associée. Cette méthode vérifie si l'utilisateur est ciblé, trouve la variation attribuée au visiteur et l'enregistre dans le stockage. Lorsque `track=true`, le SDK enverra l'événement d'exposition à l'expérience spécifiée lors de la prochaine requête de suivi, qui est automatiquement déclenchée en fonction du [`tracking_interval_millisecond`](#configuration-supplémentaire) du SDK. Par défaut, cet intervalle est défini à 1000 millisecondes (1 seconde).

La méthode `getVariation()` vous permet de contrôler si le suivi est effectué. Si `track=false`, aucun événement d'exposition ne sera envoyé par le SDK. C'est utile si vous préférez ne pas suivre les données via le SDK et vous appuyer à la place sur le suivi côté client géré par le moteur Kameleoon, par exemple. De plus, définir `track=false` est utile lors de l'utilisation de la méthode `getVariations()`, où vous n'avez peut-être besoin que des variations de tous les flags sans déclencher d'événements de suivi. Si vous souhaitez en savoir plus sur le fonctionnement du suivi, consultez [cet article](/developer-docs/feature-experimentation/technical-reference/faq-global#when-does-the-sdk-send-a-tracking-request-for-analytics)

##### Ajouter des points de données pour cibler un utilisateur ou filtrer / répartir les visites dans les rapports

Pour cibler un utilisateur, assurez-vous d'avoir ajouté les points de données pertinents à son profil avant de récupérer la variation de la fonctionnalité ou de vérifier si le flag est actif. Utilisez la méthode [`addData()`](#adddata) pour ajouter ces points de données au profil de l'utilisateur.

Pour récupérer les points de données collectés sur d'autres appareils, utilisez la méthode [`getRemoteVisitorData()`](#getremotevisitordata). Cette méthode récupère les données des serveurs de manière asynchrone. Il est important d'appeler `getRemoteVisitorData()` *avant* de récupérer la variation ou de vérifier si le feature flag est actif, car ces données peuvent être nécessaires pour attribuer un utilisateur à une variation donnée.

Pour en savoir plus sur les conditions de ciblage disponibles, consultez l'[article détaillé sur le sujet](/developer-docs/feature-experimentation/targeting-and-segmentation/native-segmentation).

De plus, les points de données que vous ajoutez au profil du visiteur seront disponibles lors de l'analyse de vos expériences, vous permettant de filtrer et de répartir vos résultats selon des facteurs comme l'appareil. Consultez la liste complète [ici](/fr/user-manual/experiment-analytics/analyze-results/results-page/results-page-settings#ventiler-l’audience).

Si vous devez suivre des points de données supplémentaires au-delà de ce qui est collecté automatiquement, vous pouvez utiliser la [fonctionnalité de données personnalisées](#customdata) de Kameleoon. Les données personnalisées vous permettent de capturer et d'analyser des informations spécifiques pertinentes pour vos expériences. N'oubliez pas d'appeler la méthode [`flush()`](#flush) pour envoyer les données collectées aux serveurs Kameleoon pour analyse.

##### Suivre les conversions d'objectifs

Lorsqu'un utilisateur réalise une action souhaitée (comme effectuer un achat), elle est enregistrée comme une conversion. Pour suivre les conversions, utilisez la méthode [`trackConversion()`](#trackconversion) et fournissez le paramètre requis `goalId`.

La requête de suivi de conversion sera envoyée avec la prochaine requête de suivi planifiée, que le SDK envoie à intervalles réguliers (défini par [`tracking_interval_millisecond`](#configuration-supplémentaire)). Si vous préférez envoyer la requête immédiatement, utilisez la méthode [`flush()`](#flush) avec le paramètre `instant=true`.

### Expérimentation cross-device

Pour prendre en charge les visiteurs qui accèdent à une application depuis plusieurs appareils, Kameleoon permet la synchronisation des données de visiteurs précédemment collectées sur chacun des appareils du visiteur et la réconciliation de leur historique de visites entre les appareils via l'expérimentation cross-device. Des études de cas et des informations détaillées sur la façon dont Kameleoon gère les données entre les appareils sont disponibles dans l'[article sur l'expérimentation cross-device](/developer-docs/cross-device-experimentation).

#### Synchroniser les données personnalisées entre appareils

Bien que la synchronisation du mapping personnalisé soit utilisée pour aligner les données des visiteurs entre les appareils, elle n'est pas toujours nécessaire. Voici deux scénarios dans lesquels la synchronisation du mapping personnalisé n'est pas requise :

**Même ID utilisateur sur tous les appareils**
Si le même ID utilisateur est utilisé de manière cohérente sur tous les appareils, la synchronisation est gérée automatiquement sans synchronisation de mapping personnalisé. Il suffit d'appeler la méthode `getRemoteVisitorData()` lorsque vous souhaitez synchroniser les données collectées entre plusieurs appareils.

**Instances multi-serveurs avec IDs cohérents**
Dans les configurations complexes impliquant plusieurs serveurs (par exemple, des instances de serveurs distribués), où le même ID utilisateur est disponible sur tous les serveurs, la synchronisation entre les serveurs (avec `getRemoteVisitorData()`) est suffisante sans synchronisation supplémentaire de mapping personnalisé.

Les clients qui ont besoin de données supplémentaires peuvent se référer à la description de la méthode [`getRemoteVisitorData()`](#getremotevisitordata) pour plus de conseils. Dans le code ci-dessous, on suppose que le même identifiant unique (dans ce cas, le `visitorCode`, qui peut également être appelé `userId`) est utilisé de manière cohérente entre les deux appareils pour une récupération précise des données.

<Note>
  Si vous souhaitez synchroniser les données collectées en temps réel, vous devez choisir la portée **Visiteur** pour vos données personnalisées.
</Note>

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java title="Device A" theme={null}
    // In this, example Custom data with index `90` was set to "Visitor" scope in Kameleoon.
    final int VISITOR_SCOPE_CUSTOM_DATA_INDEX = 90;

    kameleoonClient.addData(new CustomData(VISITOR_SCOPE_CUSTOM_DATA_INDEX, "your data"));
    kameleoonClient.flush();
    ```

    ```java title="Device B" theme={null}
    // Before working with the data, call `getRemoteVisitorData`.
    kameleoonClient.getRemoteVisitorData(result -> {
        // After calling, the SDK on Device B will have access to CustomData of Visitor scope defined on Device A.
        // So, "your data" will be available to target and track the visitor.
    });
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin title="Device A" theme={null}
    // In this example Custom data with index `90` was set to "Visitor" scope on Kameleoon Platform.
    val VISITOR_SCOPE_CUSTOM_DATA_INDEX = 90

    kameleoonClient.addData(CustomData(VISITOR_SCOPE_CUSTOM_DATA_INDEX, "your data"))
    kameleoonClient.flush()
    ```

    ```kotlin title="Device B" theme={null}
    // Before working with the data, call the `getRemoteVisitorData` method.
    kameleoonClient.getRemoteVisitorData { result ->
        // After that the SDK on Device B will have an access to CustomData of Visitor scope defined on Device A.
        // So "your data" will be available for targeting and tracking for the visitor.
    }
    ```
  </Tab>

  <Tab title="Kotlin (Coroutines)">
    ```kotlin title="Device A" theme={null}
    // In this example Custom data with index `90` was set to "Visitor" scope on Kameleoon Platform.
    val VISITOR_SCOPE_CUSTOM_DATA_INDEX = 90

    kameleoonClient.addData(CustomData(VISITOR_SCOPE_CUSTOM_DATA_INDEX, "your data"))
    kameleoonClient.flush()
    ```

    ```kotlin title="Device B" theme={null}
    // Before working with the data, call the `getRemoteVisitorData` method.
    kameleoonClient.getRemoteVisitorData()
    // After that the SDK on Device B will have an access to CustomData of Visitor scope defined on Device A.
    // So "your data" will be available for targeting and tracking for the visitor.
    ```
  </Tab>
</Tabs>

#### Utilisation des données personnalisées pour la fusion de sessions

L'[expérimentation cross-device](/developer-docs/cross-device-experimentation) permet de combiner l'historique d'un visiteur sur chacun de ses appareils (réconciliation de l'historique). La réconciliation de l'historique permet de fusionner différentes sessions de visiteur en une seule. Pour réconcilier l'historique des visites, utilisez [`CustomData`](#customdata) pour fournir un identifiant unique au visiteur. Pour plus d'informations, consultez la [documentation dédiée](/developer-docs/cross-device-experimentation/#activating-cross-device-history-reconciliation).

Une fois la réconciliation cross-device activée, l'appel à [`getRemoteVisitorData()`](#getremotevisitordata) avec le paramètre `userId` récupère toutes les données connues pour un utilisateur donné.

Les sessions ayant le même identifiant verront toujours la même variation dans une expérience. Dans la vue Visiteur des pages de résultats de votre expérience, ces sessions apparaîtront comme un seul visiteur.

La configuration du SDK garantit que les sessions associées voient toujours la même variation de l'expérience. Cependant, il existe certaines limitations concernant l'allocation des variations cross-device. Ces limitations sont décrites [ici](/developer-docs/cross-device-experimentation#critical-points-and-practical-insights).

Suivez le guide [activation de la réconciliation de l'historique cross-device](#expérimentation-cross-device) pour configurer vos données personnalisées sur la plateforme Kameleoon.

Ensuite, vous pouvez utiliser le SDK normalement. Les méthodes suivantes peuvent être utiles dans le contexte de la fusion de sessions :

* `getRemoteVisitorData()` avec `isUniqueIdentifier=true` passé à [`KameleoonClientConfig`](#configuration-supplémentaire) - pour récupérer les données de tous les visiteurs liés.
* [`trackConversion()`](#trackconversion) ou [`flush()`](#flush) avec `isUniqueIdentifier=true` passé à `KameleoonClientConfig` - pour suivre certaines données pour un visiteur spécifique associé à un autre visiteur.

<Tip>
  Comme les données personnalisées que vous utilisez comme identifiant doivent être définies sur la **portée Visiteur**, vous devez utiliser la [synchronisation des données personnalisées cross-device](/developer-docs/cross-device-experimentation) pour récupérer l'identifiant avec la méthode [`getRemoteVisitorData()`](#getremotevisitordata) sur chaque appareil.
</Tip>

Voici un exemple d'utilisation des données personnalisées pour la fusion de sessions.

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    // In this example, `91` represents the Custom Data's index,
    // configured as a unique identifier in Kameleoon.
    final int MAPPING_INDEX = 91;
    final String FEATURE_KEY = "ff123";

    // 0. Initializing anonymous KameleoonClient

    // Assume `anonymousVisitorCode` is the randomly generated ID for that visitor.
    KameleoonClient anonymousKameleoonClient = KameleoonClientFactory.create(siteCode, anonymousVisitorCode, getApplicationContext());
    anonymousKameleoonClient.runWhenReady(result -> {
        // ...
    });

    // 1. Before the visitor is authenticated

    // Retrieve the variation for an unauthenticated visitor.
    Variation anonymousVariation = anonymousKameleoonClient.getVariation(FEATURE_KEY);

    // 2. After the visitor is authenticated

    // Assume `userId` is the authenticated visitor's visitor code.
    anonymousKameleoonClient.addData(new CustomData(MAPPING_INDEX, userId));
    anonymousKameleoonClient.flush(true);

    KameleoonClient userKameleoonClient = KameleoonClientFactory.create(
        siteCode, userId,
        (new KameleoonClientConfig.Builder())
            .isUniqueIdentifier(true) // Indicate that `userId` is a unique identifier
            .build(),
        getApplicationContext()
    );
    userKameleoonClient.runWhenReady(result -> {
        // ...
    });

    // 3. After the visitor has been authenticated

    // Retrieve the variation for the `userId`, which will match the anonymous visitor code's variation.
    Variation userVariation = userKameleoonClient.getVariation(FEATURE_KEY);
    boolean isSameVariation = userVariation.getKey().equals(anonymousVariation.getKey()); // true

    // The `userId` and `anonymousVisitorCode` are now linked and tracked as a single visitor.
    kameleoonClient.trackConversion(123, 10.0f);

    // Additionally, the linked visitors will share all fetched remote visitor data.
    kameleoonClient.getRemoteVisitorData(result -> {
        // ...
    });
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    // In this example, `91` represents the Custom Data's index
    // configured as a unique identifier in Kameleoon.
    val MAPPING_INDEX = 91
    val FEATURE_KEY = "ff123"

    // 0. Initializing anonymous KameleoonClient

    // Assume `anonymousVisitorCode` is the randomly generated ID for that visitor.
    val anonymousKameleoonClient = KameleoonClientFactory.create(siteCode, anonymousVisitorCode, applicationContext)
    anonymousKameleoonClient.runWhenReady { result ->
        // ...
    }

    // 1. Before the visitor is authenticated

    // Retrieve the variation for an unauthenticated visitor.
    val anonymousVariation = anonymousKameleoonClient.getVariation(FEATURE_KEY)

    // 2. After the visitor is authenticated

    // Assume `userId` is the authenticated visitor's visitor code.
    anonymousKameleoonClient.addData(CustomData(MAPPING_INDEX, userId))
    anonymousKameleoonClient.flush(true)

    val userKameleoonClient = KameleoonClientFactory.create(
        siteCode, userId,
        KameleoonClientConfig.Builder()
            .isUniqueIdentifier(true) // Indicate that `userId` is a unique identifier
            .build(),
        applicationContext
    )
    userKameleoonClient.runWhenReady { result ->
        // ...
    }

    // 3. After the visitor has been authenticated

    // Retrieve the variation for the `userId`, which will match the anonymous visitor code's variation.
    val userVariation = userKameleoonClient.getVariation(FEATURE_KEY)
    val isSameVariation = userVariation.getKey() == anonymousVariation.getKey() // true

    // The `userId` and `anonymousVisitorCode` are now linked and tracked as a single visitor.
    userKameleoonClient.trackConversion(123, 10.0f)

    // Additionally, the linked visitors will share all fetched remote visitor data.
    userKameleoonClient.getRemoteVisitorData { result ->
        // ...
    }
    ```
  </Tab>

  <Tab title="Kotlin (Coroutines)">
    ```kotlin theme={null}
    // In this example, `91` represents the Custom Data's index
    // configured as a unique identifier in Kameleoon.
    val MAPPING_INDEX = 91
    val FEATURE_KEY = "ff123"

    // 0. Initializing anonymous KameleoonClient

    // Assume `anonymousVisitorCode` is the randomly generated ID for that visitor.
    val anonymousKameleoonClient = KameleoonClientFactory.create(siteCode, anonymousVisitorCode, applicationContext)
    anonymousKameleoonClient.runWhenReady()

    // 1. Before the visitor is authenticated

    // Retrieve the variation for an unauthenticated visitor.
    val anonymousVariation = anonymousKameleoonClient.getVariation(FEATURE_KEY)

    // 2. After the visitor is authenticated

    // Assume `userId` is the authenticated visitor's visitor code.
    anonymousKameleoonClient.addData(CustomData(MAPPING_INDEX, userId))
    anonymousKameleoonClient.flush(true)

    val userKameleoonClient = KameleoonClientFactory.create(
        siteCode, userId,
        KameleoonClientConfig.Builder()
            .isUniqueIdentifier(true) // Indicate that `userId` is a unique identifier
            .build(),
        applicationContext
    )
    userKameleoonClient.runWhenReady()

    // 3. After the visitor has been authenticated

    // Retrieve the variation for the `userId`, which will match the anonymous visitor code's variation.
    val userVariation = userKameleoonClient.getVariation(FEATURE_KEY)
    val isSameVariation = userVariation.getKey() == anonymousVariation.getKey() // true

    // The `userId` and `anonymousVisitorCode` are now linked and tracked as a single visitor.
    userKameleoonClient.trackConversion(123, 10.0f)

    // Additionally, the linked visitors will share all fetched remote visitor data.
    userKameleoonClient.getRemoteVisitorData()
    ```
  </Tab>
</Tabs>

Dans cet exemple, l'application possède une page de connexion. L'ID utilisateur étant inconnu au moment de la connexion, un visiteur anonyme généré automatiquement par le SDK est utilisé. Le code visiteur peut être récupéré avec la méthode [`getVisitorCode()`](#getvisitorcode). Une fois que l'utilisateur se connecte, le visiteur anonyme est associé à l'ID utilisateur et utilisé comme identifiant unique pour le visiteur.

### Utiliser une clé de bucketing personnalisée

Par défaut, Kameleoon utilise un identifiant unique et anonyme de visiteur (`visitorCode`) pour attribuer les utilisateurs aux variations de feature flags. Cet identifiant est généralement généré et stocké sur l'appareil de l'utilisateur (dans un cookie de navigateur pour les SDKs côté client et côté serveur — dans un stockage persistant pour les SDKs mobiles). Cependant, dans certains scénarios, vous pourriez avoir besoin de vous assurer que tous les utilisateurs d'une même organisation voient la même variante d'un feature flag.

L'option **Clé de bucketing personnalisée** vous permet de remplacer ce comportement par défaut en fournissant votre propre identifiant personnalisé pour le bucketing. Ce remplacement garantit que la logique d'attribution de Kameleoon utilise la clé que vous avez spécifiée au lieu du `visitorCode` par défaut.

#### Cas d'usage

L'utilisation d'une clé de bucketing personnalisée est essentielle pour maintenir la cohérence et la précision de vos attributions de feature flags, en particulier dans ces situations :

* **Expériences au niveau du compte ou de l'organisation :** Pour les produits B2B ou les scénarios dans lesquels vous souhaitez attribuer tous les utilisateurs d'une même organisation à la même variation, vous pouvez utiliser un identifiant comme `accountId`. Les clés de bucketing personnalisées sont cruciales pour les A/B tests de fonctionnalités qui impactent toute une équipe ou une entreprise.

En implémentant une clé de bucketing personnalisée, vous garantissez une meilleure cohérence et précision dans vos expériences, conduisant à des résultats plus fiables et à une meilleure expérience utilisateur.

#### Détails techniques

Lorsque vous configurez une clé de bucketing personnalisée pour un feature flag, vous fournissez à Kameleoon un identifiant spécifique provenant des données de votre application :

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    kameleoonClient.addData(new CustomData(index, "newVisitorCode"));
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    kameleoonClient.addData(CustomData(index, "newVisitorCode"))
    ```
  </Tab>
</Tabs>

* **Fournir la clé personnalisée :** Vous fournissez votre identifiant personnalisé au SDK Kameleoon en utilisant la méthode [`addData()`](#adddata). Dans cette méthode, vous passerez votre clé de bucketing personnalisée choisie sous forme d'objet [`CustomData`](#customdata). Ici, `newVisitorCode` fait référence à l'identifiant que vous souhaitez utiliser pour votre bucketing (par exemple, le nouvel `userId` ou `accountId`).

<Warning>
  Pour que la clé de bucketing personnalisée fonctionne correctement, elle doit également être définie et configurée pour le feature flag lors du processus de création ou de modification du flag. Sans cette configuration correspondante, le bucketing du SDK n'appliquera pas votre clé personnalisée. Pour des instructions détaillées sur la façon de configurer cela dans Kameleoon, consultez cet [article](/user-manual/experimentation/feature-experimentation/create-and-manage-flags/create-a-feature-flag#Advanced_Flag_Settings).
</Warning>

* **Logique de bucketing :** Une fois qu'une clé de bucketing personnalisée est fournie via la méthode `addData()`, tous les calculs de hachage pour l'attribution des utilisateurs aux variations utiliseront ce `newVisitorCode` (votre clé personnalisée) au lieu du `visitorCode` par défaut. L'utilisation du `newVisitorCode` signifie que la décision de bucketing est liée à votre identifiant personnalisé, garantissant des attributions cohérentes dans divers contextes où cet identifiant est présent.
* **Suivi des données et analytics :** Il est crucial de noter que, bien que le `newVisitorCode` (votre clé personnalisée) soit utilisé pour les décisions de bucketing, **toutes les données ultérieures (événements de suivi et conversions, par exemple) sont envoyées et associées au `visitorCode` *d'origine*.** Cette séparation garantit que vos analytics reflètent avec précision les parcours et interactions individuels des utilisateurs dans le contexte plus large de votre expérience, même lorsque le bucketing est effectué à un niveau supérieur (comme un compte) ou sur plusieurs appareils/sessions. Vos données visiteur d'origine restent intactes pour un reporting complet.

#### Exigences techniques

Pour utiliser efficacement une clé de bucketing personnalisée :

* La clé doit être une `String`.
* Elle doit être unique pour l'entité que vous souhaitez bucketiser (par exemple, si vous utilisez un `userId`, l'ID de chaque utilisateur doit être unique).
* La clé doit être disponible pour le SDK au moment exact où la décision du feature flag est évaluée pour cet utilisateur ou cette requête.

### Conditions de ciblage

Les SDKs Kameleoon prennent en charge une variété de conditions de ciblage prédéfinies que vous pouvez utiliser pour cibler les utilisateurs dans vos campagnes. Pour la liste des conditions que ce SDK prend en charge, consultez [utiliser l'historique des visites pour cibler les utilisateurs](/developer-docs/feature-experimentation/targeting-and-segmentation/native-segmentation).

Vous pouvez également utiliser vos propres [données externes pour cibler les utilisateurs](/developer-docs/apis/data-api-rest/tutorials/storing-and-retrieving-external-data-to-target-users).

### Gestion des erreurs

Toutes les méthodes du **SDK Kameleoon** peuvent lever **uniquement** `KameleoonException` ou ses exceptions héritées documentées (listées dans la section *Exceptions levées* pour chaque méthode).
Ces exceptions sont un **comportement attendu** du SDK. Si vous souhaitez gérer différemment des scénarios spécifiques, vous pouvez attraper les exceptions héritées individuellement ; sinon, attraper `KameleoonException` gérera toutes les erreurs liées au SDK.

Bien que nos **tests unitaires et d'intégration** confirment que le SDK **ne lève jamais** `Exception` ou `RuntimeException`, nous comprenons que **patcher les versions du SDK sur Android peut être difficile**, et des problèmes inattendus peuvent survenir provenant de **bibliothèques tierces** susceptibles de lever une `RuntimeException`. Pour empêcher votre application de planter dans de tels cas rares, nous vous recommandons également d'**attraper `Exception` (ou `RuntimeException`)** comme protection supplémentaire. Il s'agit strictement d'une précaution et **non d'un comportement attendu du SDK**.

Par exemple :

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    try {
        // Calling a method of the SDK
    } catch (KameleoonException e) {
        // Handling expected exceptions
    } catch (Exception e) {
        // Recommended (but optional) safeguard for unexpected exceptions from third-party libraries
    }
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    try {
        // Calling a method of the SDK
    } catch (e: KameleoonException) {
        // Handling expected exceptions
    } catch (e: Exception) {
        // Recommended (but optional) safeguard for unexpected exceptions from third-party libraries
    }
    ```
  </Tab>
</Tabs>

### Logging

Le SDK génère des logs pour refléter divers processus internes et problèmes.

#### Niveaux de log

Le SDK prend en charge la configuration de la limitation du logging par un niveau de log.

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    // The `NONE` log level does not allow logging.
    com.kameleoon.logging.KameleoonLogger.setLogLevel(com.kameleoon.logging.LogLevel.NONE);

    // The `ERROR` log level only allows logging issues that may affect the SDK's main behaviour.
    com.kameleoon.logging.KameleoonLogger.setLogLevel(com.kameleoon.logging.LogLevel.ERROR);

    // The `WARNING` log level allows logging issues which may require additional attention.
    // It extends the `ERROR` log level.
    // The `WARNING` log level is a default log level.
    com.kameleoon.logging.KameleoonLogger.setLogLevel(com.kameleoon.logging.LogLevel.WARNING);

    // The `INFO` log level allows logging general information on the SDK's internal processes.
    // It extends the `WARNING` log level.
    com.kameleoon.logging.KameleoonLogger.setLogLevel(com.kameleoon.logging.LogLevel.INFO);

    // The `DEBUG` level logs additional details about the SDK’s internal processes and extends the `INFO` level
    // with more granular. diagnostic output.
    // This information is not intended for end-user interpretation but can be sent to our support team
    // to assist with internal troubleshooting.
    com.kameleoon.logging.KameleoonLogger.setLogLevel(com.kameleoon.logging.LogLevel.DEBUG);
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    // The `NONE` log level allows no logging.
    com.kameleoon.logging.KameleoonLogger.setLogLevel(com.kameleoon.logging.LogLevel.NONE)

    // The `ERROR` log level allows to log only issues that may affect the SDK's main behaviour.
    com.kameleoon.logging.KameleoonLogger.setLogLevel(com.kameleoon.logging.LogLevel.ERROR)

    // The `WARNING` log level allows to log issues which may require an attention.
    // It extends the `ERROR` log level.
    // The `WARNING` log level is a default log level.
    com.kameleoon.logging.KameleoonLogger.setLogLevel(com.kameleoon.logging.LogLevel.WARNING)

    // The `INFO` log level allows to log general information on the SDK's internal processes.
    // It extends the `WARNING` log level.
    com.kameleoon.logging.KameleoonLogger.setLogLevel(com.kameleoon.logging.LogLevel.INFO)

    // The `DEBUG` log level allows to log extra information on the SDK's internal processes.
    // It extends the `INFO` log level.
    com.kameleoon.logging.KameleoonLogger.setLogLevel(com.kameleoon.logging.LogLevel.DEBUG)
    ```
  </Tab>
</Tabs>

#### Gestion personnalisée des logs

Le SDK écrit ses logs sur la sortie console par défaut. Ce comportement peut être remplacé.

<Note>
  La limitation du logging par un niveau de log est effectuée séparément de la logique de gestion des logs.
</Note>

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    public class CustomLogger implements com.kameleoon.logging.Logger {
        // `log` method accepts logs from the SDK
        @Override
        public void log(com.kameleoon.logging.LogLevel level, String message) {
            // Custom log handling logic here. For example:
            switch (level) {
                case ERROR:
                    android.util.Log.e("your-log-tag", message);
                    break;
                case WARNING:
                    android.util.Log.w("your-log-tag", message);
                    break;
                case INFO:
                    android.util.Log.i("your-log-tag", message);
                    break;
                case DEBUG:
                    android.util.Log.d("your-log-tag", message);
                    break;
                default:
            }
        }
    }


    // Log level filtering is applied separately from log handling logic.
    // The custom logger will only accept logs that meet or exceed the specified log level.
    // Ensure the log level is set correctly.
    com.kameleoon.logging.KameleoonLogger.setLogLevel(com.kameleoon.logging.LogLevel.DEBUG); // Optional, defaults to `LogLevel.WARNING`.
    com.kameleoon.logging.KameleoonLogger.setLogger(new CustomLogger());
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    class CustomLogger : com.kameleoon.logging.Logger {

        override fun log(level: com.kameleoon.logging.LogLevel, message: String) {
            // Custom log handling logic here. For example:
            when (level) {
                com.kameleoon.logging.LogLevel.ERROR -> android.util.Log.e("your-log-tag", message)
                com.kameleoon.logging.LogLevel.WARNING -> android.util.Log.w("your-log-tag", message)
                com.kameleoon.logging.LogLevel.INFO -> android.util.Log.i("your-log-tag", message)
                com.kameleoon.logging.LogLevel.DEBUG -> android.util.Log.d("your-log-tag", message)
                else -> {
                    // Optional: handle default case if needed
                }
            }
        }
    }

    // Log level filtering is applied separately from log handling logic.
    // The custom logger will only accept logs that meet or exceed the specified log level.
    // Ensure the log level is set correctly.
    com.kameleoon.logging.KameleoonLogger.setLogLevel(com.kameleoon.logging.LogLevel.DEBUG) // Optional, defaults to `LogLevel.WARNING`.
    com.kameleoon.logging.KameleoonLogger.setLogger(CustomLogger())
    ```
  </Tab>
</Tabs>

### Transmettre le code visiteur à une WebView

Dans certains cas, vous devrez peut-être transmettre le **code visiteur** de l'application native à une WebView qui utilise [Engine.js](/developer-docs/web-experimentation/implementation-and-deployment/standard-implementation) ou les SDKs web [JavaScript](/developer-docs/sdks/web-sdks/js-sdk) ou [React](/developer-docs/sdks/web-sdks/react-js-sdk). L'exemple suivant illustre la manière recommandée d'y parvenir :

<Tabs defaultTabIndex={0}>
  <Tab title="Kotlin">
    ```kotlin theme={null}
    class WebViewActivity : AppCompatActivity() {

        private var webView: WebView? = null

        private val DEFAULT_URL = "https://example.com"
        private val COOKIE_NAME = "kameleoonVisitorCode"
        private val COOKIE_DOMAIN = ".example.com"

        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)

            webView = WebView(this).also { webView ->
                setContentView(webView)
                configureWebView(DEFAULT_URL, kameleoonClient)
                webView.loadUrl(DEFAULT_URL)
            }
        }

        private fun configureWebView(url: String, kameleoonClient: KameleoonClient) {
            CookieManager.getInstance().apply {
                setCookie(
                    url,
                    "$COOKIE_NAME=${kameleoonClient.visitorCode}; Domain=$COOKIE_DOMAIN; Path=/; Secure"
                )
                flush()
            }
        }
    }
    ```
  </Tab>

  <Tab title="Kotlin (Jetpack Compose)">
    ```kotlin theme={null}
    @Composable
    fun KameleoonCookieWebView(url: String, kameleoonClient: KameleoonClient) {
        AndroidView(
            factory = { context ->
                WebView(context).apply {
                    configureWebView(url, kameleoonClient)
                    loadUrl(url)
                }
            },
        )
    }

    private fun WebView.configureWebView(url: String, kameleoonClient: KameleoonClient) {
        val COOKIE_NAME = "kameleoonVisitorCode"
        val COOKIE_DOMAIN = ".example.com"

        CookieManager.getInstance().apply {
            setCookie(
                url,
                "$COOKIE_NAME=${kameleoonClient.visitorCode}; Domain=$COOKIE_DOMAIN; Path=/; Secure"
            )
            flush()
        }
    }
    ```
  </Tab>

  <Tab title="Java">
    ```java theme={null}
    public class WebViewActivity extends AppCompatActivity {

        private WebView webView;

        private static final String DEFAULT_URL = "https://example.com";
        private static final String COOKIE_NAME = "kameleoonVisitorCode";
        private static final String COOKIE_DOMAIN = ".example.com";

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);

            webView = new WebView(this);
            setContentView(webView);
            configureWebView(webView, DEFAULT_URL, kameleoonClient);
            webView.loadUrl(url);
        }

        private void configureWebView(WebView webView, String url, KameleoonClient kameleoonClient) {
            CookieManager cookieManager = CookieManager.getInstance();
            cookieManager.setCookie(
                    url,
                    COOKIE_NAME + "=" + kameleoonClient.getVisitorCode() + "; Domain=" + COOKIE_DOMAIN + "; Path=/; Secure"
            );
            cookieManager.flush();
        }
    }
    ```
  </Tab>
</Tabs>

## Référence

Ceci est la documentation de référence complète du SDK Android de Kameleoon.

### Initialisation

Une fois que vous avez [installé le SDK](#installation) dans votre application, la première étape consiste à initialiser Kameleoon. Toutes les interactions de votre application avec le SDK, telles que le déclenchement d'une expérience, sont effectuées via cet objet client Kameleoon.

#### create()

Appelez cette méthode avant toute autre pour initialiser le SDK. Cette méthode se trouve dans `com.kameleoon.KameleoonClientFactory`. Votre application effectue toutes les interactions avec le SDK en utilisant l'objet `KameleoonClient` résultant que cette méthode crée.

Vous pouvez personnaliser le comportement du SDK (par exemple, l'environnement, les identifiants, etc.) en fournissant un [objet de configuration](#configuration-supplémentaire). Sinon, le SDK essaie de trouver et d'utiliser votre fichier de configuration à la place.

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    String siteCode = "a8st4f59bj";
    try {
        // pass client configuration and visitorCode as arguments
        KameleoonClientConfig config = new KameleoonClientConfig.Builder()
            .refreshIntervalMinute(15) // in minutes, 1 hour by default, optional
            .defaultTimeoutMillisecond(10_000) // in milliseconds, 10 seconds by default, optional
            .dataExpirationIntervalMinute(1440 * 365) // in minutes, infinity by default, optional
            .isUniqueIdentifier(false) // optional, false by default. Set to true if the visitorCode corresponds to your customer's unique userId.
            .environment("staging") // optional
            .build();
        String visitorCode = "yourVisitorCode";
        KameleoonClient kameleoonClient = KameleoonClientFactory.create(siteCode, visitorCode, config, getApplicationContext());
    } catch (KameleoonException.SiteCodeIsEmpty | KameleoonException.VisitorCodeInvalid exception) {
        // Exception indicates that the provided siteCode is empty or the visitorCode is invalid
    } catch (Exception exception) {
        // Recommended (but optional) safeguard for unexpected exceptions from third-party libraries
    }

    try {
        // generate visitorCode automatically and read client configuration from a file 'kameleoon-client.properties'
        KameleoonClient kameleoonClient = KameleoonClientFactory.create(siteCode, getApplicationContext());
    } catch (KameleoonException.SiteCodeIsEmpty | KameleoonException.VisitorCodeInvalid exception) {
        // Exception indicates that the provided siteCode is empty or the visitorCode is invalid
    } catch (Exception exception) {
        // Recommended (but optional) safeguard for unexpected exceptions from third-party libraries
    }
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    val siteCode = "a8st4f59bj"
    try {
        // pass client configuration and visitor code as arguments
        val config = KameleoonClientConfig.Builder()
            .refreshIntervalMinute(15) // in minutes, 1 hour by default, optional
            .defaultTimeoutMillisecond(10_000) // in milliseconds, 10 seconds by default, optional
            .dataExpirationIntervalMinute(1440 * 365) // in minutes, infinity by default, optional
            .environment("staging") // optional
            .build();
        val visitorCode = "yourVisitorCode"
        val kameleoonClient = KameleoonClientFactory.create(siteCode, visitorCode, config, applicationContext)
    } catch (e: KameleoonException.SiteCodeIsEmpty) {
        // Exception indicating that the provided siteCode is empty
    } catch (e: KameleoonException.VisitorCodeInvalid) {
        // Exception indicating that the provided visitorCode is invalid
    } catch (e: Exception) {
        // Recommended (but optional) safeguard for unexpected exceptions from third-party libraries
    }

    try {
        // generate visitorCode automatically and read client configuration from the 'kameleoon-client.properties' file
        val kameleoonClient = KameleoonClientFactory.create(siteCode, applicationContext)
    } catch (e: KameleoonException.SiteCodeIsEmpty) {
        // Exception indicating that the provided siteCode is empty
    } catch (e: KameleoonException.VisitorCodeInvalid) {
        // Exception indicating that the provided visitorCode is invalid
    } catch (e: Exception) {
        // Recommended (but optional) safeguard for unexpected exceptions from third-party libraries
    }
    ```
  </Tab>
</Tabs>

##### Arguments

| Nom                           | Type                    | Description                                                                                                                                                                                                                                                                                          | Par défaut |
| ----------------------------- | ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| siteCode (*requis*)           | `String`                | Une [clé unique](/user-manual/faq#how-do-i-find-my-sitecode) identifiant le projet Kameleoon utilisé avec le SDK.                                                                                                                                                                                    |            |
| visitorCode (*optionnel*)     | `String`                | Un identifiant de visiteur optionnel. Si disponible, utilisez votre **ID utilisateur** interne ; sinon, le SDK en générera un automatiquement.                                                                                                                                                       | `nil`      |
| config (*optionnel*)          | `KameleoonClientConfig` | Configuration optionnelle du SDK. Si fournie, elle est utilisée au lieu de lire à partir d'un [fichier de configuration](#configuration-supplémentaire) externe. Si elle n'est pas fournie, le SDK tente de lire le fichier, mais si le fichier est manquant, il revient au comportement par défaut. | `nil`      |
| applicationContext (*requis*) | `Context`               | Le [contexte](https://developer.android.com/reference/android/content/Context) de l'application.                                                                                                                                                                                                     |            |

##### Valeur de retour

| Type              | Description                                                                                                                          |
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| `KameleoonClient` | Une instance de la classe `KameleoonClient` que votre application peut ensuite utiliser pour gérer vos expériences et feature flags. |

##### Exceptions levées

| Type                 | Description                                                                                                            |
| -------------------- | ---------------------------------------------------------------------------------------------------------------------- |
| `VisitorCodeInvalid` | Exception indiquant que le code visiteur fourni n'est pas valide. Il est soit vide, soit plus long que 255 caractères. |
| `SiteCodeIsEmpty`    | Exception indiquant que le site code spécifié est une chaîne vide, ce qui est une valeur invalide.                     |

#### isReady()

Pour les SDKs mobiles, le client Kameleoon ne peut pas s'initialiser immédiatement, car il doit effectuer un appel serveur pour récupérer la configuration actuelle des feature flags actifs. Utilisez cette méthode pour vérifier si le SDK est prêt en appelant `isReady()` avant de déclencher des feature flags.

Alternativement, vous pouvez utiliser un callback (voir la méthode [`runWhenReady()`](#runwhenready) pour plus de détails).

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    boolean ready = kameleoonClient.isReady();
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    val ready = kameleoonClient.isReady
    ```
  </Tab>
</Tabs>

##### Valeur de retour

| Type    | Description                                                                                                                              |
| ------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| boolean | Booléen représentant l'état du SDK. `true` si le client est entièrement initialisé et `false` s'il n'est pas encore prêt à être utilisé. |

#### runWhenReady()

* 🔄 *Effectue une requête asynchrone (si la configuration est obsolète ou manquante)*

Pour les SDKs mobiles, le `KameleoonClient` ne peut pas s'initialiser immédiatement, car il doit effectuer un appel serveur pour récupérer la configuration actuelle de tous les feature flags. Utilisez la méthode [`runWhenReady()`](#runwhenready) pour gérer le temps jusqu'à ce que le client soit prêt à être utilisé. De plus, vous pouvez définir une période de timeout maximale pour contrôler combien de temps le client attendra avant d'être prêt.

Si `result.getOrThrow()=true`, le `KameleoonClient` est initialisé et prêt, et les feature flags seront déclenchés avec leurs variations respectives. Si le résultat est `false` ou si un timeout se produit, l'initialisation ne se terminera pas avec succès.

Le callback ou le code basé sur les coroutines doit inclure la logique pour appliquer la variation de référence, car l'utilisateur sera exclu du feature flag si un timeout se produit.

<Warning>
  Étant donné que la configuration initiale peut nécessiter un appel serveur, ce mécanisme est asynchrone. Par conséquent, vous devez soit :

  * Fournir un callback `completion` comme argument de la méthode pour vous assurer d'être notifié lorsque le `KameleoonClient` est entièrement initialisé et prêt à être utilisé.
  * Utiliser les coroutines pour gérer les opérations asynchrones.
</Warning>

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    kameleoonClient.runWhenReady(1000, result -> {
        int recommendedProductsNumber = 5; // Default control number for recommended products
        try {
            if (result.getOrThrow()) {
                Variation variation = kameleoonClient.getVariation("featureKey");
                recommendedProductsNumber = (int) variation.getVariables().get("recommendedProductsNumber").getValue();
            }
        } catch (Exception ignored) {
            // The user will not be included in the experiment results and should see the control variation
        }

        applyVariation(recommendedProductsNumber);
    });
    ```

    ##### Arguments

    | Nom                               | Type                                          | Description                                | Par défaut                                                                                               |
    | --------------------------------- | --------------------------------------------- | ------------------------------------------ | -------------------------------------------------------------------------------------------------------- |
    | timeoutMilliseconds (*optionnel*) | `int`                                         | Timeout pour le processus d'initialisation | [`defaultTimeoutMillisecond`](#create) ou [`default_timeout_millisecond`](#configuration-supplémentaire) |
    | completion (*requis*)             | `ResultCompletion<Boolean, TimeoutException>` | Le callback qui traite les données reçues. |                                                                                                          |
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    kameleoonClient.runWhenReady(1000) { result ->
        val recommendedProductsNumber = runCatching {
            if (result.getOrThrow()) {
                val variation = kameleoonClient.getVariation("featureKey")
                variation.variables["recommendedProductsNumber"]?.value as Int
            } else {
                null // The user will not be included in the experiment results and should see the control variation
            }
        }.getOrDefault(5)  // Default control number for recommended products

        applyVariation(recommendedProductsNumber)
    }
    ```

    ##### Arguments

    | Nom                               | Type                                          | Description                                | Par défaut                                                                                               |
    | --------------------------------- | --------------------------------------------- | ------------------------------------------ | -------------------------------------------------------------------------------------------------------- |
    | timeoutMilliseconds (*optionnel*) | `Int`                                         | Timeout pour le processus d'initialisation | [`defaultTimeoutMillisecond`](#create) ou [`default_timeout_millisecond`](#configuration-supplémentaire) |
    | completion (*requis*)             | `ResultCompletion<Boolean, TimeoutException>` | Le callback qui traite les données reçues. |                                                                                                          |
  </Tab>

  <Tab title="Kotlin (Coroutines)">
    <Warning>
      Une erreur courante est d'utiliser des fonctions suspendues à l'intérieur de `mapCatching`, `runCatching`, ou d'un bloc `try-catch` sans relancer correctement `CancellationException`, ce qui peut interférer avec l'annulation des coroutines. Pour garantir un comportement correct, essayez d'éviter d'appeler des fonctions suspend dans ces blocs.
    </Warning>

    ```kotlin theme={null}
    viewModelScope.launch {
        kameleoonClient.runWhenReady(1000).getOrNull() ?: return@launch
        val recommendedProductsNumber = runCatching {
            val variation = kameleoonClient.getVariation("featureKey")
            variation.variables["recommendedProductsNumber"]?.value as? Int
        }.getOrNull() ?: 5 // Default control number for recommended products

        applyVariation(recommendedProductsNumber)
    }
    ```

    ##### Arguments

    | Nom                               | Type  | Description                                | Par défaut                                                                                               |
    | --------------------------------- | ----- | ------------------------------------------ | -------------------------------------------------------------------------------------------------------- |
    | timeoutMilliseconds (*optionnel*) | `Int` | Timeout pour le processus d'initialisation | [`defaultTimeoutMillisecond`](#create) ou [`default_timeout_millisecond`](#configuration-supplémentaire) |

    ##### Valeur de retour

    | Type           | Description                                                                                      |
    | -------------- | ------------------------------------------------------------------------------------------------ |
    | `Result<Unit>` | Un `Result` Kotlin qui contient soit le résultat de succès, soit l'exception qui s'est produite. |
  </Tab>
</Tabs>

### Feature flags et variations

#### isFeatureActive()

* 📨 *Envoie des données de suivi à Kameleoon (selon le paramètre `track`)*

<Note>
  Cette méthode s'appelait auparavant `activateFeature`, qui a été supprimée dans la version `4.0.0` du SDK.
</Note>

Appelez cette méthode pour activer un feature toggle. Cette méthode accepte un `featureKey` comme argument requis pour vérifier si la fonctionnalité spécifiée sera active pour un visiteur.

Si le visiteur n'a jamais été associé à ce feature flag, la méthode renvoie une valeur booléenne aléatoire (`true` si la fonctionnalité doit être affichée à ce visiteur, sinon `false`). Si le visiteur est déjà enregistré avec ce feature flag, cette méthode renvoie la valeur précédente de `featureFlag`.

Assurez-vous de configurer correctement la gestion des erreurs comme montré dans l'exemple de code pour attraper les exceptions potentielles.

<Note>
  Kameleoon utilise le suivi pour compter les sessions et les visiteurs lorsque vous appelez certaines méthodes, telles que `isFeatureActive()`, `getVariation()` ou `getVariations()`.

  Utilisez la valeur par défaut `true` pour le paramètre `track` lorsque vous exposez les visiteurs à une variation et que vous devez les compter. Définissez le paramètre `track` à `false` uniquement si vous appelez ces méthodes avant d'exposer les visiteurs.

  Par exemple, si vous appelez `getVariations()` pour récupérer toutes les variations avant d'exposer les visiteurs, définissez le paramètre `track` à `false`. Ce paramètre empêche Kameleoon de compter prématurément une session. Vous pouvez ensuite déclencher le suivi plus tard lorsque vous exposez explicitement le visiteur.

  Kameleoon envoie des données de suivi toutes les secondes par défaut. Vous pouvez configurer cet intervalle jusqu'à cinq secondes en utilisant l'option de configuration de l'intervalle de suivi. Kameleoon regroupe les événements de suivi dans une seule session tant que l'intervalle entre les événements est inférieur à 30 minutes. Si plus de 30 minutes s'écoulent entre les événements de suivi, Kameleoon compte les événements comme des sessions séparées. Une visite apparaît dans vos rapports 30 minutes après le dernier événement enregistré dans la session.
</Note>

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    String featureKey = "new_checkout";

    boolean hasNewCheckout = false;
    try {
        hasNewCheckout = kameleoonClient.isFeatureActive(featureKey);
        // disabling tracking
        hasNewCheckout = kameleoonClient.isFeatureActive(featureKey, false);
    } catch (KameleoonException.SDKNotReady e) {
        // Exception indicating that the SDK has not completed its initialization yet.
    } catch (KameleoonException.FeatureNotFound e) {
        // SDK not initialized, or feature toggle not yet activated in Kameleoon - we consider the feature inactive
    } catch (Exception exception) {
        // Recommended (but optional) safeguard for unexpected exceptions from third-party libraries
    }
    if (hasNewCheckout)
    {
        // Implement new checkout code here
    }
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    val featureKey = "new_checkout"
    var hasNewCheckout = false

    try {
        hasNewCheckout = kameleoonClient.isFeatureActive(featureKey)
        // disabling tracking
        hasNewCheckout = kameleoonClient.isFeatureActive(featureKey, false)
    } catch (e: KameleoonException.SDKNotReady) {
        // Exception indicating that the SDK has not completed its initialization yet.
        hasNewCheckout = false
    } catch (e: KameleoonException.FeatureNotFound) {
        // SDK not initialized or feature toggle not yet activated on Kameleoon's side - we consider the feature inactive
        hasNewCheckout = false
    } catch (e: Exception) {
        // Recommended (but optional) safeguard for unexpected exceptions from third-party libraries
        hasNewCheckout = false
    }
    if (hasNewCheckout) {
        // Implement new checkout code here
    }
    ```
  </Tab>
</Tabs>

<Warning>
  La méthode `isFeatureActive()` évalue la variante servie, et non l'état du master flag. Si vous excluez des règles, la méthode utilise l'état par défaut **Then, for everyone else serve**. Si vous sélectionnez **Off** pour cet état par défaut, la méthode renvoie toujours `false` même lorsque le master feature flag est **On**.
</Warning>

##### Arguments

| Nom        | Type    | Description                                                                                                          |
| ---------- | ------- | -------------------------------------------------------------------------------------------------------------------- |
| featureKey | String  | Clé unique de la fonctionnalité que vous souhaitez exposer à un utilisateur. Ce champ est requis.                    |
| track      | boolean | Un paramètre optionnel pour activer ou désactiver le suivi de l'évaluation de la fonctionnalité (`true` par défaut). |

##### Valeur de retour

| Type    | Description                                                       |
| ------- | ----------------------------------------------------------------- |
| Boolean | Valeur de la fonctionnalité qui est enregistrée pour un visiteur. |

##### Exceptions levées

| Type            | Description                                                                                                                                                                                                                                                                                    |
| --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| SDKNotReady     | Exception indiquant que le SDK n'a pas terminé son initialisation.                                                                                                                                                                                                                             |
| FeatureNotFound | Exception indiquant que l'ID de fonctionnalité demandé n'a pas été trouvé dans la configuration interne du SDK. Cette exception signifie généralement que le feature flag n'a pas été activé côté Kameleoon (mais le code implémentant la fonctionnalité est déjà déployé dans l'application). |

#### getVariation()

* 📨 *Envoie des données de suivi à Kameleoon (selon le paramètre `track`)*

Récupère la [`Variation`](#variation) attribuée à un visiteur donné pour un feature flag spécifique.

Cette méthode prend un `visitorCode` et un `featureKey` comme arguments obligatoires. L'argument `track` est optionnel et vaut `true` par défaut.

Elle renvoie la `Variation` attribuée au visiteur. Si le visiteur n'est associé à aucune règle de feature flag, la méthode renvoie la `Variation` par défaut pour le feature flag donné.

Assurez-vous qu'une gestion appropriée des erreurs est implémentée dans votre code pour gérer les exceptions potentielles.

<Note>
  La variation par défaut fait référence à la variation attribuée à un visiteur lorsqu'il ne correspond à aucune règle de livraison prédéfinie pour un feature flag. En d'autres termes, c'est la variation de secours appliquée à tous les utilisateurs qui ne sont pas ciblés par des règles spécifiques. Elle est représentée comme la variation dans la section "Then, for everyone else..." d'une interface de gestion.
</Note>

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    final String featureKey = "featureKey";
    Variation variation = null;

    try {
        variation = kameleoonClient.getVariation(featureKey);
        // disabling tracking
        variation = kameleoonClient.getVariation(featureKey, false);
    } catch (KameleoonException.SDKNotReady ex) {
        // Exception indicating that the SDK has not completed its initialization yet.
    } catch (KameleoonException.FeatureNotFound ex) {
        // The feature key is not in the configuration file that has been fetched by the SDK.
    } catch (KameleoonException.FeatureEnvironmentDisabled ex) {
        // The feature flag is disabled for the environment.
    }

    if (variation != null) {
        String title = (String) variation.getVariables().get("title").getValue();

        switch (variation.getKey()) {
            case "on":
                // Main variation key is selected for visitorCode
                break;
            case "alternative_variation":
                // Alternative variation key
                break;
            default:
                // Default variation key
                break;
        }
    }
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    val featureKey = "featureKey"
    var variation: Variation? = null

    try {
        variation = kameleoonClient.getVariation(featureKey)
        // disabling tracking
        variation = kameleoonClient.getVariation(featureKey, false)
    } catch (e: KameleoonException.SDKNotReady) {
        // Exception indicating that the SDK has not completed its initialization yet.
    } catch (e: KameleoonException.FeatureNotFound) {
        // The feature key is not yet in the configuration file that has been fetched by the SDK.
    } catch (e: KameleoonException.FeatureEnvironmentDisabled) {
        // The feature flag is disabled for the environment
    }

    val title = variation?.variables?.get("title")?.value as? String

    when (variation?.key) {
        "on" -> {
            // Main variation key is selected for visitorCode
        }
        "alternative_variation" -> {
            // Alternative variation key
        }
        else -> {
            // Default variation key
        }
    }
    ```
  </Tab>
</Tabs>

##### Arguments

| Nom                    | Type      | Description                                                                                      | Par défaut |
| ---------------------- | --------- | ------------------------------------------------------------------------------------------------ | ---------- |
| visitorCode (*requis*) | `String`  | Identifiant unique du visiteur.                                                                  |            |
| featureKey (*requis*)  | `String`  | Clé de la fonctionnalité que vous souhaitez exposer à un visiteur.                               |            |
| track (*optionnel*)    | `boolean` | Un paramètre optionnel pour activer ou désactiver le suivi de l'évaluation de la fonctionnalité. | `true`     |

##### Valeur de retour

| Type        | Description                                                                                  |
| ----------- | -------------------------------------------------------------------------------------------- |
| `Variation` | Une [`Variation`](#variation) attribuée à un visiteur donné pour un feature flag spécifique. |

##### Exceptions levées

| Type                         | Description                                                                                                                                                                                                                                                                                         |
| ---------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `VisitorCodeInvalid`         | Exception indiquant que le code visiteur fourni n'est pas valide. Il est soit vide, soit plus long que 255 caractères.                                                                                                                                                                              |
| `FeatureNotFound`            | Exception indiquant que la clé de fonctionnalité demandée n'a pas été trouvée dans la configuration interne du SDK. Cela signifie généralement que le feature flag n'est pas activé dans l'application Kameleoon (mais le code implémentant la fonctionnalité est déjà déployé dans l'application). |
| `FeatureEnvironmentDisabled` | Exception indiquant que le feature flag est désactivé pour l'environnement actuel du visiteur (par exemple, production, staging ou development).                                                                                                                                                    |

#### getVariations()

* 📨 *Envoie des données de suivi à Kameleoon (selon le paramètre `track`)*

Récupère une map d'objets [`Variation`](#variation) attribués à un visiteur donné pour tous les feature flags.

Cette méthode itère sur tous les feature flags disponibles et renvoie la `Variation` attribuée pour chaque flag associé au visiteur spécifié. Elle prend `onlyActive` et `track` comme arguments optionnels.

* Si `onlyActive` est défini à `true`, la méthode `getVariations()` renverra les variations des feature flags à condition que l'utilisateur ne soit pas affecté à la variation `off`.
* Le paramètre `track` contrôle si la méthode suivra ou non les attributions de variations. Par défaut, il est défini à `true`. S'il est défini à `false`, le suivi sera désactivé.

La map renvoyée se compose de clés de feature flag comme clés et de leurs `Variation` correspondantes comme valeurs. Si aucune variation n'est attribuée pour un feature flag, la méthode renvoie la `Variation` par défaut pour ce flag.

Une gestion appropriée des erreurs doit être implémentée pour gérer les exceptions potentielles.

<Note>
  La variation par défaut fait référence à la variation attribuée à un visiteur lorsqu'il ne correspond à aucune règle de livraison prédéfinie pour un feature flag. En d'autres termes, c'est la variation de secours appliquée à tous les utilisateurs qui ne sont pas ciblés par des règles spécifiques. Elle est représentée comme la variation dans la section "Then, for everyone else..." d'une interface de gestion.
</Note>

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    try {
        Map<String, Variation> variations = kameleoonClient.getVariations();
        // only active variations
        Map<String, Variation> variations = kameleoonClient.getVariations(true);
        // disable tracking
        Map<String, Variation> variations = kameleoonClient.getVariations(false, false);
    } catch (KameleoonException.SDKNotReady ex) {
        // Exception indicating that the SDK has not completed its initialization yet.
    }
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    try {
        val variations = kameleoonClient.getVariations()
        // only active variations
        val variations = kameleoonClient.getVariations(true)
        // disable tracking
        val variations = kameleoonClient.getVariations(false, false)
    } catch (e: KameleoonException.SDKNotReady) {
        // Exception indicating that the SDK has not completed its initialization yet.
    }
    ```
  </Tab>
</Tabs>

##### Arguments

| Nom                      | Type      | Description                                                                                                                  | Par défaut |
| ------------------------ | --------- | ---------------------------------------------------------------------------------------------------------------------------- | ---------- |
| onlyActive (*optionnel*) | `boolean` | Un paramètre optionnel indiquant s'il faut renvoyer les variations pour les feature flags actifs (`true`) ou tous (`false`). | `false`    |
| track (*optionnel*)      | `boolean` | Un paramètre optionnel pour activer ou désactiver le suivi de l'évaluation de la fonctionnalité.                             | `true`     |

##### Valeur de retour

| Type                     | Description                                                                                                                                  |
| ------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------- |
| `Map<String, Variation>` | Map qui contient les objets [`Variation`](#variation) attribués des feature flags en utilisant les clés des fonctionnalités correspondantes. |

##### Exceptions levées

| Type          | Description                                                 |
| ------------- | ----------------------------------------------------------- |
| `SDKNotReady` | Indique que le SDK n'est pas encore entièrement initialisé. |

#### setForcedVariation()

La méthode vous permet d'attribuer programmatiquement une [`Variation`](#variation) spécifique à un utilisateur, contournant le processus d'évaluation standard. Ceci est particulièrement précieux pour les expériences contrôlées dans lesquelles la logique d'évaluation habituelle n'est pas nécessaire ou doit être ignorée. Cela peut également être utile dans des scénarios tels que le débogage ou les tests personnalisés.

Lorsqu'une variation **forcée** est définie, elle remplace la logique d'évaluation en temps réel de Kameleoon. Les processus tels que la segmentation, les conditions de ciblage et les calculs algorithmiques sont ignorés. Pour préserver la segmentation et les conditions de ciblage pendant une expérience, définissez `forceTargeting=false` à la place.

Une variation forcée est traitée de la même manière qu'une variation évaluée. Elle est suivie dans les analytics et stockée dans le contexte utilisateur comme toute variation évaluée standard, garantissant la cohérence du reporting.

La méthode peut lever des exceptions sous certaines conditions (par ex. paramètres invalides, contexte utilisateur ou problèmes internes). Une gestion appropriée des exceptions est essentielle pour garantir que votre application reste stable et résiliente.

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    final int experimentId = 9516;
    try {
        // Forcing the variation "on" for the experiment 9516 for the visitor
        kameleoonClient.setForcedVariation(experimentId, "on");

        // Forcing the variation "on" while preserving segmentation and targeting conditions during the experiment
        kameleoonClient.setForcedVariation(experimentId, "on", false);

        // Resetting the forced variation for the experiment 9516 for the visitor
        kameleoonClient.setForcedVariation(experimentId, null);
    } catch (KameleoonException e) {
        // Handling the exception
    }
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    val experimentId = 9516
    try {
        // Forcing the variation "on" for the experiment 9516 for the visitor
        kameleoonClient.setForcedVariation(experimentId, "on")

        // Forcing the variation "on" while preserving segmentation and targeting conditions during the experiment
        kameleoonClient.setForcedVariation(experimentId, "on", false)

        // Resetting the forced variation for the experiment 9516 for the visitor
        kameleoonClient.setForcedVariation(experimentId, null)
    } catch (e: KameleoonException) {
        // Handling the exception
    }
    ```
  </Tab>
</Tabs>

##### Arguments

| Nom                          | Type      | Description                                                                                                                                                                         | Par défaut |
| ---------------------------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| experimentId (*requis*)      | `int`     | **Experiment Id** qui sera ciblé et sélectionné pendant le processus d'évaluation.                                                                                                  |            |
| variationKey (*requis*)      | `String`  | **Variation Key** correspondant à une `Variation` qui devrait être forcée comme valeur renvoyée pour l'expérience. Si la valeur est `null`, la variation forcée sera réinitialisée. |            |
| forceTargeting (*optionnel*) | `boolean` | Indique si le ciblage pour l'expérience doit être forcé et ignoré (`true`) ou appliqué comme dans le processus d'évaluation standard (`false`).                                     | `true`     |

##### Exceptions levées

| Type                        | Description                                                                                                                                                                                                                                        |
| --------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `SDKNotReady`               | Indique que le SDK n'est pas encore entièrement initialisé.                                                                                                                                                                                        |
| `FeatureExperimentNotFound` | Exception indiquant que l'experiment id demandé n'a pas été trouvé dans la configuration interne du SDK. Ceci est généralement normal et signifie que l'expérience correspondante à la règle n'a pas encore été activée côté Kameleoon.            |
| `FeatureVariationNotFound`  | Exception indiquant que la variation key(id) demandée n'a pas été trouvée dans la configuration interne du SDK. Ceci est généralement normal et signifie que l'expérience correspondante à la variation n'a pas encore été activée côté Kameleoon. |

<Info>
  Dans la plupart des cas, seule l'erreur de base, `KameleoonException`, doit être gérée, comme démontré dans l'exemple. Cependant, si différents types d'erreurs nécessitent une réponse, gérez chacun séparément en fonction des exigences spécifiques. De plus, pour une fiabilité accrue, les erreurs générales de langage peuvent être gérées en incluant `Exception`.
</Info>

#### evaluateAudiences()

* 📨 *Envoie des données de suivi à Kameleoon*

Cette méthode évalue les visiteurs par rapport à tous les segments disponibles dans Audiences Explorer et suit ceux qui correspondent.

`evaluateAudiences()` doit être appelée **après que toutes les données pertinentes du visiteur ont été définies ou mises à jour**, et **juste avant** d'obtenir une variation de fonctionnalité ou de vérifier un feature flag. Cette approche garantit que le visiteur est évalué par rapport aux données les plus récentes disponibles, permettant une attribution précise des audiences en fonction de tous les critères.

Après avoir appelé cette méthode, vous pouvez effectuer une analyse détaillée des performances des segments dans Audiences Explorer.

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    try {
        kameleoonClient.evaluateAudiences();
    } catch (KameleoonException e) {
        // Handling the exception
    }
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    try {
        kameleoonClient.evaluateAudiences()
    } catch (e: KameleoonException) {
        // Handling the exception
    }
    ```
  </Tab>
</Tabs>

##### Exceptions levées

| Type          | Description                                                 |
| ------------- | ----------------------------------------------------------- |
| `SDKNotReady` | Indique que le SDK n'est pas encore entièrement initialisé. |

<Info>
  Dans la plupart des cas, seule l'erreur de base, `KameleoonException`, doit être gérée, comme démontré dans l'exemple. Cependant, si différents types d'erreurs nécessitent une réponse, gérez chacun séparément en fonction des exigences spécifiques. De plus, pour une fiabilité accrue, les erreurs générales de langage peuvent être gérées en incluant `Exception`.
</Info>

#### getDataFile()

<Tip>
  Pour évaluer tous les feature flags, utilisez [`getVariations()`](#getvariations). Cette méthode est plus efficace que d'appeler `DataFile` et d'itérer à travers les flags avec [`getVariation()`](#getvariation).
</Tip>

Renvoie la configuration actuelle du SDK sous forme d'objet [`DataFile`](#datafile).

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    try {
        DataFile dataFile = kameleoonClient.getDataFile();
    } catch (KameleoonException.SDKNotReady e) {
        // Exception indicates that the SDK has not completed its initialization yet.
    } catch (Exception e) {
        // Recommended (but optional) safeguard for unexpected exceptions from third-party libraries
    }
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    try {
        val dataFile = kameleoonClient.dataFile
        val dateModified = dataFile.dateModified
    } catch (e: KameleoonException.SDKNotReady) {
        // Exception indicates that the SDK has not completed its initialization yet.
    } catch (e: Exception) {
        // Recommended (but optional) safeguard for unexpected exceptions from third-party libraries
    }
    ```
  </Tab>
</Tabs>

##### Valeur de retour

| Type       | Description                                                  |
| ---------- | ------------------------------------------------------------ |
| `DataFile` | Le [`DataFile`](#datafile) contenant la configuration du SDK |

##### Erreurs levées

| Type          | Description                                                 |
| ------------- | ----------------------------------------------------------- |
| `SDKNotReady` | Indique que le SDK n'est pas encore entièrement initialisé. |

### Objectifs

#### trackConversion()

* 📨 *Envoie des données de suivi à Kameleoon*

Utilisez cette méthode pour suivre les conversions. Cette méthode nécessite `goalId` pour suivre la conversion sur cet [objectif](/user-manual//assets/goals/create-a-goal) particulier. De plus, cette méthode accepte également les arguments `revenue`, `metadata` et `negative`.

La méthode `trackConversion()` ne renvoie aucune valeur. Cette méthode est non bloquante car l'appel au serveur est effectué de manière asynchrone.

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    final int goalId = 83023;
    kameleoonClient.trackConversion(goalId); // default revenue

    kameleoonClient.trackConversion(goalId, 10); // provided revenue == 10

    kameleoonClient.trackConversion(goalId, new CustomData(1, "metadata")); // Add metadata
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    val goalId = 83023
    kameleoonClient.trackConversion(goalId) // default revenue

    kameleoonClient.trackConversion(goalId, 10f) // provided revenue == 10

    kameleoonClient.trackConversion(goalId, CustomData(1, "metadata")) // Add metadata
    ```
  </Tab>
</Tabs>

##### Arguments

| Nom                    | Type            | Description                                                                                                                                         | Par défaut          |
| ---------------------- | --------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------- |
| goalId (*requis*)      | `int`           | ID de l'objectif.                                                                                                                                   |                     |
| revenue (*optionnel*)  | `float`         | Revenu de la conversion.                                                                                                                            | `0`                 |
| negative (*optionnel*) | `boolean`       | Définit si le revenu est positif ou négatif.                                                                                                        | `false`             |
| metadata (*optionnel*) | `CustomData...` | Métadonnées de la conversion. [Doit être défini au préalable dans l'application Kameleoon](/fr/user-manual/assets/goals/create-a-goal#métadonnées). | `new CustomData[0]` |

<Note>
  Les valeurs de metadata sont accessibles via les [exports de données brutes](/user-manual/experiment-analytics/analyze-results/results-page/results-page-actions#Export) et [la page des résultats](/user-manual/experiment-analytics/analyze-results/data-and-metrics/goal-metadata).

  Si le paramètre `metadata` est fourni, Kameleoon utilisera ces valeurs spécifiées pour la conversion actuelle au lieu de ce qui a été précédemment collecté à l'aide de la méthode [`addData()`](#adddata). Si le paramètre est omis, Kameleoon utilisera les dernières valeurs suivies pour ces [`CustomData`](#customdata) avant la conversion et au cours de la même visite.

  Kameleoon ne prendra en compte que les valeurs de métadonnées qui sont explicitement passées en tant que paramètres à la méthode `trackConversion()`.

  Dans l'exemple ci-dessous, Kameleoon n'associera la conversion qu'à la valeur de donnée personnalisée explicitement fournie en tant que paramètre (ici : index 5 avec la valeur 'Amex Credit Card').

  <Tabs defaultTabIndex={1}>
    <Tab title="Java">
      ```java theme={null}
      kameleoonClient.addData(new CustomData(5, "Credit Card"), new CustomData(9, "Express Delivery"));
      kameleoonClient.trackConversion(1000, new CustomData(5, "Amex Credit Card"));
      ```
    </Tab>

    <Tab title="Kotlin">
      ```kotlin theme={null}
      kameleoonClient.addData(CustomData(5, "Credit Card"), CustomData(9, "Express Delivery"))
      kameleoonClient.trackConversion(1000, CustomData(5, "Amex Credit Card"))
      ```
    </Tab>
  </Tabs>
</Note>

### Événements

#### onUpdateConfiguration()

<Note>
  Cette méthode s'appelait auparavant `updateConfigurationHandler`, qui a été supprimée dans la version `4.0.0` du SDK.
</Note>

La méthode `onUpdateConfiguration()` vous permet de gérer l'événement lorsque la configuration a mis à jour des données. Elle prend un paramètre d'entrée, **completion**. Le completion qui sera appelé lorsque la configuration est mise à jour à l'aide d'un événement de configuration en temps réel.

<Note>
  Ce handler n'est déclenché que lorsque le SDK fonctionne en [mode streaming](/developer-docs/feature-experimentation/technical-reference/technical-considerations#streaming-option-premium) (server-sent events). Il **n'est pas** appelé pour les actualisations de configuration effectuées en mode polling par défaut (`refreshIntervalMinute`).
</Note>

##### Arguments

| Nom        | Type                                | Description                                                                                                                 |
| ---------- | ----------------------------------- | --------------------------------------------------------------------------------------------------------------------------- |
| completion | `ResultCompletion<Long, Exception>` | Le handler qui sera appelé lorsque la configuration est mise à jour à l'aide d'un événement de configuration en temps réel. |

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    kameleoonClient.onUpdateConfiguration(result -> {
        if (result.isSuccess()) {
            // result value contains the value of Unix time (number of seconds that have elapsed since January 1, 1970) when configuration was updated
        }
    });
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    kameleoonClient.onUpdateConfiguration { result ->
        if (result.isSuccess) {
            // result value contains the value of Unix time (number of seconds that have elapsed since January 1, 1970) when configuration was updated
        }
    }
    ```
  </Tab>
</Tabs>

### Données visiteur

#### getVisitorCode()

Renvoie le code visiteur unique utilisé dans le SDK.

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    String visitorCode = kameleoonClient.getVisitorCode();
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    val visitorCode = kameleoonClient.visitorCode
    ```
  </Tab>
</Tabs>

##### Valeur de retour

| Type     | Description                                                      |
| -------- | ---------------------------------------------------------------- |
| `String` | String représentant un code visiteur unique utilisé dans le SDK. |

#### addData()

La méthode `addData()` ajoute des [données de ciblage](#types-de-données) au stockage afin que d'autres méthodes puissent utiliser les données pour décider si elles doivent cibler ou non le visiteur actuel.

La méthode `addData()` ne renvoie aucune valeur et n'interagit pas seule avec les serveurs back-end de Kameleoon. Au lieu de cela, toutes les données déclarées sont enregistrées pour une transmission future à l'aide de la méthode [`flush()`](#flush). Cette approche réduit le nombre d'appels au serveur effectués, car les données sont généralement regroupées en un seul appel serveur déclenché par `flush()`.

La méthode [`trackConversion()`](#trackconversion) envoie également toutes les données précédemment associées, tout comme `flush()`. Il en va de même pour les méthodes [`getVariation()`](#getvariation) et [`getVariations()`](#getvariations) si une règle d'expérimentation est déclenchée.

<Tip>
  Chaque visiteur ne peut avoir qu'une seule instance de données associées pour la plupart des types de données. Cependant, [`CustomData`](#customdata) est une exception. Les visiteurs peuvent avoir une instance de `CustomData` associée par index.
</Tip>

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    // Add a single data item (tracked by default)
    kameleoonClient.addData(new CustomData(1, "value"));

    // Add multiple data items (tracked by default)
    kameleoonClient.addData(new CustomData(1, "value"), new Geolocation("France"));

    // Add multiple data items stored locally for targeting only (not sent to the Kameleoon Data API)
    kameleoonClient.addData(false, new CustomData(1, "value"), new Geolocation("France"));
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    // Add a single data item (tracked by default)
    kameleoonClient.addData(CustomData(1, "value"))

    // Add multiple data items (tracked by default)
    kameleoonClient.addData(CustomData(1, "value"), Geolocation("France"))

    // Add multiple data items stored locally for targeting only (not sent to the Kameleoon Data API)
    kameleoonClient.addData(false, CustomData(1, "value"), Geolocation("France"))
    ```
  </Tab>
</Tabs>

##### Arguments

| Nom                 | Type      | Description                                                                                                                                                                                                                                    | Valeur par défaut |
| ------------------- | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------- |
| track (*optionnel*) | `boolean` | Spécifie si les données ajoutées sont éligibles au suivi. Lorsqu'il est défini à `false`, les données sont stockées localement et utilisées uniquement pour l'évaluation du ciblage ; elles ne sont pas envoyées à l'API de données Kameleoon. | `true`            |
| data (*requis*)     | `Data...` | Collection de types de données Kameleoon.                                                                                                                                                                                                      |                   |

#### flush()

* 📨 *Envoie des données de suivi à Kameleoon*

`flush()` prend les données Kameleoon associées à un visiteur, et envoie une requête de suivi avec toutes les données qui ont été ajoutées précédemment à l'aide de la méthode `addData()` et qui n'ont pas encore été envoyées lors de l'appel à l'une de [ces méthodes](/developer-docs/feature-experimentation/technical-reference/faq-global#when-does-the-sdk-send-a-tracking-request-for-analytics). `flush()` est non bloquant, car l'appel au serveur est effectué de manière asynchrone.

`flush()` fournit un contrôle sur le moment où les données associées à un visiteur sont envoyées aux serveurs. Par exemple, si `addData()` est appelé une douzaine de fois, envoyer des données au serveur après chaque invocation de `addData()` serait inefficace. Appelez `flush()` une fois à la fin.

La méthode `flush()` utilise `visitorCode` comme identifiant unique du visiteur, ce qui est utile pour l'[expérimentation cross-device](/developer-docs/cross-device-experimentation). Si vous définissez le paramètre de configuration `isUniqueIdentifier` à `true`, le SDK lie les données vidées au visiteur associé à l'identifiant spécifié.

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    kameleoonClient.addData(Device.phone());
    kameleoonClient.addData(new Conversion(32, 10f, false));

    kameleoonClient.flush(); // Interval tracking (most performant tracking method)

    kameleoonClient.flush(true); // Instant tracking
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    kameleoonClient.addData(Device.phone())
    kameleoonClient.addData(Conversion(32, 10f, false))

    kameleoonClient.flush() // Interval tracking (most performant tracking method)

    kameleoonClient.flush(true) // Instant tracking
    ```
  </Tab>
</Tabs>

##### Arguments

| Nom     | Type    | Description                                                                                                                                                                                            |
| ------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| instant | boolean | Indicateur booléen indiquant si les données doivent être envoyées instantanément (`true`) ou selon l'intervalle de suivi planifié (`false`). Ce champ est optionnel. La valeur par défaut est `false`. |

#### getRemoteData()

* 🔄 *Effectue une requête asynchrone*

<Note>
  Cette méthode s'appelait auparavant `retrieveDataFromRemoteSource`, qui a été supprimée dans la version `4.0.0` du SDK.
</Note>

Utilisez cette méthode pour récupérer des données depuis un serveur Kameleoon distant en fonction du `siteCode` actif et de l'argument `key` (ou du `visitorCode` actif si `key` est omis). Le `visitorCode` et le `siteCode` sont spécifiés dans `KameleoonClientFactory.create()`. Les données peuvent être stockées rapidement et facilement sur des serveurs distants hautement évolutifs à l'aide de l'API de données Kameleoon. L'application peut alors récupérer les données à l'aide de cette méthode.

<Warning>
  Étant donné qu'un appel serveur est requis, ce mécanisme est asynchrone. Par conséquent, vous devez soit :

  * Fournir un callback `completion` comme argument de la méthode pour vous assurer d'être notifié lorsque les données ont été récupérées avec succès.
  * Utiliser les coroutines pour une gestion asynchrone.
</Warning>

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    kameleoonClient.getRemoteData("key", result -> {
        try {
            JSONObject jsonObject = result.getOrThrow();
            // jsonObject contains result of request
        } catch (Exception ex) {
            // request failed with an exception
        }
    });
    ```

    ##### Arguments

    | Nom                   | Type                                      | Description                                                      | Par défaut |
    | --------------------- | ----------------------------------------- | ---------------------------------------------------------------- | ---------- |
    | key (*optionnel*)     | `String`                                  | La clé à laquelle les données que vous récupérez sont associées. | `null`     |
    | completion (*requis*) | `ResultCompletion<JSONObject, Exception>` | Le callback qui traite les données reçues.                       |            |
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    kameleoonClient.getRemoteData("key") { result ->
        try {
            val jsonObject: JSONObject = result.getOrThrow()
            // jsonObject contains result of request
        } catch (ex: Exception) {
            // request failed with an exception
        }
    }
    ```

    ##### Arguments

    | Nom                   | Type                                      | Description                                                      | Par défaut |
    | --------------------- | ----------------------------------------- | ---------------------------------------------------------------- | ---------- |
    | key (*optionnel*)     | `String`                                  | La clé à laquelle les données que vous récupérez sont associées. | `null`     |
    | completion (*requis*) | `ResultCompletion<JSONObject, Exception>` | Le callback qui traite les données reçues.                       |            |
  </Tab>

  <Tab title="Kotlin (Coroutines)">
    <Warning>
      Une erreur courante est d'utiliser des fonctions suspendues à l'intérieur de `mapCatching`, `runCatching`, ou d'un bloc `try-catch` sans relancer correctement `CancellationException`, ce qui peut interférer avec l'annulation des coroutines. Pour garantir un comportement correct, essayez d'éviter d'appeler des fonctions suspend dans ces blocs.
    </Warning>

    ```kotlin theme={null}
    viewModelScope.launch {
        val jsonObject = kameleoonClient.getRemoteData("key").getOrNull() ?: return@launch
    }
    ```

    ##### Arguments

    | Nom               | Type     | Description                                                      | Par défaut |
    | ----------------- | -------- | ---------------------------------------------------------------- | ---------- |
    | key (*optionnel*) | `String` | La clé à laquelle les données que vous récupérez sont associées. | `null`     |

    ##### Valeur de retour

    | Type                 | Description                                                                                                   |
    | -------------------- | ------------------------------------------------------------------------------------------------------------- |
    | `Result<JSONObject>` | Un `Result` Kotlin qui contient soit la valeur récupérée (`JSONObject`), soit l'exception qui s'est produite. |
  </Tab>
</Tabs>

#### getRemoteVisitorData()

* 🔄 *Effectue une requête asynchrone*

`getRemoteVisitorData()` est une méthode asynchrone pour récupérer les données de visites Kameleoon pour le visiteur depuis l'API de données Kameleoon. La méthode ajoute des données au stockage pour que d'autres méthodes les utilisent lors de la prise de décisions de ciblage.

Les données obtenues à l'aide de cette méthode jouent un rôle important lorsque vous souhaitez :

* utiliser des données collectées depuis d'autres appareils.
* accéder à l'historique d'un utilisateur, comme les données personnalisées collectées lors de visites précédentes.

Lisez [cet article](/developer-docs/feature-experimentation/targeting-and-segmentation/native-segmentation) pour une meilleure compréhension des cas d'utilisation possibles.

<Info>
  Par défaut, `getRemoteVisitorData()` récupère automatiquement les dernières données personnalisées stockées avec `scope=Visitor` et les attache au visiteur sans avoir à appeler la méthode `addData()`. C'est particulièrement utile pour [synchroniser les données personnalisées entre plusieurs appareils](/developer-docs/sdks/web-sdks/nodejs-sdk#synchronizing-custom-data-across-devices).

  Il est recommandé de vérifier uniquement les résultats ayant échoué. Cependant, si nécessaire, on peut vérifier que les données ont été ajoutées au visiteur et sont disponibles à des fins de ciblage (ou pour le débogage, bien que l'utilisation du [logging](#logging) soit meilleure pour le débogage). De plus, les données peuvent être gérées manuellement si le paramètre `shouldAddData=false` est passé.
</Info>

<Warning>
  Étant donné qu'un appel serveur est requis, ce mécanisme est asynchrone. Par conséquent, vous devez soit :

  * Fournir un callback `completion` comme argument de la méthode pour vous assurer d'être notifié lorsque les données ont été récupérées et ajoutées avec succès au visiteur.
  * Utiliser les coroutines pour une gestion asynchrone.
</Warning>

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    // Visitor data will be fetched and automatically added for `visitorCode`.
    kameleoonClient.getRemoteVisitorData(result -> {
        if (result.isSuccess()) {
            // Data was successfully retrieved from the Kameleoon servers and added to the visitor.
        } else {
            // The request failed due to an exception.
        }
    });

    // If you only want to fetch data and add it yourself manually, set shouldAddData == `false`.
    kameleoonClient.getRemoteVisitorData(false, result -> {
        try {
            List<Data> visitorData = result.getOrThrow();
            // visitorData contains the fetched visitor data from Kameleoon servers, which can be manually added.
        } catch (Exception ex) {
            // The request failed due to an exception.
        }
    });

    // If you want to fetch custom list of data types
    RemoteVisitorDataFilter filter = RemoteVisitorDataFilter.builder()
            .previousVisitAmount(25)
            .experiments(true)
            .conversion(true)
            .build();
    kameleoonClient.getRemoteVisitorData(filter, result -> {
        if (result.isSuccess()) {
            // Data was successfully retrieved from the Kameleoon servers and added to the visitor.
        } else {
            // The request failed due to an exception.
        }
    });
    ```

    ##### Arguments

    | Nom                         | Type                                      | Description                                                                                                                                                                                         | Par défaut |
    | --------------------------- | ----------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
    | filter (*optionnel*)        | `RemoteVisitorDataFilter`                 | Filtre qui sélectionne quelles données doivent être récupérées de l'historique des visites. Par défaut, la méthode récupère `CustomData` de la visite actuelle et de la dernière visite précédente. | `null`     |
    | shouldAddData (*optionnel*) | `boolean`                                 | Un booléen indiquant si la méthode doit automatiquement ajouter les données récupérées pour un visiteur.                                                                                            | `true`     |
    | completion (*requis*)       | `ResultCompletion<List<Data>, Exception>` | Le callback qui traite les données visiteur reçues.                                                                                                                                                 |            |
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    // Visitor data will be fetched and automatically added to the visitor.
    kameleoonClient.getRemoteVisitorData { result ->
        if (result.isSuccess) {
            // Data was successfully retrieved from the Kameleoon servers and added to the visitor.
        } else {
            // The request failed due to an exception.
        }
    }

    // If you only want to fetch data and add it yourself manually, set shouldAddData == `false`
    kameleoonClient.getRemoteVisitorData(false) { result ->
        try {
            val visitorData = result.getOrThrow()
            // visitorData contains the fetched visitor data from Kameleoon servers, which can be manually added.
        } catch (e: Exception) {
            // The request failed due to an exception.
        }
    }

    val filter = RemoteVisitorDataFilter.builder()
        .previousVisitAmount(25)
        .experiments(true)
        .conversion(true)
        .build()
    kameleoonClient.getRemoteVisitorData(filter) { result ->
        if (result.isSuccess) {
            // Data was successfully retrieved from the Kameleoon servers and added to the visitor.
        } else {
            // The request failed due to an exception.
        }
    }
    ```

    ##### Arguments

    | Nom                         | Type                                      | Description                                                                                                                                                                                         | Par défaut |
    | --------------------------- | ----------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
    | filter (*optionnel*)        | `RemoteVisitorDataFilter`                 | Filtre qui sélectionne quelles données doivent être récupérées de l'historique des visites. Par défaut, la méthode récupère `CustomData` de la visite actuelle et de la dernière visite précédente. | `null`     |
    | shouldAddData (*optionnel*) | `Boolean`                                 | Un booléen indiquant si la méthode doit automatiquement ajouter les données récupérées pour un visiteur.                                                                                            | `true`     |
    | completion (*requis*)       | `ResultCompletion<List<Data>, Exception>` | Le callback qui traite les données visiteur reçues.                                                                                                                                                 |            |
  </Tab>

  <Tab title="Kotlin (Coroutines)">
    <Warning>
      Une erreur courante est d'utiliser des fonctions suspendues à l'intérieur de `mapCatching`, `runCatching`, ou d'un bloc `try-catch` sans relancer correctement `CancellationException`, ce qui peut interférer avec l'annulation des coroutines. Pour garantir un comportement correct, essayez d'éviter d'appeler des fonctions suspend dans ces blocs.
    </Warning>

    ```kotlin theme={null}
    // Visitor data will be fetched and automatically added for `visitorCode`
    viewModelScope.launch {
        kameleoonClient.getRemoteVisitorData() ?: return@launch
    }

    // If you only want to fetch data and add it yourself manually, set shouldAddData == `false`
    viewModelScope.launch {
        kameleoonClient.getRemoteVisitorData(shouldAddData = false)
            .onSuccess { visitorData ->
                // visitorData contains the fetched visitor data from Kameleoon servers, which can be manually added.
            }.onFailure { ex ->
                // request failed with exception
            }
    }

    viewModelScope.launch {
        val filter = RemoteVisitorDataFilter.builder()
            .previousVisitAmount(25)
            .experiments(true)
            .conversion(true)
            .build()
        // In general, we recommend checking only if the request fails.
        kameleoonClient.getRemoteVisitorData(filter) ?: return@launch
    }
    ```

    ##### Arguments

    | Nom                         | Type                      | Description                                                                                                                                                                                         | Par défaut |
    | --------------------------- | ------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
    | filter (*optionnel*)        | `RemoteVisitorDataFilter` | Filtre qui sélectionne quelles données doivent être récupérées de l'historique des visites. Par défaut, la méthode récupère `CustomData` de la visite actuelle et de la dernière visite précédente. | `null`     |
    | shouldAddData (*optionnel*) | `Boolean`                 | Un booléen indiquant si la méthode doit automatiquement ajouter les données récupérées pour un visiteur.                                                                                            | `true`     |

    ##### Valeur de retour

    | Type                 | Description                                                                                                   |
    | -------------------- | ------------------------------------------------------------------------------------------------------------- |
    | `Result<List<Data>>` | Un `Result` Kotlin qui contient soit la valeur récupérée (`List<Data>`), soit l'exception qui s'est produite. |
  </Tab>
</Tabs>

##### Utilisation des paramètres de `RemoteVisitorDataFilter`

La méthode `getRemoteVisitorData()` offre de la flexibilité en vous permettant de définir divers paramètres lors de la récupération des données sur les visiteurs. Que vous cibliez en fonction des objectifs, des expériences ou des variations, la même approche s'applique à tous les types de données.

Par exemple, supposons que vous souhaitiez récupérer des données sur les visiteurs qui ont atteint un objectif "Order transaction". Vous pouvez spécifier des paramètres dans la méthode `getRemoteVisitorData()` pour affiner votre ciblage. Par exemple, si vous souhaitez cibler uniquement les utilisateurs qui ont converti sur l'objectif lors de leurs cinq dernières visites, vous pouvez définir le paramètre `previousVisitAmount` à `5` et `conversions` à `true`.

La flexibilité illustrée dans cet exemple n'est pas limitée aux données d'objectif. Vous pouvez utiliser des paramètres dans la méthode `getRemoteVisitorData()` pour récupérer des données sur une variété de comportements des visiteurs.

<Note>
  Voici la liste des options `RemoteVisitorDataFilter` disponibles :

  | Nom                               | Type      | Description                                                                                                                                                                                                                                                                                                                                                     | Par défaut |
  | --------------------------------- | --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
  | previousVisitAmount (*optionnel*) | `int`     | Nombre de visites précédentes à partir desquelles récupérer les données. Nombre entre `1` et `25`                                                                                                                                                                                                                                                               | `1`        |
  | currentVisit (*optionnel*)        | `boolean` | Si true, les données de la visite actuelle seront récupérées                                                                                                                                                                                                                                                                                                    | `true`     |
  | customData (*optionnel*)          | `boolean` | Si true, les données personnalisées seront récupérées.                                                                                                                                                                                                                                                                                                          | `true`     |
  | geolocation (*optionnel*)         | `boolean` | Si true, les données de géolocalisation seront récupérées.                                                                                                                                                                                                                                                                                                      | `false`    |
  | conversions (*optionnel*)         | `boolean` | Si true, les données de conversion seront récupérées.                                                                                                                                                                                                                                                                                                           | `false`    |
  | experiments (*optionnel*)         | `boolean` | Si true, les données d'expérience seront récupérées.                                                                                                                                                                                                                                                                                                            | `false`    |
  | kcs (*optionnel*)                 | `boolean` | Si true, le Kameleoon Conversion Score (KCS) sera récupéré. Nécessite l'[add-on AI Predictive Targeting](/user-manual/ai-predictive-targeting/target-users-based-on-likelihood-to-convert)                                                                                                                                                                      | `false`    |
  | visitorCode (*optionnel*)         | `boolean` | Si true, Kameleoon récupérera le `visitorCode` de la visite la plus récente et l'utilisera pour la visite actuelle. C'est nécessaire si vous voulez vous assurer que le visiteur, identifié par son `visitorCode`, reçoit toujours la même variation à travers les visites pour l'[expérimentation cross-device](/developer-docs/cross-device-experimentation). | `true`     |
  | personalization (*optionnel*)     | `boolean` | Si true, les données de personnalisation seront récupérées. Ceci est requis pour la condition de personnalisation.                                                                                                                                                                                                                                              | `false`    |
  | cbs (*optionnel*)                 | `boolean` | Si true, les données du score Contextual Bandit seront récupérées.                                                                                                                                                                                                                                                                                              | `false`    |
</Note>

#### getVisitorWarehouseAudience()

* 🔄 *Effectue une requête asynchrone*

Récupère toutes les données d'audience associées au visiteur dans votre data warehouse. Le paramètre optionnel `warehouseKey` est généralement votre ID utilisateur interne. Le paramètre `customDataIndex` correspond aux données personnalisées Kameleoon que Kameleoon utilise pour cibler vos visiteurs. Vous pouvez vous référer à la [documentation sur le ciblage warehouse](/user-manual/integrations/data-warehouses/bigquery/use-bigquery-as-a-source-audience-targeting) pour plus de détails.

<Warning>
  Étant donné qu'un appel serveur est requis, ce mécanisme est asynchrone. Par conséquent, vous devez soit :

  * Fournir un callback `completion` comme argument de la méthode pour vous assurer d'être notifié lorsque les données ont été récupérées et ajoutées avec succès au visiteur.
  * Utiliser les coroutines pour une gestion asynchrone.

  Il est recommandé de vérifier uniquement les résultats ayant échoué. Cependant, si nécessaire, on peut vérifier que les données ont été ajoutées au visiteur et sont disponibles à des fins de ciblage (ou pour le débogage, bien que l'utilisation du [logging](#logging) soit meilleure pour le débogage).
</Warning>

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    // Visitor data will be fetched and automatically added for the visitor
    kameleoonClient.getVisitorWarehouseAudience(customDataIndex, result -> {
        if (result.isSuccess()) {
            // Due to method called before this callback, data was automatically added to the visitor.
        } else {
            Exception exception = result.failure();
            // The request failed due to an exception.
        }
    });

    // If you need to specify warehouse key
    kameleoonClient.getVisitorWarehouseAudience("warehouseKey", customDataIndex, result -> {
        // Due to method called before this callback, data was automatically added to the visitor,
        // but you can evaluate the added data if necessary.
        try {
            CustomData data = result.getOrThrow();
        } catch (Exception exception) {
            // The request failed due to an exception.
        }
    });
    ```

    ##### Arguments

    | Nom                        | Type                                      | Description                                                                                                               | Par défaut |
    | -------------------------- | ----------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- | ---------- |
    | warehouseKey (*optionnel*) | `String`                                  | Une clé unique pour identifier les données du warehouse (généralement, votre ID utilisateur interne).                     | `null`     |
    | customDataIndex (*requis*) | `int`                                     | Un entier représentant l'index des données personnalisées que vous souhaitez utiliser pour cibler vos audiences BigQuery. |            |
    | completion (*requis*)      | `ResultCompletion<CustomData, Exception>` | Le callback qui traite les données reçues.                                                                                |            |
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    // Visitor data will be fetched and automatically added for the visitor
    kameleoonClient.getVisitorWarehouseAudience(customDataIndex) { result ->
        if (result.isSuccess) {
            // Due to method called before this callback, data was automatically added to the visitor.
        } else {
            val exception = result.failure()
            // The request failed due to an exception.
        }
    }

    // If you need to specify warehouse key
    kameleoonClient.getVisitorWarehouseAudience("warehouseKey", customDataIndex) { result ->
        // As a result of the method before this callback is called, data was automatically added to the visitor
        // but you can evaluate the added data if you need to check it.
        try {
            val data = result.getOrThrow()
        } catch (e: Exception) {
            // The request failed due to an exception.
        }
    }
    ```

    ##### Arguments

    | Nom                        | Type                                      | Description                                                                                                               | Par défaut |
    | -------------------------- | ----------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- | ---------- |
    | warehouseKey (*optionnel*) | `String`                                  | Une clé unique pour identifier les données du warehouse (généralement, votre ID utilisateur interne).                     | `null`     |
    | customDataIndex (*requis*) | `Int`                                     | Un entier représentant l'index des données personnalisées que vous souhaitez utiliser pour cibler vos audiences BigQuery. |            |
    | completion (*requis*)      | `ResultCompletion<CustomData, Exception>` | Le callback qui traite les données reçues.                                                                                |            |
  </Tab>

  <Tab title="Kotlin (Coroutines)">
    <Warning>
      Une erreur courante est d'utiliser des fonctions suspendues à l'intérieur de `mapCatching`, `runCatching`, ou d'un bloc `try-catch` sans relancer correctement `CancellationException`, ce qui peut interférer avec l'annulation des coroutines. Pour garantir un comportement correct, essayez d'éviter d'appeler des fonctions suspend dans ces blocs.
    </Warning>

    ```kotlin theme={null}
    // Visitor data will be fetched and automatically added for the visitor
    viewModelScope.launch {
        // As a result of the method call, the data was automatically added to the visitor.
        kameleoonClient.getVisitorWarehouseAudience(customDataIndex = customDataIndex) ?: return@launch
    }

    // If you need to specify warehouse key
    viewModelScope.launch {
        // As a result of the method call, the data was automatically added to the visitor.
        kameleoonClient.getVisitorWarehouseAudience("warehouseKey", customDataIndex)
            .onSuccess { customData ->
                // But you can evaluate the added data if you need to check it.
            }
            .onFailure { ex ->
                // The request failed due to an exception.
            }
    }
    ```

    ##### Arguments

    | Nom                        | Type     | Description                                                                                                               | Par défaut |
    | -------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------- | ---------- |
    | warehouseKey (*optionnel*) | `String` | Une clé unique identifiant les données du warehouse (généralement votre ID utilisateur interne).                          | `null`     |
    | customDataIndex (*requis*) | `Int`    | Un entier représentant l'index des données personnalisées que vous souhaitez utiliser pour cibler vos audiences BigQuery. |            |

    ##### Valeur de retour

    | Type                 | Description                                                                                                   |
    | -------------------- | ------------------------------------------------------------------------------------------------------------- |
    | `Result<CustomData>` | Un `Result` Kotlin qui contient soit la valeur récupérée (`CustomData`), soit l'exception qui s'est produite. |
  </Tab>
</Tabs>

#### setLegalConsent()

Vous devez utiliser cette méthode pour spécifier si le visiteur a donné son consentement légal pour l'utilisation de ses données personnelles. Définir le paramètre `legalConsent` à `false` limite les types de données que vous pouvez inclure dans les requêtes de suivi. Cette méthode vous aide à respecter les exigences légales et réglementaires tout en gérant de manière responsable les données des visiteurs. Vous pouvez trouver plus d'informations sur les données personnelles dans la [politique de gestion du consentement](/user-manual/project-management/consent-management-policy).

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    kameleoonClient.setLegalConsent(true);
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    kameleoonClient.setLegalConsent(true)
    ```
  </Tab>
</Tabs>

##### Arguments

| Nom          | Type    | Description                                                                                                                                                                                                                                    |
| ------------ | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| legalConsent | boolean | Une valeur booléenne représentant le statut du consentement légal. `true` indique que le visiteur a donné son consentement légal, `false` indique que le visiteur n'a jamais fourni, ou a retiré, son consentement légal. Ce champ est requis. |

### Types de données

Cette section liste les types `com.Kameleoon.Data` pris en charge par Kameleoon. Plusieurs types de données standard sont fournis, ainsi que le type `CustomData` pour définir des types de données personnalisés.

#### Conversion

Le jeu de données `Conversion` stocké ici peut être utilisé pour filtrer les rapports d'expérience et de personnalisation par tout objectif qui lui est associé.

<Tip>
  * Chaque visiteur peut avoir plusieurs objets `Conversion`.
  * Vous pouvez trouver le `goalId` dans l'application Kameleoon.
</Tip>

| Nom                    | Type            | Description                                  | Par défaut          |
| ---------------------- | --------------- | -------------------------------------------- | ------------------- |
| goalId (*requis*)      | `int`           | ID de l'objectif.                            |                     |
| revenue (*optionnel*)  | `float`         | Revenu de la conversion                      | `0`                 |
| negative (*optionnel*) | `boolean`       | Définit si le revenu est positif ou négatif. | `false`             |
| metadata (*optionnel*) | `CustomData...` | Métadonnées de la conversion.                | `new CustomData[0]` |

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    kameleoonClient.addData(new Conversion(32, 10f));

    kameleoonClient.addData(new Conversion(33, 0f, true));

    kameleoonClient.addData(
        new Conversion(34, 5f, new CustomData(3, "metadata1", "md2"), new CustomData(5, "md3"))
    );
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    kameleoonClient.addData(Conversion(32, 10f))

    kameleoonClient.addData(Conversion(33, 0f, true))

    kameleoonClient.addData(
        Conversion(34, 5f, CustomData(3, "metadata1", "md2"), CustomData(5, "md3"))
    )
    ```
  </Tab>
</Tabs>

#### Device

<Note>
  Depuis le SDK Android `4.13.0`, le `Device` est automatiquement détecté en fonction du [`android.content.Context`](https://developer.android.com/reference/android/content/Context). Cependant, vous pouvez toujours le remplacer manuellement si nécessaire.
</Note>

Stocke les informations sur l'appareil de l'utilisateur.

| Nom               | Type      | Description                                               |
| ----------------- | --------- | --------------------------------------------------------- |
| device (*requis*) | `Devices` | Liste des appareils : **phone**, **tablet**, **desktop**. |

<Tabs defaultTabIndex={0}>
  <Tab title="Java">
    ```java theme={null}
    kameleoonClient.addData(Device.tablet());
    ```
  </Tab>
</Tabs>

#### Geolocation

`Geolocation` contient les détails de géolocalisation du visiteur.

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    kameleoonClient.addData(new Geolocation("France", "Île-de-France", "Paris"));
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    kameleoonClient.addData(Geolocation("France", "Île-de-France", "Paris"))
    ```
  </Tab>
</Tabs>

| Nom                      | Type                  | Description                                                                                                                    |
| ------------------------ | --------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| country (*requis*)       | `String`              | Le pays du visiteur.                                                                                                           |
| region (*optionnel*)     | <nobr>`String`</nobr> | La région du visiteur.                                                                                                         |
| city (*optionnel*)       | <nobr>`String`</nobr> | La ville du visiteur.                                                                                                          |
| postalCode (*optionnel*) | <nobr>`String`</nobr> | Le code postal du visiteur.                                                                                                    |
| latitude (*optionnel*)   | `float`               | La coordonnée de latitude représentant la localisation du visiteur. Le nombre des coordonnées représente des degrés décimaux.  |
| longitude (*optionnel*)  | `float`               | La coordonnée de longitude représentant la localisation du visiteur. Le nombre des coordonnées représente des degrés décimaux. |

<Tip>
  * Chaque visiteur ne peut avoir qu'une seule `Geolocation`. L'ajout d'une seconde `Geolocation` écrase la première.
</Tip>

#### CustomData

Définissez vos propres types de données personnalisés dans l'application Kameleoon ou l'API de données et utilisez-les depuis le SDK.

| Nom                     | Type                             | Description                                                                                                                                                                                                                                    | Par défaut |
| ----------------------- | -------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| index/name (*requis*)   | `int`/`String`                   | Index ou Nom des données personnalisées. **Soit `index` soit `name` doit être fourni** pour identifier les données.                                                                                                                            |            |
| values (*requis*)       | `String...`/`Collection<String>` | Valeurs des données personnalisées à stocker.                                                                                                                                                                                                  |            |
| overwrite (*optionnel*) | `boolean`                        | Indicateur pour contrôler explicitement la manière dont les valeurs sont stockées et la manière dont elles apparaissent dans les rapports. [Voir plus](/developer-docs/custom-data#default-logic-when-overwrite-parameter-is-false-or-omitted) | `true`     |

<Note>
  * L'index des données personnalisées est disponible sur la page **Custom data configuration** de l'application Kameleoon. Attention : cet index commence à 0, donc les premières données personnalisées que vous créez pour un site donné auraient l'index 0, et non 1.
  * L'ajout d'une instance `CustomData` créée avec un nom alors que la configuration de l'instance du SDK n'est pas à jour ou que le nom n'est pas enregistré, entraînera l'ignorance des données.
</Note>

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    kameleoonClient.addData(new CustomData(1, "value"));

    // With several values
    kameleoonClient.addData(new CustomData(1, "value1", "value2"));

    // To set the 'overwrite' flag to false
    kameleoonClient.addData(new CustomData(1, false, "value"));

    // To use a name instead of the index
    kameleoonClient.addData(new CustomData("my-custom-data", "value"));
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    kameleoonClient.addData(CustomData(1, "value"))

    // With several values
    kameleoonClient.addData(CustomData(1, "value1", "value2"))

    // To set the 'overwrite' flag to false
    kameleoonClient.addData(CustomData(1, false, "value"))

    // To use a name instead of the index
    kameleoonClient.addData(CustomData("my-custom-data", "value"))
    ```
  </Tab>
</Tabs>

### Types retournés

#### DataFile

Le `DataFile` contient les détails de configuration du SDK.

Il peut être étendu avec des informations supplémentaires si les clients l'exigent. Si vous avez besoin de plus de détails, veuillez contacter votre Customer Success Manager.

| Nom          | Type                       | Description                                                                                        |
| ------------ | -------------------------- | -------------------------------------------------------------------------------------------------- |
| featureFlags | `Map<String, FeatureFlag>` | Une map d'objets [`FeatureFlag`](#featureflag), indexée par les clés de feature flag.              |
| dateModified | `long`                     | L'horodatage (en millisecondes) indiquant quand le `DataFile` a été modifié pour la dernière fois. |

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    // Retrieves the map of feature flags from the DataFile.
    // The map is keyed by feature flag identifiers, with each value being a FeatureFlag object.
    Map<String, FeatureFlag> featureFlags = dataFile.getFeatureFlags();

    // Retrieves the last modification timestamp of the DataFile.
    // The value is a long representing milliseconds since the Unix epoch.
    long dateModified = dataFile.getDateModified();
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    // Retrieves the map of feature flags from the DataFile.
    // The map is keyed by feature flag identifiers, with each value being a FeatureFlag object.
    val featureFlags = dataFile.featureFlags

    // Retrieves the last modification timestamp of the DataFile.
    // The value is a long representing milliseconds since the Unix epoch.
    val dateModified = dataFile.dateModified
    ```
  </Tab>
</Tabs>

#### FeatureFlag

Le `FeatureFlag` représente un ensemble de propriétés qui définissent un feature flag lui-même — par exemple, ses [`Variations`](#variation), [`Rules`](#rule), statut d'environnement et autres détails connexes.

Il peut être étendu avec des informations supplémentaires si les clients l'exigent. Si vous avez besoin de plus de détails, veuillez contacter votre Customer Success Manager.

| Nom                 | Type                     | Description                                                        |
| ------------------- | ------------------------ | ------------------------------------------------------------------ |
| environmentEnabled  | `boolean`                | Indique si le feature flag est activé dans l'environnement actuel. |
| defaultVariationKey | `String`                 | La clé de la variation par défaut associée au feature flag.        |
| variations          | `Map<String, Variation>` | Une map d'objets `Variation`, indexée par les clés de variation.   |
| rules               | `List<Rule>`             | Une liste d'objets `Rule`                                          |

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    // Check whether the feature flag is enabled in the current environment
    boolean isEnvironmentEnabled = featureFlag.isEnvironmentEnabled();

    // Retrieve the key of the default variation
    String defaultVariationKey = featureFlag.getDefaultVariationKey();

    // Retrieve the default variation object
    Variation defaultVariation = featureFlag.getDefaultVariation();

    // Retrieve all variations of the feature flag as a map (key = variation key, value = Variation object)
    Map<String, Variation> variations = featureFlag.getVariations();

    // Retrieve all targeting rules associated with the feature flag
    List<Rule> rules = featureFlag.getRules();
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    // Check whether the feature flag is enabled in the current environment
    val isEnvironmentEnabled = featureFlag.isEnvironmentEnabled

    // Retrieve the key of the default variation
    val defaultVariationKey = featureFlag.defaultVariationKey

    // Retrieve the default variation object
    val defaultVariation = featureFlag.defaultVariation

    // Retrieve all variations of the feature flag as a map (key = variation key, value = Variation object)
    val variations = featureFlag.variations

    // Retrieve all targeting rules associated with the feature flag
    val rules = featureFlag.rules
    ```
  </Tab>
</Tabs>

#### Rule

La `Rule` représente un ensemble de propriétés qui définissent une règle elle-même — par exemple, ses [`Variations`](#variation).

Elle peut être étendue avec des informations supplémentaires si les clients l'exigent. Si vous avez besoin de plus de détails, veuillez contacter votre Customer Success Manager.

| Nom        | Type                     | Description                                                      |
| ---------- | ------------------------ | ---------------------------------------------------------------- |
| variations | `Map<String, Variation>` | Une map d'objets `Variation`, indexée par les clés de variation. |

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    // Retrieve all variations of the rule as a map (key = variation key, value = Variation object)
    Map<String, Variation> variations = rule.getVariations();
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    // Retrieve all variations of the rule as a map (key = variation key, value = Variation object)
    val variations = rule.variations
    ```
  </Tab>
</Tabs>

#### Variation

`Variation` contient des informations sur la variation attribuée au visiteur (ou la variation par défaut, si aucune attribution spécifique n'existe).

| Nom          | Type                    | Description                                                                                                                                                         |
| ------------ | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| name         | `String`                | Le nom de la variation.                                                                                                                                             |
| key          | `String`                | La clé unique identifiant la variation.                                                                                                                             |
| id           | `Integer`               | L'ID de la variation attribuée (ou `null` s'il s'agit de la variation par défaut).                                                                                  |
| experimentId | `Integer`               | L'ID de l'expérience associée à la variation (ou `null` si par défaut).                                                                                             |
| variables    | `Map<String, Variable>` | Une map contenant les variables de la variation attribuée, indexée par les noms de variables. Cela peut être une collection vide si aucune variable n'est associée. |

<Note>
  * L'objet `Variation` fournit des détails sur la variation attribuée et son expérience associée, tandis que l'objet [`Variable`](#variable) contient des détails spécifiques sur chaque variable dans une variation.
  * Assurez-vous que votre code gère le cas où `id` ou `experimentId` peut être `null`, indiquant une variation par défaut.
  * La map `variables` peut être vide si aucune variable n'est associée à la variation.
</Note>

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    // Retrieving the variation name
    String variationName = variation.getName();

    // Retrieving the variation key
    String variationKey = variation.getKey();

    // Retrieving the variation id
    Integer variationId = variation.getId();

    // Retrieving the experiment id
    Integer experimentId = variation.getExperimentId();

    // Retrieving the variables map
    Map<String, Variable> variables = variation.getVariables();
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    // Retrieving the variation name
    val variationName = variation.name

    // Retrieving the variation key
    val variationKey = variation.key

    // Retrieving the variation id
    val variationId = variation.id

    // Retrieving the experiment id
    val experimentId = variation.experimentId

    // Retrieving the variables map
    val variables = variation.variables
    ```
  </Tab>
</Tabs>

#### Variable

`Variable` contient des informations sur une variable associée à la variation attribuée.

| Nom   | Type     | Description                                                                                                                                                           |
| ----- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| key   | `String` | La clé unique identifiant la variable.                                                                                                                                |
| type  | `String` | Le type de la variable. Valeurs possibles : **BOOLEAN**, **NUMBER**, **STRING**, **JSON**.                                                                            |
| value | `Object` | La valeur de la variable, qui peut être de l'un des types suivants : **boolean**, **int**, **long**, **double**, **String**, **JSONObject**, **JSONArray**, **null**. |

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    // Retrieving the variables map
    Map<String, Variable> variables = variation.getVariables();

    // Variable type can be retrieved for further processing
    String type = variables.get("isDiscount").getType();

    // Get the Boolean value of "isDiscount"
    Boolean isDiscount = (Boolean) variables.get("isDiscount").getValue();

    // Get the numeric value of "number" as an Integer
    Integer number = (Integer) variables.get("number").getValue();

    // Get the String value of "title"
    String title = (String) variables.get("title").getValue();
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    // Retrieving the variables map
    val variables = variation.variables

    // Variable type can be retrieved for further processing
    val type = variables["isDiscount"]?.type

    // Get the Boolean value of "isDiscount"
    val isDiscount = variables["isDiscount"]?.value as? Boolean

    // Get the numeric value of "number" as an Integer
    val number = variables.get("number").value as? Int

    // Get the String value of "title"
    val title = variables["title"]?.value as? String
    ```
  </Tab>
</Tabs>

### Méthodes obsolètes

<Warning>
  Ces méthodes sont obsolètes et seront supprimées dans la version `5.0.0` du SDK.
</Warning>

#### getFeatureVariationKey()

* 📨 *Envoie des données de suivi à Kameleoon*

<Note>
  Utilisez [`getVariation()`](#getvariation) à la place.
</Note>

Utilisez cette méthode pour obtenir la clé de variation de fonctionnalité pour un visiteur. Cette méthode prend un `featureKey` comme argument requis pour récupérer la clé de variation pour l'utilisateur spécifié.

Si le visiteur n'a jamais été associé à ce feature flag, le SDK renvoie une clé de variation attribuée aléatoirement (selon les règles du feature flag). Si le visiteur est déjà enregistré avec ce feature flag, cette méthode renvoie la clé de variation précédente. Si l'utilisateur ne correspond à aucune des règles, la valeur par défaut sera renvoyée, qui est définie dans le compte de votre client.

Assurez-vous de configurer une gestion appropriée des erreurs comme montré dans l'exemple de code pour attraper les exceptions potentielles.

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    String featureKey = "new_checkout";
    String variationKey = "";

    try {
        variationKey = kameleoonClient.getFeatureVariationKey(featureKey);
    } catch (KameleoonException.SDKNotReady e) {
        // Exception indicates that the SDK has not completed its initialization yet.
    } catch (KameleoonException.FeatureNotFound e) {
        // The error has occurred; feature flag isn't found in current configuration.
    } catch (KameleoonException.FeatureEnvironmentDisabled e) {
        // The feature flag is disabled for the environment
    } catch (Exception e) {
        // Recommended (but optional) safeguard for unexpected exceptions from third-party libraries
    }

    switch (variationKey) {
        case "on":
            //main variation key is selected for visitorCode
            break;
        case "alternative_variation":
            //alternative variation key
            break;
        default:
            //default variation key
            break;
    }
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    val featureKey = "new_checkout"
    var variationKey = ""

    try {
        variationKey = kameleoonClient.getFeatureVariationKey(featureKey)
    } catch (e: KameleoonException.SDKNotReady) {
        // Exception indicates that the SDK has not completed its initialization yet.
    } catch (e: KameleoonException.FeatureNotFound) {
        // Exception indicates that the SDK not initialized or the feature toggle is not yet activated on Kameleoon's side. We consider the feature inactive.
    } catch (e: KameleoonException.FeatureEnvironmentDisabled) {
        // The feature flag is disabled for the environment
    } catch (e: Exception) {
        // Recommended (but optional) safeguard for unexpected exceptions from third-party libraries
    }

    when (variationKey) {
        "on" -> {}
        "alternative_variation" -> {}
        else -> {}
    }
    ```
  </Tab>
</Tabs>

#### getFeatureVariationKey()

* 📨 *Envoie des données de suivi à Kameleoon*

<Note>
  Utilisez [`getVariation()`](#getvariation) à la place.
</Note>

Utilisez cette méthode pour obtenir la clé de variation de fonctionnalité pour un visiteur. Cette méthode prend un `featureKey` comme argument requis pour récupérer la clé de variation pour l'utilisateur spécifié.

Si le visiteur n'a jamais été associé à ce feature flag, le SDK renvoie une clé de variation attribuée aléatoirement (selon les règles du feature flag). Si le visiteur est déjà enregistré avec ce feature flag, cette méthode renvoie la clé de variation précédente. Si l'utilisateur ne correspond à aucune des règles, la valeur par défaut sera renvoyée, qui est définie dans le compte de votre client.

Assurez-vous de configurer une gestion appropriée des erreurs comme montré dans l'exemple de code pour attraper les exceptions potentielles.

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    String featureKey = "new_checkout";
    String variationKey = "";

    try {
        variationKey = kameleoonClient.getFeatureVariationKey(featureKey);
    } catch (KameleoonException.SDKNotReady e) {
        // Exception indicates that the SDK has not completed its initialization yet.
    } catch (KameleoonException.FeatureNotFound e) {
        // The error has occurred; feature flag isn't found in current configuration.
    } catch (KameleoonException.FeatureEnvironmentDisabled e) {
        // The feature flag is disabled for the environment
    } catch (Exception e) {
        // Recommended (but optional) safeguard for unexpected exceptions from third-party libraries
    }

    switch (variationKey) {
        case "on":
            //main variation key is selected for visitorCode
            break;
        case "alternative_variation":
            //alternative variation key
            break;
        default:
            //default variation key
            break;
    }
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    val featureKey = "new_checkout"
    var variationKey = ""

    try {
        variationKey = kameleoonClient.getFeatureVariationKey(featureKey)
    } catch (e: KameleoonException.SDKNotReady) {
        // Exception indicates that the SDK has not completed its initialization yet.
    } catch (e: KameleoonException.FeatureNotFound) {
        // Exception indicates that the SDK not initialized or the feature toggle is not yet activated on Kameleoon's side. We consider the feature inactive.
    } catch (e: KameleoonException.FeatureEnvironmentDisabled) {
        // The feature flag is disabled for the environment
    } catch (e: Exception) {
        // Recommended (but optional) safeguard for unexpected exceptions from third-party libraries
    }

    when (variationKey) {
        "on" -> {}
        "alternative_variation" -> {}
        else -> {}
    }
    ```
  </Tab>
</Tabs>

#### getActiveFeatures()

<Note>
  * Utilisez [`getVariations()`](#getvariations) à la place.
  * S'appelait auparavant `getFeatureListForVisitorCode`, qui a été supprimée dans la version `4.0.0` du SDK.
</Note>

La méthode `getActiveFeatures` récupère des informations sur les feature flags actifs disponibles pour le visiteur.

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    Map<String, Variation> listActiveFeatureFlags = kameleoonClient.getActiveFeatures();
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    val listActiveFeatureFlags = kameleoonClient.getActiveFeatures()
    ```
  </Tab>
</Tabs>

##### Valeur de retour

| Type                     | Description                                                                                                                                           |
| ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Map<String, Variation>` | Un dictionnaire qui contient les variations attribuées des fonctionnalités actives en utilisant les clés des fonctionnalités actives correspondantes. |

#### getFeatureVariable()

* 📨 *Envoie des données de suivi à Kameleoon*

<Note>
  Utilisez [`getVariation()`](#getvariation) à la place.
</Note>

Cette méthode obtient une valeur de variable de clé de variation pour un utilisateur spécifique. Elle prend un `featureKey` et un `variableKey` comme arguments requis.

Si le visiteur n'a jamais été associé au `featureKey`, le SDK renvoie une valeur de variable attribuée aléatoirement pour la clé de variation spécifiée (selon les règles du feature flag). Si le visiteur est déjà enregistré avec ce feature flag, la méthode renvoie la valeur de variable pour la variation précédemment enregistrée. Si l'utilisateur ne correspond à aucune des règles, la valeur de variable par défaut est renvoyée.

Assurez-vous de configurer une gestion appropriée des erreurs comme montré dans l'exemple de code pour attraper les exceptions potentielles.

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    String featureKey = "feature_key";
    String variableKey = "variableKey";

    try {
        Object variableValue = kameleoonClient.getFeatureVariable(featureKey, variableKey);
        // your custom code, depending on variableValue
    } catch (KameleoonException.SDKNotReady e) {
        // Exception indicates that the SDK has not completed its initialization yet.
    } catch (KameleoonException.FeatureNotFound e) {
        // The error has occurred; feature flag isn't found in current configuration.
    } catch (KameleoonException.FeatureVariableNotFound e) {
        // Requested variable not defined in Kameleoon
    } catch (KameleoonException.FeatureEnvironmentDisabled e) {
        // The feature flag is disabled for the environment.
    } catch (Exception e) {
        // Recommended (but optional) safeguard for unexpected exceptions from third-party libraries
    }
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    val featureKey = "new_checkout"
    val variableKey = "var"

    try {
        val variableValue = kameleoonClient.getFeatureVariable(featureKey, variableKey)
        // your custom code depending of variableValue
    } catch (e: KameleoonException.SDKNotReady) {
        // Exception indicating that the SDK has not completed its initialization yet.
    } catch (e: KameleoonException.FeatureNotFound) {
        // The error is happened, feature flag isn't found in current configuraiton
    } catch (e: KameleoonException.FeatureVariableNotFound) {
        // Requested variable not defined on Kameleoon's side
    } catch (e: KameleoonException.FeatureEnvironmentDisabled) {
        // The feature flag is disabled for the environment
    } catch (e: Exception) {
        // Recommended (but optional) safeguard for unexpected exceptions from third-party libraries
    }
    ```
  </Tab>
</Tabs>

##### Arguments

| Nom          | Type   | Description                                                                                 |
| ------------ | ------ | ------------------------------------------------------------------------------------------- |
| featureKey   | String | Clé de la fonctionnalité que vous souhaitez afficher à un utilisateur. Ce champ est requis. |
| variableName | String | Nom de la variable pour laquelle vous souhaitez obtenir une valeur. Ce champ est requis.    |

##### Valeur de retour

| Type   | Description                                                                                                                                                                                 |
| ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| object | Valeur de la variable de variation qui est enregistrée pour le `visitorCode` spécifié pour ce feature flag. Types valides : `boolean`, `int`, `double`, `String`, `JSONObject`, `JSONArray` |

##### Exceptions levées

| Type                       | Description                                                                                                                                                                                                                                                                                  |
| -------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| SDKNotReady                | Exception indiquant que le SDK n'a pas terminé son initialisation.                                                                                                                                                                                                                           |
| FeatureNotFound            | Exception indiquant que la clé de fonctionnalité demandée a été trouvée dans la configuration interne du SDK. Cette exception signifie généralement que le feature flag n'a pas été activé côté Kameleoon (mais le code implémentant la fonctionnalité est déjà déployé dans l'application). |
| FeatureVariableNotFound    | Exception indiquant que la variable spécifiée n'a pas été trouvée. Vérifiez que la clé de variable dans l'application Kameleoon correspond à celle de votre code.                                                                                                                            |
| FeatureEnvironmentDisabled | Exception indiquant que le feature flag est désactivé pour l'environnement actuel du visiteur (par exemple, production, staging ou development).                                                                                                                                             |

#### getFeatureVariationVariables()

<Note>
  * Utilisez [`getVariation()`](#getvariation) à la place.
  * Cette méthode s'appelait auparavant `getFeatureAllVariables`, qui a été supprimée dans la version `4.0.0` du SDK.
</Note>

Pour récupérer toutes les variables d'une fonctionnalité, appelez cette méthode. Vous pouvez modifier vos variables de fonctionnalité dans l'application Kameleoon.

Cette méthode prend un paramètre d'entrée : `featureKey`. Elle renvoie les données sous forme de type `Map<String, Object>`, comme défini dans l'application Kameleoon. Elle lève une exception (`FeatureNotFound`) si la fonctionnalité demandée n'a pas été trouvée dans la configuration interne du SDK.

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    String featureKey = "myFeature";
    String variationKey = "variation1";

    try {
        Map<String, Object> variables = kameleoonClient.getFeatureVariationVariables(featureKey, variationKey);
    } catch (KameleoonException.SDKNotReady e) {
        // Exception indicating that the SDK has not completed its initialization yet.
    } catch (KameleoonException.FeatureNotFound e) {
        // The feature is not yet activated on Kameleoon's side
    } catch (KameleoonException.FeatureEnvironmentDisabled e) {
        // The feature flag is disabled for the environment
    } catch (Exception e) {
        // This is a generic Exception handler which will handle all exceptions.
        System.out.println("Exception occurred");
    }
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    val featureKey = "myFeature"
    val variationKey = "variation1"

    try {
        val variables = kameleoonClient.getFeatureVariationVariables(featureKey, variationKey)
    } catch (e: KameleoonException.SDKNotReady) {
        // Exception indicating that the SDK has not completed its initialization yet.
    } catch (e: KameleoonException.FeatureNotFound) {
        // The feature is not yet activated on Kameleoon's side
    } catch (e: KameleoonException.FeatureEnvironmentDisabled) {
        // The feature flag is disabled for the environment
    } catch (e: Exception) {
        // This is a generic Exception handler which will handle all exceptions.
        println("Exception occurred")
    }
    ```
  </Tab>
</Tabs>

##### Arguments

| Nom        | Type   | Description                                                                          |
| ---------- | ------ | ------------------------------------------------------------------------------------ |
| featureKey | String | Identifiant unique de la fonctionnalité que vous devez obtenir. Ce champ est requis. |

##### Valeur de retour

| Type                 | Description                                                                                                                                                                                      |
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `Map<String,Object>` | Données représentant les variables associées à ce feature flag. Les valeurs peuvent être `int`, `String`, `boolean`, `JSONObject` ou `JSONArray` (selon les types définis dans l'interface web). |

##### Exceptions levées

| Type                       | Description                                                                                                                                                                                                      |
| -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| SDKNotReady                | Exception indiquant que le SDK n'a pas terminé son initialisation.                                                                                                                                               |
| FeatureNotFound            | Exception indiquant que la fonctionnalité demandée n'a pas été trouvée dans la configuration interne du SDK. Cette exception signifie généralement que le feature flag n'a pas encore été activé côté Kameleoon. |
| FeatureVariableNotFound    | Exception indiquant que la variable spécifiée n'a pas été trouvée. Vérifiez que la clé de variable dans l'application Kameleoon correspond à la clé de votre code.                                               |
| FeatureEnvironmentDisabled | Exception indiquant que le feature flag est désactivé pour l'environnement actuel du visiteur (par exemple, production, staging ou development).                                                                 |

#### getFeatureList()

<Tip>
  Si vous souhaitez itérer sur tous les feature flags et appeler [`getVariation()`](#getvariation) sur chacun, utilisez plutôt la méthode [`getVariations()`](#getvariations).
</Tip>

Renvoie une liste de clés de feature flag actuellement disponibles pour le SDK.

<Tabs defaultTabIndex={1}>
  <Tab title="Java">
    ```java theme={null}
    List<String> allFeatureFlagListId = kameleoonClient.getFeatureList();
    ```
  </Tab>

  <Tab title="Kotlin">
    ```kotlin theme={null}
    val allFeatureFlagListId = kameleoonClient.getFeatureList()
    ```
  </Tab>
</Tabs>

##### Valeur de retour

| Type           | Description                   |
| -------------- | ----------------------------- |
| `List<String>` | Liste de clés de feature flag |
