

# IVS-Broadcast-SDK: Android-Handbuch \$1 Echtzeit-Streaming
<a name="broadcast-android"></a>

Das Android-Broadcast-SDK für IVS-Echtzeit-Streaming ermöglicht es den Teilnehmern, Videos auf Android zu senden und zu empfangen.

Das Paket `com.amazonaws.ivs.broadcast` implementiert die in diesem Dokument beschriebene Schnittstelle. Das SDK unterstützt die folgenden Vorgänge:
+ Einer Stage beitreten 
+ Medien für andere Teilnehmer auf der Stage veröffentlichen
+ Medien anderer Teilnehmer auf der Stage abonnieren
+ Auf der Stage veröffentlichte Videos und Audios verwalten und überwachen
+ WebRTC-Statistiken für jede Peer-Verbindung beziehen
+ Alle Vorgänge aus dem IVS-Streaming-SDK für Android-Übertragungen mit niedriger Latenz

**Aktuelle Version des Broadcast-SDK für Android:** 1.40.0 ([Versionshinweise](https://docs.aws.amazon.com/ivs/latest/RealTimeUserGuide/release-notes.html#mar12-26-broadcast-android-rt)) 

Informationen zu den wichtigsten Methoden, die im Amazon-IVS-Android-Broadcast-SDK verfügbar sind, finden Sie in der **Referenzdokumentation** unter [https://aws.github.io/amazon-ivs-broadcast-docs/1.40.0/android/](https://aws.github.io/amazon-ivs-broadcast-docs/1.40.0/android/).

**Beispiel-Code:** Siehe das Android-Beispiel-Repository auf 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).

**Plattformanforderungen:** Android 9.0 und höher

# Erste Schritte mit dem IVS Android Broadcast SDK \$1 Streaming in Echtzeit
<a name="broadcast-android-getting-started"></a>

Dieses Dokument führt Sie durch die Schritte zum Einstieg in das Android Broadcast SDK von IVS-Streaming in Echtzeit.

## Bibliothek installieren
<a name="broadcast-android-install"></a>

Es gibt mehrere Möglichkeiten, die Android-Broadcast-Bibliothek von Amazon IVS Ihrer Android-Entwicklungsumgebung hinzuzufügen: direkte Verwendung von Gradle, Verwendung von Gradle-Versionskatalogen oder manuelle Installation des SDK.

**Direkte Verwendung von Gradle**: Fügen Sie die Bibliothek zur `build.gradle`-Datei Ihres Moduls hinzu, wie hier gezeigt (für die aktuelle Version des IVS-Broadcast-SDK):

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

**Verwendung von Gradle-Versionskatalogen**: Fügen Sie zunächst Folgendes in die `build.gradle`-Datei Ihres Moduls ein:

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

Fügen Sie anschließend Folgendes in die `libs.version.toml`-Datei ein (für die aktuelle Version des IVS-Broadcast-SDK):

```
[versions]
ivs="1.40.0"

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

**Manuelle Installation des SDK**: Laden Sie die aktuelle Version von diesem Speicherort herunter:

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

Laden Sie unbedingt die `aar` mit `-stages` angehängt herunter.

**Außerdem die Kontrolle der Freisprecheinrichtung durch das SDK zulassen**: Unabhängig davon, welche Installationsmethode Sie wählen, fügen Sie Ihrem Manifest auch die folgende Berechtigung hinzu, damit das SDK die Freisprecheinrichtung aktivieren und deaktivieren kann:

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

## Verwenden des SDK mit Debug-Symbolen
<a name="broadcast-android-using-debug-symbols-rt"></a>

Wir veröffentlichen auch eine Version des Android-Broadcast-SDK, die Debug-Symbole enthält. Sie können diese Version verwenden, um die Qualität von Debug-Berichten (Stack-Traces) in Firebase Crashlytics zu verbessern, falls im IVS-Broadcast-SDK Abstürze auftreten, d. h. `libbroadcastcore.so`. Wenn Sie diese Abstürze dem SDK-Team von IVS melden, erleichtern die qualitativ hochwertigeren Stack-Traces die Behebung der Probleme.

Um diese Version des SDK zu verwenden, fügen Sie Folgendes in Ihre Gradle-Build-Dateien ein:

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

Verwenden Sie die obige Zeile anstelle von:

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

### Hochladen von Symbolen zu Firebase Crashlytics
<a name="android-debug-symbols-rt-firebase-crashlytics"></a>

Stellen Sie sicher, dass Ihre Gradle-Build-Dateien für Firebase Crashlytics eingerichtet sind. Folgen Sie den Anweisungen von Google hier:

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

Achten Sie darauf, `com.google.firebase:firebase-crashlytics-ndk` als Abhängigkeit anzugeben.

Wenn Sie Ihre App für die Veröffentlichung erstellen, muss das Firebase-Crashlytics-Plugin Symbole automatisch hochladen. Führen Sie einen der folgenden Befehle aus, um Symbole manuell hochzuladen:

```
gradle uploadCrashlyticsSymbolFileRelease
```

```
./gradlew uploadCrashlyticsSymbolFileRelease
```

(Es schadet nicht, wenn Symbole zweimal hochgeladen werden, sowohl automatisch als auch manuell.)

### Verhindern, dass Ihre APK-Version größer wird
<a name="android-debug-symbols-rt-sizing-apk"></a>

Vor dem Verpacken der `.apk`-Release-Datei versucht das Android-Gradle-Plugin automatisch, Debug-Informationen aus gemeinsam genutzten Bibliotheken (einschließlich der `libbroadcastcore.so`-Bibliothek des IVS-Broadcast-SDK) zu entfernen. Manchmal geschieht dies jedoch nicht. Infolgedessen könnte Ihre `.apk`-Datei größer werden und Sie könnten vom Android-Gradle-Plugin eine Warnmeldung erhalten, dass es Debug-Symbole nicht entfernen kann und die `.so`-Dateien unverändert verpackt. Wenn dies passiert, gehen Sie wie folgt vor:
+ Installieren Sie ein Android-NDK. Jede aktuelle Version funktioniert.
+ Fügen Sie `ndkVersion <your_installed_ndk_version_number>` zur `build.gradle`-Datei Ihrer Anwendung hinzu. Tun Sie dies auch dann, wenn Ihre Anwendung selbst keinen nativen Code enthält.

Weitere Informationen finden Sie in diesem [Problembericht](https://issuetracker.google.com/issues/353554169).

## Berechtigungen anfordern
<a name="broadcast-android-permissions"></a>

Ihre App muss die Berechtigung für den Zugriff auf die Kamera und das Mikrofon des Benutzers anfordern. (Dies ist nicht spezifisch für Amazon IVS; es ist für alle Anwendungen erforderlich, die Zugriff auf Kameras und Mikrofone benötigen.)

Hier prüfen wir, ob der Benutzer bereits Berechtigungen erteilt hat und fragen, wenn nicht, nach ihnen:

```
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;
    }
}
```

Hier erhalten wir die Antwort des Benutzers:

```
@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();
    }
}
```

# Veröffentlichen und Abonnieren mit dem IVS Android Broadcast SDK \$1 Streaming in Echtzeit
<a name="android-publish-subscribe"></a>

Dieses Dokument führt Sie durch die Schritte zum Veröffentlichen und Abonnieren einer Stufe mit dem Android Broadcast SDK von IVS-Streaming in Echtzeit.

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

Drei Kernkonzepte liegen der Echtzeit-Funktionalität zugrunde: [Stage](#android-publish-subscribe-concepts-stage), [Strategie](#android-publish-subscribe-concepts-strategy) und [Renderer](#android-publish-subscribe-concepts-renderer). Das Designziel besteht in der Minimierung der Menge an clientseitiger Logik, die für die Entwicklung eines funktionierenden Produkts erforderlich ist.

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

Die Klasse `Stage` ist der Hauptinteraktionspunkt zwischen der Hostanwendung und dem SDK. Sie stellt die Stage selbst dar und dient dazu, der Stage beizutreten und sie zu verlassen. Für das Erstellen einer Bühne und das Beitreten ist eine gültige, noch nicht abgelaufene Token-Zeichenfolge aus der Steuerebene erforderlich (dargestellt als `token`). Einer Bühne beizutreten und sie zu verlassen, ist ganz einfach. 

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

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

stage.leave();
```

