

# Kit SDK de diffusion IVS : Guide pour Android \$1 Diffusion en temps réel
<a name="broadcast-android"></a>

Le SDK de diffusion Android par streaming en temps réel IVS permet aux participants d’envoyer et de recevoir des vidéos sur Android.

Le package `com.amazonaws.ivs.broadcast` implémente l’interface décrite dans ce document. Le SDK prend en charge les opérations suivantes :
+ Rejoindre une étape 
+ Publier du contenu multimédia à l’intention des autres participants de l’étape
+ S’abonner à du contenu multimédia d’autres participants de l’étape
+ Gérer et surveiller la vidéo et le son publiés sur l’étape
+ Obtenir des statistiques WebRTC pour chaque connexion d’appairage
+ Toutes les opérations à partir du SDK de diffusion Android par streaming à faible latence

**Dernière version du SDK de diffusion Android :** 1.40.0 ([notes de mise à jour](https://docs.aws.amazon.com/ivs/latest/RealTimeUserGuide/release-notes.html#mar12-26-broadcast-android-rt)) 

**Documentation de référence :** pour plus d'informations sur les méthodes les plus importantes disponibles dans le kit SDK de diffusion Android Amazon IVS, consultez la documentation de référence à l'adresse [https://aws.github.io/amazon-ivs-broadcast-docs/1.40.0/android/](https://aws.github.io/amazon-ivs-broadcast-docs/1.40.0/android/).

**Exemple de code : **voir le référentiel d’exemples Android sur GitHub : [https://github.com/aws-samples/amazon-ivs-real-time-streaming-android-samples](https://github.com/aws-samples/amazon-ivs-real-time-streaming-android-samples).

**Exigences de la plateforme :** Android 9.0\$1

# Démarrez avec le SDK de diffusion Android IVS \$1 Streaming en temps réel
<a name="broadcast-android-getting-started"></a>

Ce document explique les étapes nécessaires pour le démarrage avec le SDK de diffusion Android IVS en temps réel.

## Installer la bibliothèque
<a name="broadcast-android-install"></a>

Il existe plusieurs façons d’ajouter la bibliothèque de diffusion Android d’Amazon IVS à votre environnement de développement Android : utiliser Gradle directement, utiliser les catalogues de versions de Gradle ou installer le kit SDK manuellement.

**Utiliser Gradle directement** : ajoutez la bibliothèque dans le fichier `build.gradle` de votre module, comme indiqué ici (pour la dernière version du kit SDK de diffusion IVS) :

```
repositories {
    mavenCentral()
}
 
dependencies {
     implementation 'com.amazonaws:ivs-broadcast:1.40.0:stages@aar'
}
```

**Utiliser les catalogues de versions de Gradle** : ajoutez d’abord ceci dans le fichier `build.gradle` de votre module :

```
implementation(libs.ivs){
   artifact {
      classifier = "stages"
      type = "aar"
   }
}
```

Ajoutez ensuite les éléments suivants dans le fichier `libs.version.toml` (pour la dernière version du kit SDK de diffusion IVS) :

```
[versions]
ivs="1.40.0"

[libraries]
ivs = {module = "com.amazonaws:ivs-broadcast", version.ref = "ivs"}
```

**Installer le kit SDK manuellement** : téléchargez la dernière version à partir de l’emplacement suivant :

[https://search.maven.org/artifact/com.amazonaws/ivs-broadcast](https://search.maven.org/artifact/com.amazonaws/ivs-broadcast)

N’oubliez pas de télécharger le `aar` en ajoutant le suffixe `-stages`.

**Autoriser le contrôle du haut-parleur par le kit SDK** : indépendamment de la méthode d’installation choisie, ajoutez également l’autorisation suivante dans votre manifeste pour permettre au kit SDK d’activer et de désactiver le haut-parleur :

```
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
```

## Utilisation du kit SDK avec des symboles de débogage
<a name="broadcast-android-using-debug-symbols-rt"></a>

Nous publions également une version du kit SDK de diffusion Android incluant des symboles de débogage. Vous pouvez utiliser cette version pour améliorer la qualité des rapports de débogage (traces de pile) dans Firebase Crashlytics, en cas de plantages dans le kit SDK de diffusion IVS, par exemple `libbroadcastcore.so`. Lorsque vous signalez ces plantages à l’équipe SDK IVS, des traces de pile de meilleure qualité facilitent la résolution des problèmes.

Pour utiliser cette version du kit SDK, ajoutez la ligne suivante dans vos fichiers de configuration Gradle :

```
implementation "com.amazonaws:ivs-broadcast:$version:stages-unstripped@aar"
```

Utilisez la ligne ci-dessus au lieu de celle-ci :

```
implementation "com.amazonaws:ivs-broadcast:$version:stages@aar"
```

### Téléchargement des symboles vers Firebase Crashlytics
<a name="android-debug-symbols-rt-firebase-crashlytics"></a>

Assurez-vous que vos fichiers de configuration Gradle sont bien configurés pour Firebase Crashlytics. Suivez les instructions de Google ici :

[https://firebase.google.com/docs/crashlytics/ndk-reports](https://firebase.google.com/docs/crashlytics/ndk-reports)

Veillez à ajouter `com.google.firebase:firebase-crashlytics-ndk` en tant que dépendance.

Lorsque vous créez votre application en vue de sa publication, le plug-in Firebase Crashlytics devrait automatiquement télécharger les symboles. Pour ce faire, exécutez l’une des commandes suivantes :

```
gradle uploadCrashlyticsSymbolFileRelease
```

```
./gradlew uploadCrashlyticsSymbolFileRelease
```

(Il n’y a aucun risque si les symboles sont téléchargés deux fois, automatiquement et manuellement.)

### Prévention de l’augmentation de la taille du fichier .apk en version finale
<a name="android-debug-symbols-rt-sizing-apk"></a>

Avant de générer le fichier `.apk` en version finale, le plug-in Android Gradle tente automatiquement de supprimer les informations de débogage des bibliothèques partagées (y compris la bibliothèque `libbroadcastcore.so` du kit SDK de diffusion IVS). Cependant, cela ne fonctionne pas toujours. En conséquence, votre fichier `.apk` pourrait augmenter en taille et vous pourriez recevoir un message d’avertissement du plug-in Android Gradle indiquant qu’il n’a pas pu supprimer les symboles de débogage et qu’il inclut les fichiers `.so` tels quels. Si cela se produit, procédez comme suit :
+ Installez un NDK Android. Toute version récente fonctionnera.
+ Ajoutez `ndkVersion <your_installed_ndk_version_number>` au fichier `build.gradle` de votre application. Procédez ainsi même si votre application elle-même ne contient pas de code natif.

Pour plus d’informations, consultez ce [problème connu](https://issuetracker.google.com/issues/353554169).

## Demander des autorisations
<a name="broadcast-android-permissions"></a>

Votre appli doit demander l’autorisation d’accéder à la caméra et au micro de l’utilisateur. (Ce n’est pas spécifique à Amazon IVS ; cette autorisation est requise pour toute application devant accéder aux caméras et aux micros.)

Ici, nous vérifions si l’utilisateur a déjà accordé des autorisations et, dans le cas contraire, nous les demandons :

```
final String[] requiredPermissions =
         { Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO };

for (String permission : requiredPermissions) {
    if (ContextCompat.checkSelfPermission(this, permission) 
                != PackageManager.PERMISSION_GRANTED) {
        // If any permissions are missing we want to just request them all.
        ActivityCompat.requestPermissions(this, requiredPermissions, 0x100);
        break;
    }
}
```

Ici, nous obtenons la réponse de l’utilisateur :

```
@Override
public void onRequestPermissionsResult(int requestCode, 
                                      @NonNull String[] permissions,
                                      @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode,
               permissions, grantResults);
    if (requestCode == 0x100) {
        for (int result : grantResults) {
            if (result == PackageManager.PERMISSION_DENIED) {
                return;
            }
        }
        setupBroadcastSession();
    }
}
```

# Publication et abonnement avec le SDK de diffusion Android IVS \$1 Streaming en temps réel
<a name="android-publish-subscribe"></a>

Ce document explique les étapes nécessaires pour la publication et l'abonnement à une étape à l'aide du SDK de diffusion Android IVS en temps réel.

## Concepts
<a name="android-publish-subscribe-concepts"></a>

Trois concepts de base sous-tendent la fonctionnalité temps réel : [scène](#android-publish-subscribe-concepts-stage), [stratégie](#android-publish-subscribe-concepts-strategy) et [moteur de rendu](#android-publish-subscribe-concepts-renderer). L’objectif de la conception consiste à minimiser la quantité de logique côté client nécessaire à la création d’un produit fonctionnel.

### Étape
<a name="android-publish-subscribe-concepts-stage"></a>

La classe `Stage` est le principal point d’interaction entre l’application hôte et le kit SDK. Il représente l’étape elle-même et est utilisé pour rejoindre et quitter l’étape. La création et la participation à une étape nécessitent une chaîne de jetons valide et non expirée provenant du plan de contrôle (représentée par `token`). Il est très facile de rejoindre une étape et de la quitter. 

```
Stage stage = new Stage(context, token, strategy);

try {
	stage.join();
} catch (BroadcastException exception) {
	// handle join exception
}

stage.leave();
```

La classe `Stage` est également l’endroit où vous pouvez joindre le `StageRenderer` :

```
stage.addRenderer(renderer); // multiple renderers can be added
```

### Strategy
<a name="android-publish-subscribe-concepts-strategy"></a>

L’interface `Stage.Strategy` permet à l’application hôte de communiquer l’état de l’étape souhaité au kit SDK. Trois fonctions doivent être mises en œuvre : `shouldSubscribeToParticipant`, `shouldPublishFromParticipant` et `stageStreamsToPublishForParticipant`. Elles sont toutes abordées ci-dessous.

#### Abonnement aux participants
<a name="android-publish-subscribe-concepts-strategy-participants"></a>

```
Stage.SubscribeType shouldSubscribeToParticipant(@NonNull Stage stage, @NonNull ParticipantInfo participantInfo);
```

Lorsqu’un participant distant rejoint l’étape, le kit SDK interroge l’application hôte sur l’état de l’abonnement souhaité pour ce participant. Les options sont `NONE`, `AUDIO_ONLY` et `AUDIO_VIDEO`. Lors d’un renvoi d’une valeur pour cette fonction, l’application hôte n’a pas à se soucier de l’état de publication, de l’état actuel de l’abonnement ou de l’état de la connexion de l’étape. Si `AUDIO_VIDEO` est renvoyé, le kit SDK attend que le participant distant effectue une publication avant de s’abonner, puis il met à jour l’application hôte par le biais du moteur de rendu tout au long du processus.

Voici un exemple d’implémentation :

```
@Override
Stage.SubscribeType shouldSubscribeToParticipant(@NonNull Stage stage, @NonNull ParticipantInfo participantInfo) {
	return Stage.SubscribeType.AUDIO_VIDEO;
}
```

Il s’agit de l’implémentation complète de cette fonction pour une application hôte qui souhaite toujours que tous les participants se voient mutuellement, comme une application de chat vidéo.

Des implémentations plus avancées sont également possibles. Utilisez la propriété `userInfo` sur `ParticipantInfo` pour vous abonner de manière sélective aux participants en fonction des attributs fournis par le serveur :

```
@Override
Stage.SubscribeType shouldSubscribeToParticipant(@NonNull Stage stage, @NonNull ParticipantInfo participantInfo) {
	switch(participantInfo.userInfo.get(“role”)) {
		case “moderator”:
			return Stage.SubscribeType.NONE;
		case “guest”:
			return Stage.SubscribeType.AUDIO_VIDEO;
		default:
			return Stage.SubscribeType.NONE;
	}
}
```

Elle peut servir à créer une scène où les modérateurs peuvent surveiller tous les invités sans être vus ou entendus. L’application hôte pourrait utiliser une logique métier supplémentaire pour permettre aux modérateurs de se voir mutuellement tout en restant invisible pour les invités.

#### Configuration d’abonnement aux participants
<a name="android-publish-subscribe-concepts-strategy-participants-config"></a>

```
SubscribeConfiguration subscribeConfigurationForParticipant(@NonNull Stage stage, @NonNull ParticipantInfo participantInfo);
```

[Lorsqu’un participant distant est abonné (voir Abonnement aux participants](#android-publish-subscribe-concepts-strategy-participants)), le kit SDK interroge l’application hôte sur une configuration d’abonnement personnalisée pour ce participant. Cette configuration est facultative et permet à l’application hôte de contrôler certains aspects du comportement de l’abonné. Pour plus d’informations sur les options de configuration, consultez [SubscribeConfiguration](https://aws.github.io/amazon-ivs-web-broadcast/docs/sdk-reference/interfaces/SubscribeConfiguration) dans la documentation de référence du kit SDK.

Voici un exemple d’implémentation :

```
@Override
public SubscribeConfiguration subscribeConfigrationForParticipant(@NonNull Stage stage, @NonNull ParticipantInfo participantInfo) {
    SubscribeConfiguration config = new SubscribeConfiguration();

    config.jitterBuffer.setMinDelay(JitterBufferConfiguration.JitterBufferDelay.MEDIUM());

    return config;
}
```

Cette implémentation met à jour le délai minimum de la mémoire tampon pour tous les participants abonnés à un préréglage de `MEDIUM`.

Comme pour `shouldSubscribeToParticipant`, des implémentations plus avancées sont possibles. `ParticipantInfo` peut être utilisé pour mettre à jour de manière sélective la configuration d’abonnement pour des participants spécifiques.

Nous recommandons d’utiliser les comportements par défaut. Spécifiez une configuration personnalisée uniquement si vous souhaitez modifier un comportement particulier.

#### Publication
<a name="android-publish-subscribe-concepts-strategy-publishing"></a>

```
boolean shouldPublishFromParticipant(@NonNull Stage stage, @NonNull ParticipantInfo participantInfo);
```

Une fois connecté à l’étape, le kit SDK interroge l’application hôte pour savoir si un participant en particulier doit effectuer une publication. Elle n’est invoquée que pour les participants locaux autorisés à publier sur la base du jeton fourni.

Voici un exemple d’implémentation :

```
@Override
boolean shouldPublishFromParticipant(@NonNull Stage stage, @NonNull ParticipantInfo participantInfo) {
	return true;
}
```

Il s’agit d’une application de chat vidéo standard dans laquelle les utilisateurs souhaitent toujours publier. Ils peuvent désactiver et réactiver leur son et leur vidéo pour être instantanément masqués ou vus/entendus. (Ils peuvent également utiliser la fonction de publication/d’annulation de la publication, mais c’est beaucoup plus lent. Il est préférable de désactiver ou de réactiver le son dans les cas d’utilisation où il est souvent souhaitable de modifier la visibilité.)

#### Choix des flux à publier
<a name="android-publish-subscribe-concepts-strategy-streams"></a>

```
@Override
List<LocalStageStream> stageStreamsToPublishForParticipant(@NonNull Stage stage, @NonNull ParticipantInfo participantInfo);
}
```

Lors de la publication, cette fonction est utilisée pour déterminer les flux audio et vidéo à publier. Ce point est abordé plus en détail dans la section [Publier un flux multimédia](#android-publish-subscribe-publish-stream).

#### Mise à jour de la stratégie
<a name="android-publish-subscribe-concepts-strategy-updates"></a>

La stratégie se veut dynamique : les valeurs renvoyées par n’importe laquelle des fonctions ci-dessus peuvent être modifiées à tout moment. Par exemple, si l’application hôte ne souhaite pas publier tant que l’utilisateur final n’a pas appuyé sur un bouton, vous pouvez renvoyer une variable depuis `shouldPublishFromParticipant` (quelque chose comme `hasUserTappedPublishButton`). Lorsque cette variable change en fonction d’une interaction de l’utilisateur final, appelez `stage.refreshStrategy()` pour signaler au kit SDK qu’il doit interroger la stratégie pour connaître les dernières valeurs, en appliquant uniquement les éléments qui ont changé. Si le kit SDK constate que la valeur `shouldPublishFromParticipant` a changé, il lance le processus de publication. Si les requêtes du kit SDK et toutes les fonctions renvoient la même valeur qu’auparavant, l’appel `refreshStrategy` n’apportera aucune modification à l’étape.

Si la valeur de retour de `shouldSubscribeToParticipant` passe de `AUDIO_VIDEO` à `AUDIO_ONLY`, le flux vidéo sera supprimé pour tous les participants dont les valeurs renvoyées ont été modifiées, s’il existait déjà un flux vidéo.

En général, l’étape utilise la stratégie pour appliquer au mieux la différence entre les stratégies précédentes et actuelles, sans que l’application hôte n’ait à se soucier de tout l’état requis pour la gérer correctement. Pour cette raison, et pour réduire les frais, envisagez d’appeler `stage.refreshStrategy()`, car cela ne fait rien à moins que la stratégie ne change.

### Moteur de rendu
<a name="android-publish-subscribe-concepts-renderer"></a>

L’interface `StageRenderer` communique l’état de l’étape à l’application hôte. Les mises à jour de l’interface utilisateur de l’application hôte peuvent généralement être entièrement optimisées par les événements fournis par le moteur de rendu. Le moteur de rendu fournit les fonctions suivantes :

```
void onParticipantJoined(@NonNull Stage stage, @NonNull ParticipantInfo participantInfo);

void onParticipantLeft(@NonNull Stage stage, @NonNull ParticipantInfo participantInfo);

void onParticipantPublishStateChanged(@NonNull Stage stage, @NonNull ParticipantInfo participantInfo, @NonNull Stage.PublishState publishState);

void onParticipantSubscribeStateChanged(@NonNull Stage stage, @NonNull ParticipantInfo participantInfo, @NonNull Stage.SubscribeState subscribeState);

void onStreamsAdded(@NonNull Stage stage, @NonNull ParticipantInfo participantInfo, @NonNull List<StageStream> streams);

void onStreamsRemoved(@NonNull Stage stage, @NonNull ParticipantInfo participantInfo, @NonNull List<StageStream> streams);

void onStreamsMutedChanged(@NonNull Stage stage, @NonNull ParticipantInfo participantInfo, @NonNull List<StageStream> streams);

void onError(@NonNull BroadcastException exception);

void onConnectionStateChanged(@NonNull Stage stage, @NonNull Stage.ConnectionState state, @Nullable BroadcastException exception);
                
void onStreamAdaptionChanged(@NonNull Stage stage, @NonNull ParticipantInfo participantInfo, @NonNull RemoteStageStream stream, boolean adaption);

void onStreamLayersChanged(@NonNull Stage stage, @NonNull ParticipantInfo participantInfo, @NonNull RemoteStageStream stream, @NonNull List<RemoteStageStream.Layer> layers);

void onStreamLayerSelected(@NonNull Stage stage, @NonNull ParticipantInfo participantInfo, @NonNull RemoteStageStream stream, @Nullable RemoteStageStream.Layer layer, @NonNull RemoteStageStream.LayerSelectedReason reason);
```

Pour la plupart de ces méthodes, les `Stage` et `ParticipantInfo` correspondantes sont fournies.

Les informations fournies par le moteur de rendu ne devraient pas avoir d’impact sur les valeurs de retour de la stratégie. Par exemple, la valeur de retour de `shouldSubscribeToParticipant` ne devrait pas changer lors de l’appel de `onParticipantPublishStateChanged`. Si l’application hôte souhaite s’abonner à un participant en particulier, elle doit renvoyer le type d’abonnement souhaité, quel que soit l’état de publication de ce participant. Le kit SDK est chargé de s’assurer que l’état souhaité de la stratégie est appliqué au bon moment en fonction de l’état de l’étape.

Le `StageRenderer` peut être attaché à la classe de l’étape :

```
stage.addRenderer(renderer); // multiple renderers can be added
```

Notez que seuls les participants à la publication déclenchent `onParticipantJoined` et que chaque fois qu’un participant arrête de publier ou quitte la session de l’étape, `onParticipantLeft` est déclenché.

## Publier un flux multimédia
<a name="android-publish-subscribe-publish-stream"></a>

Les appareils locaux tels que les microphones et les caméras intégrés sont découverts via `DeviceDiscovery`. Voici un exemple de sélection de la caméra frontale et du microphone par défaut, puis de leur renvoi en tant que `LocalStageStreams` à publier par le SDK :

```
DeviceDiscovery deviceDiscovery = new DeviceDiscovery(context);

List<Device> devices = deviceDiscovery.listLocalDevices();
List<LocalStageStream> publishStreams = new ArrayList<LocalStageStream>();

Device frontCamera = null;
Device microphone = null;

// Create streams using the front camera, first microphone
for (Device device : devices) {
	Device.Descriptor descriptor = device.getDescriptor();
	if (!frontCamera && descriptor.type == Device.Descriptor.DeviceType.Camera && descriptor.position = Device.Descriptor.Position.FRONT) {
		front Camera = device;
	}
	if (!microphone && descriptor.type == Device.Descriptor.DeviceType.Microphone) {
		microphone = device;
	}
}

ImageLocalStageStream cameraStream = new ImageLocalStageStream(frontCamera);
AudioLocalStageStream microphoneStream = new AudioLocalStageStream(microphoneDevice);

publishStreams.add(cameraStream);
publishStreams.add(microphoneStream);

// Provide the streams in Stage.Strategy
@Override
@NonNull List<LocalStageStream> stageStreamsToPublishForParticipant(@NonNull Stage stage, @NonNull ParticipantInfo participantInfo) {
	return publishStreams;
}
```

## Afficher et supprimer des participants
<a name="android-publish-subscribe-participants"></a>

Une fois l’abonnement effectué, vous recevrez un tableau d’objets `StageStream` via la fonction `onStreamsAdded` du moteur de rendu. Vous pouvez récupérer l’aperçu à partir d’un `ImageStageStream` :

```
ImagePreviewView preview = ((ImageStageStream)stream).getPreview();

// Add the view to your view hierarchy
LinearLayout previewHolder = findViewById(R.id.previewHolder);
preview.setLayoutParams(new LinearLayout.LayoutParams(
		LinearLayout.LayoutParams.MATCH_PARENT,
		LinearLayout.LayoutParams.MATCH_PARENT));
previewHolder.addView(preview);
```

Vous pouvez récupérer les statistiques au niveau de l’audio à partir d’un `AudioStageStream` :

```
((AudioStageStream)stream).setStatsCallback((peak, rms) -> {
	// handle statistics
});
```

Lorsqu’un participant arrête de publier ou en cas de désabonnement, la fonction `onStreamsRemoved` est appelée avec les flux qui ont été supprimés. Les applications hôte doivent utiliser ce signal pour supprimer le flux vidéo du participant de la hiérarchie des vues.

`onStreamsRemoved` est invoqué pour tous les scénarios dans lesquels un flux peut être supprimé, notamment : 
+ Le participant distant arrête de publier.
+ Un appareil local se désabonne ou modifie l’abonnement de `AUDIO_VIDEO` en `AUDIO_ONLY`.
+ Le participant distant quitte l’étape.
+ Le participant local quitte l’étape.

Comme `onStreamsRemoved` est invoqué pour tous les scénarios, aucune logique métier personnalisée n’est requise pour supprimer des participants de l’interface utilisateur lors des opérations de départ locales ou à distance.

## Désactiver et réactiver le son des flux de médias sociaux
<a name="android-publish-subscribe-mute-streams"></a>

Les objets `LocalStageStream` ont une fonction `setMuted` qui contrôle si le son du flux est désactivé. Cette fonction peut être appelée sur le flux avant ou après son renvoi par la fonction de stratégie `streamsToPublishForParticipant`.

**Important** : si une nouvelle instance d’objet `LocalStageStream` est renvoyée par `streamsToPublishForParticipant` après un appel à `refreshStrategy`, l’état muet du nouvel objet de flux est appliqué à l’étape. Lorsque vous créez des instances `LocalStageStream`, veillez à ce que l’état muet attendu soit conservé.

## Surveiller l’état muet du contenu multimédia des participants distants
<a name="android-publish-subscribe-mute-state"></a>

Lorsqu’un participant modifie l’état muet de son flux vidéo ou audio, la fonction `onStreamMutedChanged` du moteur de rendu est invoquée avec une liste des flux qui ont changé. Utilisez la méthode `getMuted` sur `StageStream` pour mettre à jour votre interface utilisateur en conséquence. 

```
@Override
void onStreamsMutedChanged(@NonNull Stage stage, @NonNull ParticipantInfo participantInfo, @NonNull List<StageStream> streams) {
	for (StageStream stream : streams) {
		boolean muted = stream.getMuted();
		// handle UI changes
	}
}
```

## Obtenir les statistiques WebRTC
<a name="android-publish-subscribe-webrtc-stats"></a>

Pour obtenir les dernières statistiques WebRTC relatives à un flux de publication ou d’abonnement, utilisez `requestRTCStats` sur `StageStream`. Lorsqu’une collecte est réalisée, vous recevez des statistiques via le `StageStream.Listener` que vous pouvez définir sur `StageStream`.

```
stream.requestRTCStats();

@Override
void onRTCStats(Map<String, Map<String, String>> statsMap) {
	for (Map.Entry<String, Map<String, string>> stat : statsMap.entrySet()) {
		for(Map.Entry<String, String> member : stat.getValue().entrySet()) {
			Log.i(TAG, stat.getKey() + “ has member “ + member.getKey() + “ with value “ + member.getValue());
		}
	}
}
```

## Obtenir les attributs des participants
<a name="android-publish-subscribe-participant-attributes"></a>

Si vous spécifiez des attributs dans la demande de l’opération `CreateParticipantToken`, vous pouvez les voir dans les propriétés `ParticipantInfo` :

```
@Override
void onParticipantJoined(@NonNull Stage stage, @NonNull ParticipantInfo participantInfo) {
	for (Map.Entry<String, String> entry : participantInfo.userInfo.entrySet()) {
		Log.i(TAG, “attribute: “ + entry.getKey() + “ = “ + entry.getValue());
	}
}
```

## Messages intégrés
<a name="android-publish-subscribe-embed-messages"></a>

La méthode `embedMessage` sur ImageDevice permet d’insérer des données utiles de métadonnées directement dans les images vidéo lors de la publication. Cela permet une messagerie synchronisée avec les images pour les applications en temps réel. L’intégration de messages est disponible uniquement lors de l’utilisation du SDK pour la publication en temps réel (et non pour la publication à faible latence).

Les messages intégrés ne sont pas garantis d’arriver aux abonnés, car ils sont intégrés directement dans les images vidéo et transmis via UDP, qui ne garantit pas la livraison des paquets. La perte de paquets pendant la transmission peut entraîner la perte de messages, en particulier dans des conditions réseau médiocres. Pour atténuer ce problème, la méthode `embedMessage` inclut un paramètre `repeatCount` qui duplique le message sur plusieurs images consécutives, augmentant ainsi la fiabilité de la livraison. Cette fonctionnalité est disponible uniquement pour les flux vidéo.

### Utilisation de embedMessage
<a name="android-embed-messages-using-embedmessage"></a>

Les clients de publication peuvent intégrer des données utiles de messages dans leur flux vidéo en utilisant la méthode `embedMessage` sur ImageDevice. La taille des données utiles doit être supérieure à 0 Ko et inférieure à 1 Ko. Le nombre de messages intégrés insérés par seconde ne doit pas dépasser 10 Ko. 

```
val surfaceSource: SurfaceSource = imageStream.device as SurfaceSource
val message = "hello world"
val messageBytes = message.toByteArray(StandardCharsets.UTF_8)

try {
    surfaceSource.embedMessage(messageBytes, 0)
} catch (e: BroadcastException) {
    Log.e("EmbedMessage", "Failed to embed message: ${e.message}")
}
```

### Répétition des données utiles de messages
<a name="android-embed-messages-repeat-payloads"></a>

Utilisez `repeatCount` pour dupliquer le message sur plusieurs images afin d’améliorer la fiabilité. La valeur doit être comprise entre 0 et 30. Les clients destinataires doivent disposer d'une logique permettant de dédupliquer le message.

```
try {
    surfaceSource.embedMessage(messageBytes, 5)
    // repeatCount: 0-30, receiving clients should handle duplicates
} catch (e: BroadcastException) {
    Log.e("EmbedMessage", "Failed to embed message: ${e.message}")
}
```

### Lecture des messages intégrés
<a name="android-embed-messages-read-messages"></a>

Consultez la section « Obtenir des informations supplémentaires sur les améliorations (SEI) » ci-dessous pour savoir comment lire les messages intégrés à partir des flux entrants.

## Obtenir des informations supplémentaires sur les améliorations (SEI)
<a name="android-publish-subscribe-sei-attributes"></a>

L’unité NAL d’informations supplémentaires sur les améliorations (SEI) est utilisée pour stocker des métadonnées alignées sur l’image à côté de la vidéo. Les clients abonnés peuvent lire les données utiles SEI d’un diffuseur de publication qui publie une vidéo H.264 en inspectant la propriété `embeddedMessages` sur les objets `ImageDeviceFrame` provenant de l’objet `ImageDevice` du diffuseur de publication. Pour ce faire, acquérez `ImageDevice` d’un diffuseur de publication, puis observez chaque image via un rappel fourni à `setOnFrameCallback`, comme le montre l’exemple suivant :

```
// in a StageRenderer’s onStreamsAdded function, after acquiring the new ImageStream

val imageDevice = imageStream.device as ImageDevice
imageDevice.setOnFrameCallback(object : ImageDevice.FrameCallback {
	override fun onFrame(frame: ImageDeviceFrame) {
    		for (message in frame.embeddedMessages) {
        		if (message is UserDataUnregisteredSeiMessage) {
            		val seiMessageBytes = message.data
            		val seiMessageUUID = message.uuid
           	 
            		// interpret the message's data based on the UUID
        		}
    		}
	}
})
```

## Poursuivre la session en arrière-plan
<a name="android-publish-subscribe-background-session"></a>

Lorsque l’application passe en arrière-plan, vous souhaiterez peut-être vous abonner uniquement au contenu audio des autres participants distants ou arrêter de le publier. Pour ce faire, mettez à jour votre implémentation `Strategy` pour arrêter la publication et abonnez-vous à `AUDIO_ONLY` (ou `NONE`, le cas échéant).

```
// Local variables before going into the background
boolean shouldPublish = true;
Stage.SubscribeType subscribeType = Stage.SubscribeType.AUDIO_VIDEO;

// Stage.Strategy implementation
@Override
boolean shouldPublishFromParticipant(@NonNull Stage stage, @NonNull ParticipantInfo participantInfo) {
	return shouldPublish;
}

@Override
Stage.SubscribeType shouldSubscribeToParticipant(@NonNull Stage stage, @NonNull ParticipantInfo participantInfo) {
	return subscribeType;
}

// In our Activity, modify desired publish/subscribe when we go to background, then call refreshStrategy to update the stage
@Override
void onStop() {
	super.onStop();
	shouldPublish = false;
	subscribeTpye = Stage.SubscribeType.AUDIO_ONLY;
	stage.refreshStrategy();
}
```

## Encodage en couches avec Simulcast
<a name="android-publish-subscribe-layered-encoding-simulcast"></a>

L’encodage en couches avec diffusion simultanée est une fonctionnalité de diffusion en temps réel d’IVS qui permet aux diffuseurs d’envoyer plusieurs couches de vidéo de qualité différente et aux abonnés de configurer ces couches de manière dynamique ou manuelle. Cette fonctionnalité est décrite plus en détail dans le document [Optimisations de la diffusion](real-time-streaming-optimization.md).

### Configuration du codage en couches (diffuseur de publication)
<a name="android-layered-encoding-simulcast-configure-publisher"></a>

En tant que diffuseur de publication, pour activer l’encodage en couches avec la diffusion simultanée, ajoutez la configuration suivante à votre `LocalStageStream` lors de l’instanciation :

```
// Enable Simulcast
StageVideoConfiguration config = new StageVideoConfiguration();
config.simulcast.setEnabled(true);

ImageLocalStageStream cameraStream = new ImageLocalStageStream(frontCamera, config);

// Other Stage implementation code
```

En fonction de la résolution que vous avez définie dans la configuration vidéo, un certain nombre de couches seront encodées et envoyées comme défini dans la section [Couches, qualités et fréquences d’images par défaut](real-time-streaming-optimization.md#real-time-streaming-optimization-default-layers) de la section *Optimisations de la diffusion*.

Vous avez également la possibilité de configurer des couches individuelles depuis la configuration de diffusion simultanée : 

```
// Enable Simulcast
StageVideoConfiguration config = new StageVideoConfiguration();
config.simulcast.setEnabled(true);

List<StageVideoConfiguration.Simulcast.Layer> simulcastLayers = new ArrayList<>();
simulcastLayers.add(StagePresets.SimulcastLocalLayer.DEFAULT_720);
simulcastLayers.add(StagePresets.SimulcastLocalLayer.DEFAULT_180);

config.simulcast.setLayers(simulcastLayers);

ImageLocalStageStream cameraStream = new ImageLocalStageStream(frontCamera, config);

// Other Stage implementation code
```

Vous pouvez également créer vos propres configurations de couches personnalisées pour un maximum de trois couches. Si vous fournissez un tableau vide ou ne contenant aucune valeur, les valeurs par défaut décrites ci-dessus sont utilisées. Les couches sont décrites avec les propriétés setter requises suivantes :
+ `setSize: Vec2;`
+ `setMaxBitrate: integer;`
+ `setMinBitrate: integer;`
+ `setTargetFramerate: integer;`

À partir des préréglages, vous pouvez remplacer des propriétés individuelles ou créer une toute nouvelle configuration :

```
// Enable Simulcast
StageVideoConfiguration config = new StageVideoConfiguration();
config.simulcast.setEnabled(true);

List<StageVideoConfiguration.Simulcast.Layer> simulcastLayers = new ArrayList<>();

// Configure high quality layer with custom framerate
StageVideoConfiguration.Simulcast.Layer customHiLayer = StagePresets.SimulcastLocalLayer.DEFAULT_720;
customHiLayer.setTargetFramerate(15);

// Add layers to the list
simulcastLayers.add(customHiLayer);
simulcastLayers.add(StagePresets.SimulcastLocalLayer.DEFAULT_180);

config.simulcast.setLayers(simulcastLayers);

ImageLocalStageStream cameraStream = new ImageLocalStageStream(frontCamera, config);

// Other Stage implementation code
```

Pour connaître les valeurs maximales, les limites et les erreurs qui peuvent être déclenchées lors de la configuration de couches individuelles, consultez la documentation de référence du kit SDK.

### Configuration de l’encodage en couches (abonné)
<a name="android-layered-encoding-simulcast-configure-subscriber"></a>

En tant qu’abonné, il n’est pas nécessaire d’activer l’encodage en couches. Si un diffuseur de publication envoie des couches de diffusion simultanée, le serveur s’adapte dynamiquement entre les couches pour choisir la qualité optimale en fonction de l’appareil de l’abonné et des conditions du réseau.

Sinon, pour choisir les couches explicites que le diffuseur de publication envoie, il existe plusieurs options, décrites ci-dessous.

### Option 1 : préférence pour la qualité de la couche initiale
<a name="android-layered-encoding-simulcast-layer-quality-preference"></a>

En utilisant la stratégie `subscribeConfigurationForParticipant`, il est possible de choisir la couche initiale que vous voulez recevoir en tant qu’abonné :

```
@Override
public SubscribeConfiguration subscribeConfigrationForParticipant(@NonNull Stage stage, @NonNull ParticipantInfo participantInfo) {
    SubscribeConfiguration config = new SubscribeConfiguration();

    config.simulcast.setInitialLayerPreference(SubscribeSimulcastConfiguration.InitialLayerPreference.LOWEST_QUALITY);

    return config;
}
```

Par défaut, les abonnés reçoivent toujours d’abord la couche de qualité la plus faible, puis la couche de qualité la plus élevée. Cela permet d’optimiser la consommation de bande passante de l’utilisateur final et d’offrir le meilleur temps d’accès à la vidéo, réduisant ainsi les blocages initiaux de la vidéo pour les utilisateurs sur des réseaux plus faibles.

Ces options sont disponibles pour `InitialLayerPreference` :
+ `LOWEST_QUALITY` : le serveur diffuse d’abord la couche de vidéo de qualité la plus faible. Cela permet d’optimiser la consommation de la bande passante ainsi que le temps d’accès au contenu multimédia. La qualité est définie comme la combinaison de la taille, du débit binaire et de la fréquence d’images de la vidéo. Par exemple, une vidéo 720p est de moins bonne qualité qu’une vidéo 1080p.
+ `HIGHEST_QUALITY` : le serveur délivre d’abord la couche de vidéo de la plus haute qualité. Cela permet d’optimiser la qualité, mais peut augmenter le temps d’accès au contenu multimédia. La qualité est définie comme la combinaison de la taille, du débit binaire et de la fréquence d’images de la vidéo. Par exemple, la vidéo 1080p est de meilleure qualité que la vidéo 720p.

**Remarque :** pour que les préférences de couche initiale (l’appel `setInitialLayerPreference`) prennent effet, un nouvel abonnement est nécessaire, car ces mises à jour ne s’appliquent pas à l’abonnement actif.

### Option 2 : couche préférée pour le flux
<a name="android-layered-encoding-simulcast-preferred-layer"></a>

La méthode de stratégie `preferredLayerForStream` vous permet de sélectionner une couche après le démarrage du flux. Cette méthode de stratégie reçoit les informations relatives au participant et au flux, ce qui vous permet de sélectionner une couche participant par participant. Le kit SDK appelle cette méthode en réponse à des événements spécifiques, par exemple lorsque les couches de flux changent, que l’état des participants change ou que l’application hôte actualise la stratégie.

La méthode de stratégie renvoie un objet `RemoteStageStream.Layer`, qui peut être l’un des suivants :
+ Un objet de couche, tel qu’un objet renvoyé par `RemoteStageStream.getLayers`.
+ null, qui indique qu’aucune couche ne doit être sélectionnée et que l’adaptation dynamique est privilégiée.

Par exemple, dans la stratégie suivante, les utilisateurs sélectionneront toujours la couche de vidéo de la plus basse qualité disponible :

```
@Nullable
@Override
public RemoteStageStream.Layer preferredLayerForStream(@NonNull Stage stage, @NonNull ParticipantInfo participantInfo, @NonNull RemoteStageStream stream) {
    return stream.getLowestQualityLayer();
}
```

Pour réinitialiser la sélection des couches et revenir à l’adaptation dynamique, renvoyez null ou undefined dans la stratégie. Dans cet exemple, `appState` est une variable d’espace réservé qui représente l’état de l’application hôte.

```
@Nullable
@Override
public RemoteStageStream.Layer preferredLayerForStream(@NonNull Stage stage, @NonNull ParticipantInfo participantInfo, @NonNull RemoteStageStream stream) {
    if (appState.isAutoMode) {
        return null;
    } else {
        return appState.layerChoice;
    }
}
```

### Option 3 : aides pour les couches de RemoteStageStream
<a name="android-layered-encoding-simulcast-remotestagestream-helpers"></a>

`RemoteStageStream` possède plusieurs aides qui peuvent être utilisées pour prendre des décisions concernant la sélection des couches et afficher les sélections correspondantes aux utilisateurs finaux :
+ **Événements relatifs aux couches** : tout comme `StageRenderer`, `RemoteStageStream.Listener` possède des événements qui communiquent les modifications apportées aux couches et à l’adaptation de la diffusion simultanée :
  + `void onAdaptionChanged(boolean adaption)`
  + `void onLayersChanged(@NonNull List<Layer> layers)`
  + `void onLayerSelected(@Nullable Layer layer, @NonNull LayerSelectedReason reason)`
+ **Méthodes relatives aux couches** : `RemoteStageStream` possède plusieurs méthodes d’aide qui peuvent être utilisées pour obtenir des informations sur le flux et les couches présentées. Ces méthodes sont disponibles sur le flux distant fourni dans la stratégie `preferredLayerForStream`, ainsi que sur les flux distants exposés via `StageRenderer.onStreamsAdded`.
  + `stream.getLayers`
  + `stream.getSelectedLayer`
  + `stream.getLowestQualityLayer`
  + `stream.getHighestQualityLayer`
  + `stream.getLayersWithConstraints`

Pour plus de détails, consultez la classe `RemoteStageStream` dans la [documentation de référence du kit SDK](https://aws.github.io/amazon-ivs-broadcast-docs/latest/android/) (français non garanti). Pour la raison `LayerSelected`, si le message `UNAVAILABLE` est renvoyé, cela indique que la couche demandée n'a pas pu être sélectionnée. La meilleure sélection est faite à sa place, qui est généralement une couche de qualité inférieure pour maintenir la stabilité du flux.

## Limitations relatives à la configuration vidéo
<a name="android-publish-subscribe-video-limits"></a>

Le kit SDK ne permet pas de forcer l’utilisation du mode portrait ou paysage à l’aide de `StageVideoConfiguration.setSize(BroadcastConfiguration.Vec2 size)`. En orientation portrait, la plus petite dimension est utilisée comme largeur, tandis qu’en orientation paysage, il s’agit de la hauteur. Cela signifie que les deux appels suivants à `setSize` ont le même effet sur la configuration vidéo :

```
StageVideo Configuration config = new StageVideo Configuration();

config.setSize(BroadcastConfiguration.Vec2(720f, 1280f);
config.setSize(BroadcastConfiguration.Vec2(1280f, 720f);
```

## Gestion des problèmes de réseau
<a name="android-publish-subscribe-network-issues"></a>

En cas de perte de la connexion réseau de l’appareil local, le kit SDK essaie de se reconnecter en interne sans aucune action de l’utilisateur. Dans certains cas, le kit SDK échoue et une action de l’utilisateur est requise. Deux erreurs principales sont liées à la perte de la connexion réseau :
+ Code d’erreur 1400, message : « PeerConnection perdue en raison d’une erreur réseau inconnue »
+ Code d’erreur 1300, message : « Le nombre de nouvelles tentatives est épuisé »

Si la première erreur est reçue, mais pas la seconde, cela signifie que le kit SDK est toujours connecté à l’étape et qu’il essaiera de rétablir ses connexions automatiquement. Par mesure de sécurité, vous pouvez appeler `refreshStrategy` sans modifier les valeurs de retour de la méthode stratégique, afin de déclencher une tentative de reconnexion manuelle.

Si la deuxième erreur est reçue, les tentatives de reconnexion du kit SDK ont échoué et l’appareil local n’est plus connecté à l’étape. Dans ce cas, essayez de rejoindre l’étape en appelant `join` une fois votre connexion réseau rétablie.

En général, le fait de rencontrer des erreurs après avoir correctement rejoint une étape indique que le kit SDK n’a pas réussi à rétablir la connexion. Créez un objet `Stage` et essayez de le joindre lorsque les conditions du réseau s’améliorent.

## Utilisation de microphones Bluetooth
<a name="android-publish-subscribe-bluetooth-microphones"></a>

Pour publier à l’aide de microphones Bluetooth, vous devez établir une connexion Bluetooth SCO :

```
Bluetooth.startBluetoothSco(context);
// Now bluetooth microphones can be used
…
// Must also stop bluetooth SCO
Bluetooth.stopBluetoothSco(context);
```

# Problèmes connus et solutions de contournement dans le SDK de diffusion Android IVS \$1 Streaming en temps réel
<a name="broadcast-android-known-issues"></a>

Ce document répertorie les problèmes connus que vous pouvez rencontrer lors de l’utilisation du kit SDK de diffusion Android en temps réel d’Amazon IVS et propose des solutions de contournement potentielles.
+ Lorsqu’un appareil Android se met en veille et en sort, il est possible que l’aperçu soit figé.

  **Solution de contournement :** créez et utilisez une `Stage`.
+ Lorsqu’un participant rejoint la session avec un jeton utilisé par un autre participant, la première connexion est déconnectée sans erreur spécifique.

  **Solution de contournement :** aucune. 
+ Dans de rares cas, le diffuseur de publication publie, alors que l’état de la publication reçu par les abonnés est `inactive`.

  **Solution de contournement :** essayez de quitter la session, puis de la rejoindre. Si le problème persiste, créez un jeton pour le diffuseur de publication.
+ Un problème rare de distorsion audio peut survenir par intermittence pendant une session d’étape, généralement lors d’appels de plus longue durée.

  **Solution de contournement :** le participant dont le son est déformé peut soit quitter la session et la rejoindre, soit annuler la publication et republier son contenu audio pour ainsi corriger le problème.
+ Les microphones externes ne sont pas pris en charge lors de la publication sur une étape.

  **Solution de contournement :** n’utilisez pas de microphone externe connecté via USB pour publier sur une étape.
+ La publication sur une étape avec le partage d’écran en utilisant `createSystemCaptureSources` n’est pas prise en charge.

  **Solution de contournement :** gérez la capture du système manuellement à l’aide de sources d’entrée d’image personnalisées et de sources d’entrée audio personnalisées.
+ Lorsqu’une `ImagePreviewView` est supprimée d’un parent (par exemple, `removeView()` est appelée au niveau du parent), la `ImagePreviewView` est immédiatement lancée. La `ImagePreviewView` n’affiche aucun cadre lorsqu’elle est ajoutée à une autre vue parent.

  **Solution de contournement :** demandez un autre aperçu à l’aide de `getPreview`.
+ Lorsque vous rejoignez une étape avec un Samsung Galaxy S22/\$1 doté d’Android 12, vous pouvez rencontrer une erreur 1401 et l’appareil local ne parvient pas à rejoindre l’étape, ou le fait sans émettre de son.

  **Solution de contournement :** passez à Android 13.
+ Lorsque vous rejoignez une étape avec un Nokia X20 sous Android 13, il se peut que l’appareil photo ne parvienne pas à s’ouvrir et une exception est déclenchée.

  **Solution de contournement :** aucune.
+ Il se peut que les appareils équipés du chipset MediaTek Helio n’affichent pas correctement les vidéos des participants distants.

  **Solution de contournement :** aucune.
+ Sur certains appareils, le système d’exploitation de l’appareil peut choisir un microphone différent de celui sélectionné via le kit SDK. Cela est dû au fait que le kit SDK de diffusion Amazon IVS ne peut pas contrôler la façon dont la route audio `VOICE_COMMUNICATION` est définie, car elle varie en fonction des fabricants d’appareils.

  **Solution de contournement :** aucune.
+ Certains encodeurs vidéo Android ne peuvent pas être configurés avec une taille vidéo inférieure à 176x176. Configurer une taille plus petite entraîne une erreur et empêche la diffusion.

  **Solution :** ne configurez pas la taille vidéo à moins de 176x176.

# Gestion des erreurs dans le SDK de diffusion Android IVS \$1 Streaming en temps réel
<a name="broadcast-android-error-handling"></a>

Cette section donne un aperçu des conditions d’erreur, de la façon dont le SDK de diffusion Android IVS en temps réel les signale à l’application et des actions que l’application doit prendre lorsqu’elles se produisent.

## Erreurs fatales ou non fatales
<a name="broadcast-android-fatal-vs-nonfatal-errors"></a>

L’objet d’erreur possède un champ booléen « est fatal » de `BroadcastException`.

En général, les erreurs fatales sont liées à la connexion au serveur Stages (soit la connexion ne peut pas être établie, soit elle est perdue et ne peut pas être rétablie). L’application doit recréer la scène et la rejoindre, éventuellement avec un nouveau jeton ou lorsque la connectivité de l’appareil sera rétablie.

Les erreurs non fatales sont généralement liées à l’état de publication/d’abonnement et sont gérées par le kit SDK, qui relance l’opération de publication/abonnement.

Vous pouvez vérifier cette propriété :

```
try {
  stage.join(...)
} catch (e: BroadcastException) {
  If (e.isFatal) { 
    // the error is fatal
```

## Erreurs de jonction
<a name="broadcast-android-stage-join-errors"></a>

### Jeton incorrect
<a name="broadcast-android-stage-join-errors-malformed-token"></a>

Cela se produit lorsque le jeton d’étape est incorrect.

Le kit SDK génère une exception Java à partir d’un appel à `stage.join`, avec le code d’erreur = 1000 et fatal = vrai.

**Action** : créez un jeton valide et réessayez de vous connecter.

### Jeton expiré
<a name="broadcast-android-stage-join-errors-expired-token"></a>

Cela se produit lorsque le jeton d’étape est expiré.

Le kit SDK génère une exception Java à partir d’un appel à `stage.join`, avec le code d’erreur = 1001 et fatal = vrai.

**Action** : créez un nouveau jeton et réessayez de vous connecter.

### Jeton non valide ou révoqué
<a name="broadcast-android-stage-join-errors-invalid-token"></a>

Cela se produit lorsque le jeton d’étape n’est pas incorrect mais qu’il est rejeté par le serveur Stages. Cela est signalé de façon asynchrone via le moteur de rendu d’étape fourni par l’application.

Le kit SDK appelle `onConnectionStateChanged` avec une exception, avec le code d’erreur = 1026 et fatal = vrai.

**Action** : créez un jeton valide et réessayez de vous connecter.

### Erreurs réseau lors de la connexion initiale
<a name="broadcast-android-stage-join-errors-network-initial-join"></a>

Cela se produit lorsque le kit SDK ne parvient pas à contacter le serveur Stages pour établir une connexion. Cela est signalé de façon asynchrone via le moteur de rendu d’étape fourni par l’application.

Le kit SDK appelle `onConnectionStateChanged` avec une exception, avec le code d’erreur = 1300 et fatal = vrai.

**Action** : attendez que la connectivité de l’appareil soit rétablie et réessayez de vous connecter.

### Erreurs réseau lorsque vous êtes déjà connecté
<a name="broadcast-android-stage-join-errors-network-already-joined"></a>

En cas de perte de la connexion réseau de l’appareil, le kit SDK risque de perdre sa connexion aux serveurs Stage. Cela est signalé de façon asynchrone via le moteur de rendu d’étape fourni par l’application.

Le kit SDK appelle `onConnectionStateChanged` avec une exception, avec le code d’erreur = 1300 et fatal = vrai.

**Action** : attendez que la connectivité de l’appareil soit rétablie et réessayez de vous connecter.

## Erreurs de publication/d’abonnement
<a name="broadcast-android-publish-subscribe-errors"></a>

### Initial
<a name="broadcast-android-publish-subscribe-errors-initial"></a>

Il existe plusieurs erreurs :
+ MultihostSessionOfferCreationFailPublish (Échec de publication de l’offre de création de sessions multi-hôtes) (1020)
+ MultihostSessionOfferCreationFailSubscribe (Échec de la création de l’offre de session multi-hôtes) (1021)
+ MultihostSessionNoIceCandidates (Session multi-hôtes No Ice Candidats) (1022)
+ MultihostSessionStageAtCapacity (Étape de session multi-hôtes à pleine capacité) (1024)
+ SignallingSessionCannotRead (Impossible de lire la session de signalisation) (1201)
+ SignallingSessionCannotSend ((Impossible d’envoyer la session de signalisation) (1202)
+ SignallingSessionBadResponse (Mauvaise réponse de la session de signalisation) (1203)

Ceux-ci sont signalés de façon asynchrone via le moteur de rendu d’étape fourni par l’application.

Le kit SDK relance l’opération un nombre limité de fois. Lors des nouvelles tentatives, l’état de publication/d’abonnement est `ATTEMPTING_PUBLISH` / `ATTEMPTING_SUBSCRIBE`. Si les nouvelles tentatives réussissent, l’état passe à `PUBLISHED` / `SUBSCRIBED`.

Le kit SDK appelle `onError` avec le code d’erreur approprié et fatal = faux.

**Action** : aucune action n’est nécessaire, car le kit SDK réessaie automatiquement. Le cas échéant, l’application peut actualiser la stratégie pour forcer d’autres tentatives.

### Déjà établi, puis échec
<a name="broadcast-android-publish-subscribe-errors-established"></a>

Une publication ou un abonnement peut échouer une fois qu’il a été établi, probablement en raison d’une erreur réseau. Le code d’erreur pour une « connexion d’appairage perdue en raison d’une erreur réseau » est 1400.

Cela est signalé de façon asynchrone via le moteur de rendu d’étape fourni par l’application.

Le kit SDK relance l’opération de publication/d’abonnement. Lors des nouvelles tentatives, l’état de publication/d’abonnement est `ATTEMPTING_PUBLISH` / `ATTEMPTING_SUBSCRIBE`. Si les nouvelles tentatives réussissent, l’état passe à `PUBLISHED` / `SUBSCRIBED`.

Le kit SDK appelle `onError` avec le code d’erreur = 1400 et fatal = false.

**Action** : aucune action n’est nécessaire, car le kit SDK réessaie automatiquement. Le cas échéant, l’application peut actualiser la stratégie pour forcer d’autres tentatives. En cas de perte totale de connectivité, il est probable que la connexion à Stages échoue également.