Werbeunterbrechungen
Das Android Sender SDK unterstützt Werbeunterbrechungen und Companion-Anzeigen innerhalb eines bestimmten Mediastreams.
Weitere Informationen zur Funktionsweise von Werbeunterbrechungen finden Sie in der Übersicht zu Werbeunterbrechungen bei Webempfängern.
Pausen können zwar sowohl beim Sender als auch beim Empfänger angegeben werden. Es wird jedoch empfohlen, diese auf Web Receiver und Android TV Receiver anzugeben, um ein einheitliches Verhalten auf allen Plattformen aufrechtzuerhalten.
Auf Android-Geräten kannst du Werbeunterbrechungen in einem Ladebefehl mit AdBreakClipInfo
und AdBreakInfo
angeben:
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 Absender-App kann MediaIntentReceiver
so erweitern, dass benutzerdefinierte Aktionen verarbeitet oder ihr Verhalten überschrieben werden kann. Wenn du dein eigenes MediaIntentReceiver
implementiert hast, musst du es dem Manifest hinzufügen und seinen Namen in CastMediaOptions
festlegen. Dieses Beispiel bietet benutzerdefinierte Aktionen, die die Ein/Aus-Schaltfläche für die Remote-Medienwiedergabe, 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 Absenderanwendung mit der Empfängeranwendung kommunizieren kann, muss die Anwendung einen benutzerdefinierten Channel erstellen. Der Absender kann den benutzerdefinierten Channel verwenden, um Stringnachrichten 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
. Sie können mehrere benutzerdefinierte Channels mit jeweils einem eindeutigen Namespace verwenden. Die Empfänger-App kann mit demselben Namespace auch Nachrichten senden und empfangen.
Der benutzerdefinierte Channel wird mit der Cast.MessageReceivedCallback
-Oberfläche 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 Absender-App mit der Empfänger-App verbunden ist, kann der benutzerdefinierte Channel 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 mit der Methode sendMessage
Stringnachrichten über diesen Kanal an den Empfänger 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); } } }
Unterstützung für Autoplay
Weitere Informationen findest du im Abschnitt APIs für Autoplay und Wiedergabelisten.
Bildauswahl für UX-Widgets überschreiben
Verschiedene Komponenten des Frameworks, d. h. das Cast-Dialogfeld, der Mini-Controller und der UIMediaController, falls konfiguriert, zeigen das Artwork für die aktuell gestreamten Medien an. Die URLs zu den Bildgrafiken sind normalerweise in der MediaMetadata
für die Medien enthalten. Die Absender-App kann jedoch 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. eine Benachrichtigungsminiaturansicht oder der Vollbildhintergrund. Die Standardimplementierung des ImagePicker
wählt immer das erste Bild aus oder gibt null zurück, wenn kein Bild im MediaMetadata
verfügbar ist. Ihre Anwendung kann die Klasse ImagePicker
ableiten und die Methode onPickImage(MediaMetadata, ImageHints)
überschreiben, um eine alternative Implementierung bereitzustellen. Wählen Sie dann diese abgeleitete Klasse mit der Methode setImagePicker
von CastMediaOptions.Builder
aus.
ImageHints
stellt einem ImagePicker
Hinweise zum Typ und zur Größe eines Bildes bereit, das für die Anzeige in der UI ausgewählt werden soll.
Cast-Dialogfelder anpassen
Sitzungslebenszyklus verwalten
SessionManager
ist der zentrale Ort zum Verwalten des Sitzungslebenszyklus. SessionManager
erfasst Ä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 nicht ausgewählt ist, beendet SessionManager
die aktuelle Sitzung.
Achten Sie daher auf Folgendes, damit SessionManager
Sitzungslebenszyklen ordnungsgemäß verwaltet:
- Rufen Sie im Dialogfeld für die Routenauswahl
MediaRouter.selectRoute(MediaRouter.RouteInfo)
auf, wenn ein Nutzer ein Gerät auswählt. - Rufen Sie im Route Controller-Dialogfeld (entweder im verbundenen Status oder Umwandlungsstatus)
MediaRouter.unselect(int)
auf, wenn der Nutzer das Streamen beendet.
Je nachdem, wie Sie die Dialogfelder für das Streamen erstellt haben, müssen möglicherweise weitere Aktionen ausgeführt werden:
- Wenn Sie Cast-Dialogfelder mit
MediaRouteChooserDialog
undMediaRouteControllerDialog
erstellen, wird die Routenauswahl inMediaRouter
automatisch durch diese Dialogfelder aktualisiert, sodass Sie nichts weiter tun müssen. - Wenn du das Cast-Symbol mit
CastButtonFactory.setUpMediaRouteButton(Context, Menu, int)
oderCastButtonFactory.setUpMediaRouteButton(Context, MediaRouteButton)
eingerichtet hast, werden die Dialogfelder tatsächlich mitMediaRouteChooserDialog
undMediaRouteControllerDialog
erstellt. Du musst also nichts weiter tun. - In anderen Fällen erstellen Sie benutzerdefinierte Umwandlungsdialogfelder. Folgen Sie der Anleitung oben, um den Status der Routenauswahl in
MediaRouter
zu aktualisieren.
Null-Gerätestatus
Wenn du benutzerdefinierte Streaming-Dialogfelder erstellst, sollte dein benutzerdefiniertes MediaRouteChooserDialog
auch ohne Geräte erkannt werden können. Das Dialogfeld sollte Indikatoren enthalten, aus denen Nutzer klar erkennen können, wenn Ihre App noch versucht, Geräte zu finden, und der Erkennungsversuch nicht mehr aktiv ist.
Wenn Sie die Standardeinstellung MediaRouteChooserDialog
verwenden, wird der Status von null Geräten bereits verarbeitet.
Nächste Schritte
Sie haben jetzt die Funktionen, die Sie Ihrer Android-Sender-App hinzufügen können. Sie können jetzt eine Absender-App für eine andere Plattform (iOS oder Web) oder eine Webempfänger-App erstellen.