In der Klasse `Stage` erfolgt auch das Anhängen des `StageRenderer`:

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

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

Über die Schnittstelle `Stage.Strategy` kann die Hostanwendung dem SDK den gewünschten Status der Bühne mitteilen. Drei Funktionen müssen implementiert werden: `shouldSubscribeToParticipant`, `shouldPublishFromParticipant` und `stageStreamsToPublishForParticipant`. Alle werden im Folgenden behandelt.

#### Abonnieren von Teilnehmern
<a name="android-publish-subscribe-concepts-strategy-participants"></a>

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

Wenn ein Remote-Teilnehmer der Stage beitritt, fragt das SDK die Hostanwendung nach dessen gewünschtem Abonnementstatus. Die Optionen lauten `NONE`, `AUDIO_ONLY` und `AUDIO_VIDEO`. Wenn ein Wert für diese Funktion zurückgegeben wird, muss sich die Hostanwendung nicht um den Veröffentlichungs-, den aktuellen Abonnement- oder den Verbindungsstatus des Stage kümmern. Bei Rückgabe von `AUDIO_VIDEO` wartet das SDK mit dem Abonnieren, bis der Remote-Teilnehmer etwas veröffentlicht. Außerdem aktualisiert das SDK die Hostanwendung während des gesamten Prozesses über den Renderer.

Hier folgt ein Beispiel für eine Implementierung:

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

Hierbei handelt es sich um die vollständige Implementierung dieser Funktion für eine Hostanwendung, bei der sich alle Teilnehmer stets gegenseitig sehen sollen; z. B. eine Video-Chat-Anwendung.

Weitergehende Implementierungen sind ebenfalls möglich. Nutzen Sie die Eigenschaft `userInfo` für `ParticipantInfo`, um Teilnehmer anhand der vom Server bereitgestellten Attribute selektiv zu abonnieren:

```
@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;
	}
}
```

Hiermit kann eine Bühne erstellt werden, auf der Moderatoren alle Gäste überwachen können, ohne selbst gesehen oder gehört zu werden. Die Hostanwendung könnte eine zusätzliche Geschäftslogik nutzen, damit Moderatoren sich gegenseitig sehen können, für Gäste aber unsichtbar bleiben.

#### Konfiguration für das Abonnieren von Teilnehmern
<a name="android-publish-subscribe-concepts-strategy-participants-config"></a>

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

