Werbeunterbrechungen
Das Android Sender SDK bietet Unterstützung für Werbeunterbrechungen und Companion-Anzeigen in einem bestimmten Media-Stream.
Weitere Informationen zur Funktionsweise von Werbeunterbrechungen finden Sie unter Web Receiver Ad Breaks Overview.
Pausen können sowohl auf dem Sender als auch auf dem Empfänger angegeben werden. Es wird jedoch empfohlen, sie auf dem Web Receiver und dem Android TV Receiver anzugeben, um ein einheitliches Verhalten auf allen Plattformen zu gewährleisten.
Geben Sie auf Android Werbeunterbrechungen in einem Ladebefehl mit AdBreakClipInfo
und AdBreakInfo
an:
val breakClip1: AdBreakClipInfo = AdBreakClipInfo.Builder("bc0") .setTitle("Clip title") .setPosterUrl("https://www.some.url") .setDuration(60000) .setWhenSkippableInMs(5000) // Set this field so that the ad is skippable .build() val breakClip2: AdBreakClipInfo = … val breakClip3: AdBreakClipInfo = … val break1: AdBreakClipInfo = AdBreakInfo.Builder(/* playbackPositionInMs= */ 10000) .setId("b0") .setBreakClipIds({"bc0","bc1","bc2"}) … .build() val mediaInfo: MediaInfo = MediaInfo.Builder() … .setAdBreaks({break1}) .setAdBreakClips({breakClip1, breakClip2, breakClip3}) .build() val mediaLoadRequestData: MediaLoadRequestData = MediaInfo.Builder() … .setMediaInfo(mediaInfo) .build() remoteMediaClient.load(mediaLoadRequestData)
AdBreakClipInfo breakClip1 = new AdBreakClipInfo.Builder("bc0") .setTitle("Clip title") .setPosterUrl("https://www.some.url") .setDuration(60000) .setWhenSkippableInMs(5000) // Set this field so that the ad is skippable .build(); AdBreakClipInfo breakClip2 = … AdBreakClipInfo breakClip3 = … AdBreakInfo break1 = new AdBreakInfo.Builder(/* playbackPositionInMs= */ 10000) .setId("b0") .setBreakClipIds({"bc0","bc1","bc2"}) … .build(); MediaInfo mediaInfo = new MediaInfo.Builder() … .setAdBreaks({break1}) .setAdBreakClips({breakClip1, breakClip2, breakClip3}) .build(); MediaLoadRequestData mediaLoadRequestData = new MediaInfo.Builder() … .setMediaInfo(mediaInfo) .build(); remoteMediaClient.load(mediaLoadRequestData);
Benutzerdefinierte Aktionen hinzufügen
Eine Sender-App kann MediaIntentReceiver
erweitern, um benutzerdefinierte Aktionen zu verarbeiten oder ihr Verhalten zu überschreiben. Wenn Sie eine eigene MediaIntentReceiver
implementiert haben, müssen Sie sie dem Manifest hinzufügen und auch ihren Namen in der CastMediaOptions
festlegen. In diesem Beispiel werden benutzerdefinierte Aktionen bereitgestellt, die das Umschalten der Medienwiedergabe auf dem Remote-Gerät, das Drücken der Medientaste und andere Arten von Aktionen überschreiben.
// In AndroidManifest.xml
<receiver android:name="com.example.MyMediaIntentReceiver" />
// In your OptionsProvider var mediaOptions = CastMediaOptions.Builder() .setMediaIntentReceiverClassName(MyMediaIntentReceiver::class.java.name) .build() // Implementation of MyMediaIntentReceiver internal class MyMediaIntentReceiver : MediaIntentReceiver() { override fun onReceiveActionTogglePlayback(currentSession: Session) { } override fun onReceiveActionMediaButton(currentSession: Session, intent: Intent) { } override fun onReceiveOtherAction(context: Context?, action: String, intent: Intent) { } }
// In your OptionsProvider CastMediaOptions mediaOptions = new CastMediaOptions.Builder() .setMediaIntentReceiverClassName(MyMediaIntentReceiver.class.getName()) .build(); // Implementation of MyMediaIntentReceiver class MyMediaIntentReceiver extends MediaIntentReceiver { @Override protected void onReceiveActionTogglePlayback(Session currentSession) { } @Override protected void onReceiveActionMediaButton(Session currentSession, Intent intent) { } @Override protected void onReceiveOtherAction(Context context, String action, Intent intent) { } }
Benutzerdefinierten Channel hinzufügen
Damit die Sender-App mit der Empfänger-App kommunizieren kann, muss in Ihrer App ein benutzerdefinierter Kanal erstellt werden. Der Absender kann den benutzerdefinierten Channel verwenden, um String-Nachrichten an den Empfänger zu senden. Jeder benutzerdefinierte Channel wird durch einen eindeutigen Namespace definiert und muss mit dem Präfix urn:x-cast:
beginnen, z. B. urn:x-cast:com.example.custom
. Es ist möglich, mehrere benutzerdefinierte Channels mit jeweils einem eindeutigen Namespace zu haben. Die Receiver-App kann auch Nachrichten senden und empfangen, indem sie denselben Namespace verwendet.
Der benutzerdefinierte Channel wird mit der Cast.MessageReceivedCallback
-Schnittstelle implementiert:
class HelloWorldChannel : MessageReceivedCallback { val namespace: String get() = "urn:x-cast:com.example.custom" override fun onMessageReceived(castDevice: CastDevice, namespace: String, message: String) { Log.d(TAG, "onMessageReceived: $message") } }
class HelloWorldChannel implements Cast.MessageReceivedCallback { public String getNamespace() { return "urn:x-cast:com.example.custom"; } @Override public void onMessageReceived(CastDevice castDevice, String namespace, String message) { Log.d(TAG, "onMessageReceived: " + message); } }
Sobald die Sender-App mit der Empfänger-App verbunden ist, kann der benutzerdefinierte Kanal mit der Methode setMessageReceivedCallbacks
erstellt werden:
try { mCastSession.setMessageReceivedCallbacks( mHelloWorldChannel.namespace, mHelloWorldChannel) } catch (e: IOException) { Log.e(TAG, "Exception while creating channel", e) }
try { mCastSession.setMessageReceivedCallbacks( mHelloWorldChannel.getNamespace(), mHelloWorldChannel); } catch (IOException e) { Log.e(TAG, "Exception while creating channel", e); }
Nachdem der benutzerdefinierte Channel erstellt wurde, kann der Absender die Methode sendMessage
verwenden, um String-Nachrichten über diesen Channel an den Empfänger zu senden:
private fun sendMessage(message: String) { if (mHelloWorldChannel != null) { try { mCastSession.sendMessage(mHelloWorldChannel.namespace, message) .setResultCallback { status -> if (!status.isSuccess) { Log.e(TAG, "Sending message failed") } } } catch (e: Exception) { Log.e(TAG, "Exception while sending message", e) } } }
private void sendMessage(String message) { if (mHelloWorldChannel != null) { try { mCastSession.sendMessage(mHelloWorldChannel.getNamespace(), message) .setResultCallback( status -> { if (!status.isSuccess()) { Log.e(TAG, "Sending message failed"); } }); } catch (Exception e) { Log.e(TAG, "Exception while sending message", e); } } }
Autoplay unterstützen
Weitere Informationen finden Sie im Abschnitt APIs für die automatische Wiedergabe und das Hinzufügen zur Warteschlange.
Bildauswahl für UX-Widgets überschreiben
In verschiedenen Komponenten des Frameworks (nämlich im Cast-Dialogfeld, im Mini-Controller und im UIMediaController, sofern konfiguriert) werden Cover für die aktuell gestreamten Medien angezeigt. Die URLs zu den Bild-Artworks sind in der Regel im MediaMetadata
für die Medien enthalten, aber die Sender-App kann eine alternative Quelle für die URLs haben.
Die Klasse ImagePicker
definiert eine Möglichkeit, ein geeignetes Bild aus der Liste der Bilder in einem MediaMetadata
auszuwählen, basierend auf der Verwendung des Bildes, z. B. als Benachrichtigungs-Thumbnail oder als Vollbildhintergrund. Bei der Standardimplementierung von ImagePicker
wird immer das erste Bild ausgewählt oder „null“ zurückgegeben, wenn im MediaMetadata
kein Bild verfügbar ist. Ihre App kann eine Unterklasse von ImagePicker
erstellen und die Methode onPickImage(MediaMetadata, ImageHints)
überschreiben, um eine alternative Implementierung bereitzustellen. Anschließend kann sie diese Unterklasse mit der Methode setImagePicker
von CastMediaOptions.Builder
auswählen.
ImageHints
bietet einem ImagePicker
Hinweise zum Typ und zur Größe eines Bildes, das für die Anzeige in der Benutzeroberfläche ausgewählt werden soll.
Cast-Dialogfelder anpassen
Sitzungslebenszyklus verwalten
SessionManager
ist der zentrale Ort für die Verwaltung des Sitzungslebenszyklus. SessionManager
überwacht Änderungen des Routenauswahlstatus von Android MediaRouter
, um Sitzungen zu starten, fortzusetzen und zu beenden. Wenn eine Route ausgewählt ist, erstellt SessionManager
ein Session
-Objekt und versucht, es zu starten oder fortzusetzen. Wenn eine Route abgewählt wird, beendet SessionManager
die aktuelle Sitzung.
Damit SessionManager
den Sitzungslebenszyklus richtig verwalten kann, müssen Sie Folgendes sicherstellen:
- Rufen Sie im Dialogfeld zur Routenauswahl
MediaRouter.selectRoute(MediaRouter.RouteInfo)
auf, wenn ein Nutzer ein Gerät auswählt. - Rufen Sie im Dialogfeld des Routencontrollers (entweder im verbundenen Zustand oder im Casting-Zustand)
MediaRouter.unselect(int)
auf, wenn der Nutzer das Casting beendet.
Je nachdem, wie Sie die Cast-Dialogfelder erstellen, sind möglicherweise zusätzliche Aktionen erforderlich:
- Wenn Sie Cast-Dialogfelder mit
MediaRouteChooserDialog
undMediaRouteControllerDialog
erstellen, wird die Routenauswahl inMediaRouter
automatisch aktualisiert. Sie müssen also nichts weiter tun. - Wenn Sie die Cast-Schaltfläche mit
CastButtonFactory.setUpMediaRouteButton(Context, Menu, int)
oderCastButtonFactory.setUpMediaRouteButton(Context, MediaRouteButton)
eingerichtet haben, werden die Dialogfelder mitMediaRouteChooserDialog
undMediaRouteControllerDialog
erstellt. In diesem Fall ist also auch nichts weiter zu tun. - In anderen Fällen erstellen Sie benutzerdefinierte Cast-Dialogfelder. Sie müssen also der Anleitung oben folgen, um den Routenauswahlstatus in
MediaRouter
zu aktualisieren.
Status „Keine Geräte“
Wenn Sie benutzerdefinierte Cast-Dialogfelder erstellen, muss Ihr benutzerdefiniertes MediaRouteChooserDialog
den Fall, dass keine Geräte gefunden werden, richtig verarbeiten. Im Dialogfeld sollten Hinweise angezeigt werden, die Nutzern verdeutlichen, wann Ihre App noch versucht, Geräte zu finden, und wann der Suchvorgang nicht mehr aktiv ist.
Wenn Sie die Standard-MediaRouteChooserDialog
verwenden, wird der Status „Keine Geräte“ bereits berücksichtigt.
Nächste Schritte
Damit sind die Funktionen abgeschlossen, die Sie Ihrer Android-Sender-App hinzufügen können. Sie können jetzt eine Sender-App für eine andere Plattform (iOS oder Web) oder eine Web Receiver-App erstellen.