Wenn ein Remote-Teilnehmer abonniert wird (siehe [Teilnehmer abonnieren](#android-publish-subscribe-concepts-strategy-participants)), fragt das SDK die Host-Anwendung nach einer benutzerdefinierten Abonnementkonfiguration für diesen Teilnehmer ab. Diese Konfiguration ist optional und ermöglicht es der Hostanwendung, bestimmte Aspekte des Subscriber-Verhaltens zu steuern. Informationen darüber, was konfiguriert werden kann, finden Sie unter [SubscribeConfiguration](https://aws.github.io/amazon-ivs-web-broadcast/docs/sdk-reference/interfaces/SubscribeConfiguration) in der SDK-Referenzdokumentation.

Hier folgt ein Beispiel für eine Implementierung:

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

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

    return config;
}
```

Diese Implementierung aktualisiert die Mindestverzögerung für den Jitter-Buffer für alle abonnierten Teilnehmer auf die Voreinstellung `MEDIUM`.

Wie bei `shouldSubscribeToParticipant` sind auch hier weitergehende Implementierungen möglich. Die `ParticipantInfo`-Angaben können verwendet werden, um die Abonnementkonfiguration für bestimmte Teilnehmer selektiv zu aktualisieren.

Wir empfehlen die Verwendung der Standardverhaltensweisen. Geben Sie die benutzerdefinierte Konfiguration nur an, wenn Sie ein bestimmtes Verhalten ändern möchten.

#### Veröffentlichen
<a name="android-publish-subscribe-concepts-strategy-publishing"></a>

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

Sobald die Verbindung zur Stage hergestellt ist, überprüft das SDK per Anfrage an die Hostanwendung, ob ein bestimmter Teilnehmer etwas veröffentlichen soll. Dies wird nur bei lokalen Teilnehmern aufgerufen, die auf Grundlage des bereitgestellten Tokens zur Veröffentlichung berechtigt sind.

Hier folgt ein Beispiel für eine Implementierung:

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

Sie ist für eine normale Video-Chat-Anwendung gedacht, bei der Benutzer immer etwas veröffentlichen möchten. Sie können die Audio- und Videowiedergabe stummschalten und die Stummschaltung aufheben, um umgehend ausgeblendet oder gesehen/gehört zu werden. (Sie können auch „Veröffentlichen/Veröffentlichung aufheben“ verwenden, was aber viel langsamer ist. „Stummschalten/Stummschalten aufheben“ ist für Anwendungsfälle vorzuziehen, in denen eine häufige Änderung der Sichtbarkeit wünschenswert ist.)

#### Auswählen von Streams zur Veröffentlichung
<a name="android-publish-subscribe-concepts-strategy-streams"></a>

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

Beim Veröffentlichen wird hiermit bestimmt, welche Audio- und Videostreams veröffentlicht werden sollen. Dieser Punkt wird später unter [Veröffentlichen eines Medienstreams](#android-publish-subscribe-publish-stream) ausführlicher behandelt.

#### Aktualisieren der Strategie
<a name="android-publish-subscribe-concepts-strategy-updates"></a>

Die Strategie soll dynamisch sein: Die von einer der oben genannten Funktionen zurückgegebenen Werte lassen sich jederzeit ändern. Wenn die Hostanwendung beispielsweise erst veröffentlichen soll, wenn der Endbenutzer auf eine Schaltfläche tippt, können Sie eine Variable aus `shouldPublishFromParticipant` zurückgeben (zum Beispiel `hasUserTappedPublishButton`). Wenn sich diese Variable aufgrund einer Interaktion des Endbenutzers ändert, signalisieren Sie dem SDK per Aufruf von `stage.refreshStrategy()`, dass es die Strategie nach den neuesten Werten abfragen und nur Dinge anwenden soll, die sich geändert haben. Wenn das SDK feststellt, dass sich der Wert `shouldPublishFromParticipant` geändert hat, startet es den Veröffentlichungsprozess. Wenn alle Funktionen bei einer SDK-Abfrage den gleichen Wert zurückgeben wie zuvor, werden mit dem Aufruf von `refreshStrategy` keine Änderungen an der Bühne durchgeführt.

Ändert sich der Rückgabewert von `shouldSubscribeToParticipant` von `AUDIO_VIDEO` in `AUDIO_ONLY`, wird der Videostream für alle Teilnehmer mit geänderten Rückgabewerten entfernt, sofern zuvor ein Videostream vorhanden war.

Im Allgemeinen nutzt die Stage die Strategie, um den Unterschied zwischen der vorherigen und der aktuellen Strategie am effizientesten anzuwenden. Dabei muss sich die Hostanwendung nicht um die ganzen Status kümmern, die für eine ordnungsgemäße Verwaltung erforderlich sind. Stellen Sie sich den Aufruf von `stage.refreshStrategy()` daher als einen ressourcenschonenden Vorgang vor, da nur bei einer Änderung der Strategie etwas unternommen wird.

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

Die Schnittstelle `StageRenderer` teilt der Hostanwendung den Status der Bühne mit. Aktualisierungen in der Benutzeroberfläche der Hostanwendung können in der Regel vollständig über die vom Renderer bereitgestellten Ereignisse gesteuert werden. Der Renderer stellt die folgenden Funktionen bereit:

```
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);
```

Für die meisten dieser Methoden werden die entsprechende `Stage` und `ParticipantInfo` bereitgestellt.

Es wird nicht erwartet, dass sich die vom Renderer bereitgestellten Informationen auf die Rückgabewerte der Strategie auswirken. Es wird beispielsweise nicht erwartet, dass sich der Rückgabewert von `shouldSubscribeToParticipant` beim Aufruf von `onParticipantPublishStateChanged` ändert. Wenn die Hostanwendung einen bestimmten Teilnehmer abonnieren möchte, muss sie unabhängig von dessen Veröffentlichungsstatus den gewünschten Abonnementtyp zurückgeben. Das SDK muss dafür sorgen, dass entsprechend dem Status der Bühne und dem gewünschten Status der Strategie zum richtigen Zeitpunkt gehandelt wird.

Der `StageRenderer` kann der Bühnenklasse angefügt werden:

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

Hinweis: Nur veröffentlichende Teilnehmer lösen `onParticipantJoined` aus. Wenn Teilnehmer die Veröffentlichung beenden oder die Bühnensitzung verlassen, wird `onParticipantLeft` ausgelöst.

## Veröffentlichen eines Medienstreams
<a name="android-publish-subscribe-publish-stream"></a>

Lokale Geräte wie eingebaute Mikrofone und Kameras werden über `DeviceDiscovery` erkannt. Hier folgt ein Beispiel für die Auswahl der nach vorne gerichteten Kamera und des Standardmikrofons und deren anschließende Rückgabe als `LocalStageStreams` zur Veröffentlichung durch das 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;
}
```

## Anzeigen und Entfernen von Teilnehmern
<a name="android-publish-subscribe-participants"></a>

Nach Abschluss von Abonnements erhalten Sie über die Funktion `onStreamsAdded` des Renderers eine Reihe von `StageStream`-Objekten. Sie können die Vorschau von einem `ImageStageStream` abrufen:

```
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);
```

Außerdem können Sie die Statistiken des Audiolevels von einem `AudioStageStream` abrufen:

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

Wenn ein Teilnehmer die Veröffentlichung beendet oder dessen Abonnement beendet wird, wird die Funktion `onStreamsRemoved` mit den Streams aufgerufen, die entfernt wurden. Hostanwendungen sollten dies als Signal nutzen, um den Videostream des Teilnehmers aus der Ansichtshierarchie zu entfernen.

`onStreamsRemoved` wird für alle Szenarien aufgerufen, in denen ein Stream entfernt werden könnte, darunter: 
+ Der Remote-Teilnehmer beendet die Veröffentlichung.
+ Ein lokales Gerät beendet das Abonnement oder ändert das Abonnement von `AUDIO_VIDEO` in `AUDIO_ONLY`.
+ Der Remote-Teilnehmer verlässt die Stage.
+ Der lokale Teilnehmer verlässt die Stage.

Da `onStreamsRemoved` bei allen Szenarien aufgerufen wird, ist keine benutzerdefinierte Geschäftslogik erforderlich, um Teilnehmer beim remoten oder lokalen Verlassen aus der Benutzeroberfläche zu entfernen.

## Stummschalten von Medienstreams und Aufheben der Stummschaltung
<a name="android-publish-subscribe-mute-streams"></a>

`LocalStageStream`-Objekte verfügen über eine `setMuted`-Funktion, die das Stummschalten des Streams steuert. Diese Funktion kann für den Stream aufgerufen werden, bevor oder nachdem er von der Strategiefunktion `streamsToPublishForParticipant` zurückgegeben wird.

**Wichtig**: Wenn nach einem Aufruf von `refreshStrategy` eine neue `LocalStageStream`-Objekt-Instance von `streamsToPublishForParticipant` zurückgegeben wird, wird der Stummschaltungsstatus des neuen Streamobjekts auf die Bühne angewendet. Seien Sie vorsichtig beim Erstellen neuer `LocalStageStream`-Instances, um sicherzustellen, dass der erwartete Stummschaltungsstatus beibehalten wird.

## Überwachen des Medien-Stummschaltungsstatus von Remote-Teilnehmern
<a name="android-publish-subscribe-mute-state"></a>

Wenn ein Teilnehmer den Stummschaltungsstatus seines Video- oder Audiostreams ändert, wird die Funktion `onStreamMutedChanged` des Renderers mit einer Liste der Streams aufgerufen, die sich geändert haben. Verwenden Sie die Methode `getMuted` für `StageStream`, um die Benutzeroberfläche entsprechend zu aktualisieren. 

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

## Abrufen von WebRTC-Statistiken
<a name="android-publish-subscribe-webrtc-stats"></a>

Um die neuesten WebRTC-Statistiken für einen veröffentlichten oder abonnierten Stream abzurufen, verwenden Sie `requestRTCStats` für `StageStream`. Nach Abschluss einer Erfassung erhalten Sie Statistiken über den `StageStream.Listener`, der für `StageStream` eingestellt werden kann.

```
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());
		}
	}
}
```

## Abrufen von Teilnehmerattributen
<a name="android-publish-subscribe-participant-attributes"></a>

Wenn Sie Attribute in der Vorgangsanfrage `CreateParticipantToken` angeben, können Sie die Attribute in den Eigenschaften von `ParticipantInfo` einsehen:

```
@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());
	}
}
```

## Eingebettete Nachrichten
<a name="android-publish-subscribe-embed-messages"></a>

Die `embedMessage`-Methode auf ImageDevice ermöglicht es Ihnen, Metadaten-Nutzdaten während der Veröffentlichung direkt in Videoframes einzufügen. Dies ermöglicht framesynchronisiertes Messaging für Echtzeitanwendungen. Das Einbetten von Nachrichten ist nur verfügbar, wenn das SDK für die Veröffentlichung in Echtzeit verwendet wird (nicht für Veröffentlichungen mit niedriger Latenz).

Es kann nicht garantiert werden, dass eingebettete Nachrichten bei Abonnenten ankommen, da sie direkt in Videoframes eingebettet und über UDP übertragen werden, wodurch die Paketzustellung nicht garantiert wird. Der Verlust von Paketen während der Übertragung kann zum Verlust von Nachrichten führen, insbesondere bei schlechten Netzwerkbedingungen. Um dem entgegenzuwirken, beinhaltet die `embedMessage`-Methode einen `repeatCount`-Parameter, der die Nachricht über mehrere aufeinanderfolgende Frames dupliziert und so die Zuverlässigkeit der Zustellung erhöht. Diese Funktion ist nur für Videostreams verfügbar.

### Verwenden von embedMessage
<a name="android-embed-messages-using-embedmessage"></a>

Publishing-Clients können Nachrichten-Nutzdaten mithilfe der `embedMessage`-Methode auf ImageDevice in ihren Videostream einbetten. Die Nutzdaten müssen größer als 0 KB und kleiner als 1 KB sein. Die Anzahl der pro Sekunde eingebetteten Nachrichten darf 10 KB pro Sekunde nicht überschreiten. 

```
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}")
}
```

### Nachrichten-Nutzdaten
<a name="android-embed-messages-repeat-payloads"></a>

Verwenden Sie `repeatCount`, um die Nachricht über mehrere Frames hinweg zu duplizieren, um die Zuverlässigkeit zu erhöhen. Dieser Wert muss zwischen 0 und 30 liegen. Empfangende Clients müssen über eine Logik verfügen, um die Nachricht zu deduplizieren.

```
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}")
}
```

### Lesen eingebetteter Nachrichten
<a name="android-embed-messages-read-messages"></a>

Informationen zum Lesen eingebetteter Nachrichten aus eingehenden Streams finden Sie weiter unten unter „Zusätzliche Erweiterungsinformationen (SEI) abrufen“.

## Abrufen von SEI-Daten (Supplemental Enhancement Information)
<a name="android-publish-subscribe-sei-attributes"></a>

Die NAL-Einheit für Supplemental Enhancement Information (SEI) wird verwendet, um Frame-orientierte Metadaten zusammen mit dem Video zu speichern. Subscriber können SEI-Nutzlasten von einem Publisher lesen, der H.264-Video veröffentlicht, indem sie die Eigenschaften `embeddedMessages` der `ImageDeviceFrame`-Objekte aus dem `ImageDevice` des Publishers überprüfen. Erlangen Sie dazu das `ImageDevice` eines Publishers und beobachten Sie dann jeden Frame über einen Callback an `setOnFrameCallback`, wie im folgenden Beispiel gezeigt:

```
// 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
        		}
    		}
	}
})
```

## Fortsetzen der Sitzung im Hintergrund
<a name="android-publish-subscribe-background-session"></a>

Wenn die App in den Hintergrund wechselt, können Sie die Veröffentlichung beenden oder das Abonnement auf das Audio anderer Remote-Teilnehmer beschränken. Dazu aktualisieren Sie die Implementierung Ihrer `Strategy`, um die Veröffentlichung zu beenden und `AUDIO_ONLY` zu abonnieren (oder gegebenenfalls `NONE`).

```
// 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();
}
```

## Mehrschichtige Kodierung mit Simulcast
<a name="android-publish-subscribe-layered-encoding-simulcast"></a>

Bei der mehrschichtigen Kodierung mit Simulcast handelt es sich um ein Feature für IVS-Echtzeit-Streaming, mit dessen Hilfe Publisher mehrere Videoschichten unterschiedlicher Qualität senden können. Subscriber können diese Schichten dynamisch oder manuell konfigurieren. Das Feature wird im Dokument [Streaming-Optimierungen](real-time-streaming-optimization.md) ausführlicher beschrieben.

### Konfigurieren mehrschichtiger Kodierung (Publisher)
<a name="android-layered-encoding-simulcast-configure-publisher"></a>

Um als Publisher die mehrschichtige Kodierung mit Simulcast zu aktivieren, fügen Sie dem `LocalStageStream` bei der Instanziierung die folgende Konfiguration hinzu:

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

ImageLocalStageStream cameraStream = new ImageLocalStageStream(frontCamera, config);

// Other Stage implementation code
```

Je nach der in der Videokonfiguration eingestellten Auflösung wird eine festgelegte Anzahl von Schichten kodiert und gesendet, wie im Abschnitt [Standardmäßige Schichten, Qualitäten und Bildraten](real-time-streaming-optimization.md#real-time-streaming-optimization-default-layers) von *Streaming-Optimierungen* definiert.

Außerdem können Sie optional einzelne Ebenen innerhalb der Simulcast-Konfiguration konfigurieren: 

```
// 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
```

Alternativ können Sie eigene benutzerdefinierte Ebenenkonfigurationen für bis zu drei Ebenen erstellen. Wenn Sie ein leeres Array oder keinen Wert angeben, werden die oben beschriebenen Standardwerte verwendet. Ebenen werden mit den folgenden erforderlichen Eigenschaftssetzern beschrieben:
+ `setSize: Vec2;`
+ `setMaxBitrate: integer;`
+ `setMinBitrate: integer;`
+ `setTargetFramerate: integer;`

Ausgehend von den Voreinstellungen können Sie entweder einzelne Eigenschaften überschreiben oder eine völlig neue Konfiguration erstellen:

```
// 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
```

Informationen zu Höchstwerten, Grenzwerten und Fehlern, die bei der Konfiguration einzelner Ebenen ausgelöst werden können, finden Sie in der SDK-Referenzdokumentation.

### Konfigurieren mehrschichtiger Kodierung (Subscriber)
<a name="android-layered-encoding-simulcast-configure-subscriber"></a>

Subscriber müssen nichts unternehmen, um die mehrschichtige Kodierung zu aktivieren. Wenn ein Publisher Simulcast-Schichten sendet, passt sich der Server standardmäßig dynamisch den Schichten an, um je nach Gerät und Netzwerkbedingungen des Subscribers die optimale Qualität auszuwählen.

Alternativ gibt es mehrere nachfolgend beschriebene Optionen, um explizite Schichten auszuwählen, die der Publisher sendet.

### Option 1: Einstellung für die Qualität der Anfangsschicht
<a name="android-layered-encoding-simulcast-layer-quality-preference"></a>

Mit der Strategie `subscribeConfigurationForParticipant` können Sie auswählen, welche Anfangsschicht Sie als Subscriber erhalten möchten:

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

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

    return config;
}
```

Standardmäßig wird Subscribern zunächst immer die Schicht mit der niedrigsten Qualität gesendet. Nach und nach wird die Qualität gesteigert, bis die Schicht mit der höchsten Qualität erreicht ist. Das optimiert den Bandbreitenverbrauch der Endbenutzer, verkürzt die Zeit bis zum Abspielen des Videos und verringert das anfängliche Einfrieren von Videos bei Benutzern in Netzwerken mit geringerer Bandbreite.

Folgende Optionen sind für `InitialLayerPreference` verfügbar:
+ `LOWEST_QUALITY` – Der Server stellt zuerst die Videoschicht mit der niedrigsten Qualität bereit. Dadurch werden der Bandbreitenverbrauch und die Zeit bis zum Abspielen von Medien optimiert. Die Qualität ist definiert als die Kombination aus Größe, Bitrate und Bildrate des Videos. Beispielsweise weisen 720p-Videos eine geringere Qualität auf als 1080p-Videos.
+ `HIGHEST_QUALITY` – Der Server stellt zuerst die Videoschicht mit der höchsten Qualität bereit. Das optimiert die Qualität, kann aber die Zeit bis zum Abspielen von Medien verlängern. Die Qualität ist definiert als die Kombination aus Größe, Bitrate und Bildrate des Videos. Beispielsweise weisen 1080p-Videos eine höhere Qualität auf als 720p-Videos.

**Hinweis:** Damit die anfänglichen Schichteinstellungen (der Aufruf `setInitialLayerPreference`) wirksam werden, muss ein neues Abonnement abgeschlossen werden, da diese Updates für das aktive Abonnement nicht gelten.

### Option 2: Bevorzugte Schicht für Streams
<a name="android-layered-encoding-simulcast-preferred-layer"></a>

Mit der Strategiemethode `preferredLayerForStream` können Sie eine Schicht auswählen, nachdem der Stream gestartet wurde. Diese Strategiemethode erhält die Teilnehmer- und Streaminformationen, sodass Sie eine Schicht für jeden Teilnehmer auswählen können. Das SDK ruft diese Methode als Reaktion auf bestimmte Ereignisse auf, z. B. wenn sich die Streamschichten ändern, sich der Teilnehmerstatus ändert oder die Hostanwendung die Strategie aktualisiert.

Der Strategiemodus gibt ein `RemoteStageStream.Layer`-Objekt zurück, wobei es sich um Folgendes handeln kann:
+ ein Schichtobjekt, z. B. eines, das von `RemoteStageStream.getLayers` zurückgegeben wird
+ null, was bedeutet, dass keine Schicht ausgewählt werden sollte und eine dynamische Anpassung bevorzugt wird

Bei der folgenden Strategie wählen die Benutzer beispielsweise immer die Videoschicht mit der niedrigsten verfügbaren Qualität aus:

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

Um die Schichtauswahl zurückzusetzen und zur dynamischen Anpassung zurückzukehren, geben Sie in der Strategie null oder undefiniert zurück. In diesem Beispiel ist `appState` eine Platzhaltervariable, die den Status der Hostanwendung darstellt.

```
@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: Helferobjekte für RemoteStageStream-Schicht
<a name="android-layered-encoding-simulcast-remotestagestream-helpers"></a>

`RemoteStageStream` weist mehrere Helferobjekte auf, mit deren Hilfe Entscheidungen über die Schichtauswahl getroffen und Endbenutzern die entsprechende Auswahl angezeigt werden kann:
+ **Schichtereignisse** – Neben `StageRenderer` verfügt der `RemoteStageStream.Listener` über Ereignisse, die Änderungen bei der Schicht- und Simulcast-Anpassung kommunizieren:
  + `void onAdaptionChanged(boolean adaption)`
  + `void onLayersChanged(@NonNull List<Layer> layers)`
  + `void onLayerSelected(@Nullable Layer layer, @NonNull LayerSelectedReason reason)`
+ **Schichtmethoden** – `RemoteStageStream` verfügt über mehrere Helfermethoden, mit denen Informationen über den Stream und die präsentierten Schichten abgerufen werden können. Diese Methoden sind sowohl für den in der Strategie `preferredLayerForStream` bereitgestellten Remote-Stream als auch für Remote-Streams verfügbar, die über `StageRenderer.onStreamsAdded` verfügbar gemacht werden.
  + `stream.getLayers`
  + `stream.getSelectedLayer`
  + `stream.getLowestQualityLayer`
  + `stream.getHighestQualityLayer`
  + `stream.getLayersWithConstraints`

Einzelheiten finden Sie im Abschnitt zur Klasse `RemoteStageStream` in der [SDK-Referenzdokumentation](https://aws.github.io/amazon-ivs-broadcast-docs/latest/android/). Falls als Grund für `LayerSelected` `UNAVAILABLE` zurückgegeben wird, bedeutet das, dass die angeforderte Schicht nicht ausgewählt werden konnte. Stattdessen wird eine bestmögliche Auswahl getroffen. Dabei handelt es sich in der Regel um eine Schicht mit niedrigerer Qualität, um die Stabilität des Streams zu gewährleisten.

## Einschränkungen der Videokonfiguration
<a name="android-publish-subscribe-video-limits"></a>

Das SDK unterstützt kein Erzwingen des Hoch- oder Querformats mit `StageVideoConfiguration.setSize(BroadcastConfiguration.Vec2 size)`. Im Hochformat wird die kleinere Dimension als Breite verwendet, im Querformat als Höhe. Das bedeutet, dass die folgenden beiden Aufrufe von `setSize` die gleiche Auswirkung auf die Videokonfiguration haben:

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

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

## Umgang mit Netzwerkproblemen
<a name="android-publish-subscribe-network-issues"></a>

Bei Unterbrechung der Netzwerkverbindung des lokalen Geräts versucht das SDK intern, die Verbindung ohne Benutzeraktion wiederherzustellen. In einigen Fällen ist das SDK nicht erfolgreich, weshalb eine Benutzeraktion erforderlich ist. Es gibt zwei Hauptfehler im Zusammenhang mit der Unterbrechung der Netzwerkverbindung:
+ Fehlercode 1400, Meldung: „Die PeerConnection wurde aufgrund eines unbekannten Netzwerkfehlers unterbrochen.“
+ Fehlercode 1300, Meldung: „Die Zahl der Wiederholungsversuche ist ausgeschöpft.“

Wenn der erste Fehler empfangen wird, der zweite jedoch nicht, ist das SDK immer noch mit der Bühne verbunden und versucht, die Verbindungen automatisch wiederherzustellen. Zur Sicherheit können Sie `refreshStrategy` ohne Änderungen an den Rückgabewerten der Strategiemethode aufrufen, um einen manuellen Neuverbindungsversuch auszulösen.

Wenn der zweite Fehler empfangen wird, sind die Neuverbindungsversuche des SDK fehlgeschlagen und das lokale Gerät ist nicht mehr mit der Bühne verbunden. Versuchen Sie in diesem Fall, der Bühne erneut beizutreten, indem Sie `join` aufrufen, nachdem die Netzwerkverbindung wiederhergestellt wurde.

Im Allgemeinen deutet das Auftreten von Fehlern nach dem erfolgreichen Beitritt zu einer Bühne darauf hin, dass das SDK beim Wiederherstellen einer Verbindung nicht erfolgreich war. Erstellen Sie ein neues `Stage`-Objekt und versuchen Sie, der Bühne beizutreten, wenn sich die Netzwerkbedingungen verbessern.

## Verwenden von Bluetooth-Mikrofonen
<a name="android-publish-subscribe-bluetooth-microphones"></a>

Um mit Bluetooth-Mikrofongeräten zu veröffentlichen, müssen Sie eine Bluetooth-SCO-Verbindung herstellen:

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

# Bekannte Probleme und Behelfslösungen im IVS Android Broadcast SDK \$1 Streaming in Echtzeit
<a name="broadcast-android-known-issues"></a>

In diesem Dokument werden bekannte Probleme aufgeführt, die bei der Verwendung des Android Broadcast SDK von Amazon-IVS-Streaming in Echtzeit auftreten können, und es werden mögliche Problemumgehungen vorgeschlagen.
+ Wenn ein Android-Gerät in den Ruhezustand wechselt und aufwacht, befindet sich die Vorschau möglicherweise in einem eingefrorenen Zustand.

  **Problemumgehung:** Erstellen und nutzen Sie eine neue `Stage`.
+ Wenn ein Teilnehmer mit einem Token beitritt, das von einem anderen Teilnehmer verwendet wird, wird die erste Verbindung ohne einen bestimmten Fehler getrennt.

  **Problemumgehung:** Keine. 
+ Es gibt ein seltenes Problem, bei dem der Publisher etwas veröffentlicht, der Veröffentlichungsstatus, den Subscriber erhalten, jedoch `inactive` lautet.

  **Problemumgehung:** Versuchen Sie, die Sitzung zu verlassen und ihr wieder beizutreten. Wenn das Problem weiterhin besteht, erstellen Sie ein neues Token für den Publisher.
+ Während einer Bühnensitzung kann zeitweise ein seltenes Problem mit Tonverzerrungen auftreten, in der Regel bei längeren Anrufen.

  **Problemumgehung:** Der Teilnehmer mit dem verzerrtem Ton kann die Sitzung entweder verlassen und erneut beitreten oder die Veröffentlichung des Audios aufheben und dann erneut veröffentlichen.
+ Externe Mikrofone werden bei der Veröffentlichung auf einer Bühne nicht unterstützt.

  **Problemumgehung:** Verwenden Sie kein über USB angeschlossenes externes Mikrofon, um etwas auf einer Bühne zu veröffentlichen.
+ Das Veröffentlichen auf einer Bühne mit der Bildschirmfreigabe über `createSystemCaptureSources` wird nicht unterstützt.

  **Problemumgehung:** Verwalten Sie die Systemerfassung manuell, indem Sie benutzerdefinierte Bild- und Audioeingangsquellen verwenden.
+ Wenn eine `ImagePreviewView` in einem übergeordneten Element entfernt wird (`removeView()` wird z. B. im übergeordneten Element aufgerufen), wird die `ImagePreviewView` sofort freigegeben. Die `ImagePreviewView` zeigt keine Frames an, wenn sie einer anderen übergeordneten Ansicht hinzugefügt wird.

  **Problemumgehung:** Fordern Sie mit `getPreview` eine andere Vorschau an.
+ Beim Beitritt zu einer Bühne mit einem Samsung Galaxy S22/\$1 mit Android 12 tritt möglicherweise ein 1401-Fehler auf. Das lokale Gerät kann der Bühne nicht beitreten oder tritt ihr bei, hat aber keinen Ton.

  **Problemumgehung:** Führen Sie ein Upgrade auf Android 13 durch.
+ Beim Beitritt zu einer Bühne mit einem Nokia X20 unter Android 13 lässt sich die Kamera möglicherweise nicht öffnen und es wird eine Ausnahme ausgelöst.

  **Problemumgehung:** Keine.
+ Geräte mit dem MediaTek-Helio-Chipsatz können Videos von Remote-Teilnehmern nicht richtig wiedergeben.

  **Problemumgehung:** Keine.
+ Auf einigen Geräten wählt das Betriebssystem möglicherweise ein anderes Mikrofon als das, das im SDK ausgewählt wurde. Das liegt daran, dass das Amazon IVS Broadcast SDK nicht steuern kann, wie die Audioroute `VOICE_COMMUNICATION` definiert wird, da sie je nach Gerätehersteller unterschiedlich ist.

  **Problemumgehung:** Keine.
+ Einige Android-Videoencoder können nicht mit einer Videogröße von weniger als 176 × 176 konfiguriert werden. Die Konfiguration einer kleineren Größe verursacht einen Fehler und verhindert das Streaming.

  **Problemumgehung:** Konfigurieren Sie die Videogröße nicht auf weniger als 176 × 176.

# Fehlerbehandlung im IVS Android Broadcast SDK \$1 Streaming in Echtzeit
<a name="broadcast-android-error-handling"></a>

Dieser Abschnitt gibt einen Überblick über die Fehlerbedingungen, wie das Android Broadcast SDK von IVS-Streaming in Echtzeit sie an die Anwendung meldet und wie eine Anwendung reagieren sollte, wenn diese Fehler auftreten.

## Schwerwiegende und nicht schwerwiegende Fehler
<a name="broadcast-android-fatal-vs-nonfatal-errors"></a>

Das Fehlerobjekt hat das boolesche Feld „ist fatal“ von `BroadcastException`.

Im Allgemeinen hängen schwerwiegende Fehler mit der Verbindung zum Stages-Server zusammen (entweder kann eine Verbindung nicht hergestellt werden oder sie ist verloren gegangen und kann nicht wiederhergestellt werden). Die Anwendung sollte die Stage neu erstellen und erneut beitreten, ggf. mit einem neuen Token oder wenn die Konnektivität des Geräts wiederhergestellt ist.

Fehler, die nicht schwerwiegend sind, hängen in der Regel mit dem Status „Veröffentlichen/Abonnieren“ zusammen und werden vom SDK behandelt, das den Vorgang zum Veröffentlichen/Abonnieren erneut versucht.

Sie können diese Eigenschaft überprüfen:

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

## Beitrittsfehler
<a name="broadcast-android-stage-join-errors"></a>

### Fehlerhaft formatiertes Token
<a name="broadcast-android-stage-join-errors-malformed-token"></a>

Dies passiert, wenn das Phasen-Token falsch formatiert ist.

Das SDK löst bei einem Aufruf von eine Java-Ausnahme mit dem Fehlercode = 1000 und fatal = true aus. `stage.join`

**Aktion**: Erstellen Sie ein gültiges Token und versuchen Sie erneut, Mitglied zu werden.

### Abgelaufenes Token
<a name="broadcast-android-stage-join-errors-expired-token"></a>

Dies passiert, wenn das Phasen-Token abgelaufen ist.

Das SDK löst bei einem Aufruf von eine Java-Ausnahme mit dem Fehlercode = 1001 und fatal = true aus. `stage.join`

**Aktion**: Erstellen Sie ein neues Token und versuchen Sie erneut, Mitglied zu werden.

### Ungültiges oder widerrufenes Token
<a name="broadcast-android-stage-join-errors-invalid-token"></a>

Dies passiert, wenn das Stage-Token nicht falsch formatiert ist, sondern vom Stages-Server zurückgewiesen wird. Dies wird asynchron über den von der Anwendung bereitgestellten Phasen-Renderer gemeldet.

Das SDK ruft `onConnectionStateChanged` mit einer Ausnahme auf, mit dem Fehlercode = 1026 und fatal = true.

**Aktion**: Erstellen Sie ein gültiges Token und versuchen Sie erneut beizutreten.

### Netzwerkfehler beim ersten Beitritt
<a name="broadcast-android-stage-join-errors-network-initial-join"></a>

Dies passiert, wenn das SDK den Stages-Server nicht kontaktieren kann, um eine Verbindung herzustellen. Dies wird asynchron über den von der Anwendung bereitgestellten Phasen-Renderer gemeldet.

Das SDK ruft `onConnectionStateChanged` mit einer Ausnahme auf, mit dem Fehlercode = 1300 und fatal = true.

**Handlung**: Warten Sie, bis die Konnektivität des Geräts wiederhergestellt ist, und versuchen Sie erneut, eine Verbindung herzustellen.

### Netzwerkfehler, wenn bereits eine Verbindung hergestellt wurde
<a name="broadcast-android-stage-join-errors-network-already-joined"></a>

Wenn die Netzwerkverbindung des Geräts ausfällt, verliert das SDK möglicherweise die Verbindung zu den Stage-Servern. Dies wird asynchron über den von der Anwendung bereitgestellten Phasen-Renderer gemeldet.

Das SDK ruft `onConnectionStateChanged` mit einer Ausnahme auf, mit dem Fehlercode = 1300 und fatal = true.

**Handlung**: Warten Sie, bis die Konnektivität des Geräts wiederhergestellt ist, und versuchen Sie erneut, eine Verbindung herzustellen.

## Fehler beim Veröffentlichen/Abonnieren
<a name="broadcast-android-publish-subscribe-errors"></a>

### Anfänglich
<a name="broadcast-android-publish-subscribe-errors-initial"></a>

Es gibt mehrere Arten von Fehlern:
+ MultihostSessionOfferCreationFailPublish (1.020)
+ MultihostSessionOfferCreationFailSubscribe (1.021)
+ MultihostSessionNoIceCandidates (1.022)
+ MultihostSessionStageAtCapacity (1.024)
+ SignallingSessionCannotRead (1.201)
+ SignallingSessionCannotSend (1.202)
+ SignallingSessionBadResponse (1.203)

Diese werden asynchron über den von der Anwendung bereitgestellten Stage-Renderer gemeldet.

Das SDK wiederholt den Vorgang für eine begrenzte Anzahl von Malen. Bei Wiederholungen ist der Status „Veröffentlichen/Abonnieren“ `ATTEMPTING_PUBLISH` / `ATTEMPTING_SUBSCRIBE`. Wenn die Wiederholungsversuche erfolgreich sind, ändert sich der Status auf `PUBLISHED` / `SUBSCRIBED`.

Das SDK ruft `onError` mit dem entsprechenden Fehlercode und fatal = false auf.

**Aktion**: Es ist keine Aktion erforderlich, da das SDK es automatisch wiederholt. Optional kann die Anwendung die Strategie aktualisieren, um weitere Wiederholungsversuche zu erzwingen.

### Bereits eingerichtet, dann gescheitert
<a name="broadcast-android-publish-subscribe-errors-established"></a>

Eine Veröffentlichung oder ein Abonnement kann nach der Einrichtung fehlschlagen, was höchstwahrscheinlich auf einen Netzwerkfehler zurückzuführen ist. Fehlercode 1400, Meldung: „Die Peer-Verbindung wurde aufgrund eines unbekannten Netzwerkfehlers unterbrochen.“

Dies wird asynchron über den von der Anwendung bereitgestellten Stage-Renderer gemeldet.

Das SDK versucht erneut, den Vorgang zu veröffentlichen/abonnieren. Bei Wiederholungen ist der Status „Veröffentlichen/Abonnieren“ `ATTEMPTING_PUBLISH` / `ATTEMPTING_SUBSCRIBE`. Wenn die Wiederholungsversuche erfolgreich sind, ändert sich der Status auf `PUBLISHED` / `SUBSCRIBED`.

Das SDK ruft `onError` mit dem Fehlercode = 1400 und fatal = false auf.

**Aktion**: Es ist keine Aktion erforderlich, da das SDK es automatisch wiederholt. Optional kann die Anwendung die Strategie aktualisieren, um weitere Wiederholungsversuche zu erzwingen. Im Falle eines vollständigen Verbindungsverlusts ist es wahrscheinlich, dass auch die Verbindung zu Stages fehlschlägt.