Werbeunterbrechungen
Das Android Sender SDK unterstützt Werbeunterbrechungen und Companion-Anzeigen in einem bestimmten Medienstream.
Weitere Informationen zur Funktionsweise von Werbeunterbrechungen findest du unter Übersicht über Werbeunterbrechungen für Webreceiver.
Pausen können sowohl beim Sender als auch beim Empfänger angegeben werden. Wir empfehlen jedoch, sie beim Web-Empfänger und beim Android TV-Empfänger anzugeben, um ein einheitliches Verhalten auf allen Plattformen zu gewährleisten.
Gib auf Android-Geräten 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 Absender-App kann MediaIntentReceiver
erweitern, um benutzerdefinierte Aktionen zu verarbeiten oder ihr Verhalten zu überschreiben. Wenn Sie Ihre eigene MediaIntentReceiver
implementiert haben, müssen Sie sie dem Manifest hinzufügen und auch ihren Namen in CastMediaOptions
festlegen. In diesem Beispiel werden benutzerdefinierte Aktionen bereitgestellt, die die Umschaltung der Medienwiedergabe per Fernbedienung, 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 Absender-App mit der Empfänger-App kommunizieren kann, muss Ihre App einen benutzerdefinierten Kanal erstellen. Der Absender kann über den benutzerdefinierten Channel Strings an den Empfänger senden. Jeder benutzerdefinierte Kanal 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 Empfänger-App kann auch Nachrichten über denselben Namespace senden und empfangen.
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 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
Strings über diesen Channel 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 die automatische Wiedergabe
Weitere Informationen findest du im Abschnitt Autoplay- und Wiedergabelisten-APIs.
Bildauswahl für UX-Widgets überschreiben
In verschiedenen Komponenten des Frameworks (nämlich im Übertragungsdialogfeld, im Minicontroller und im UIMediaController, sofern konfiguriert) wird Artwork für die aktuell gestreamten Medien angezeigt. Die URLs zu den Bild-Artworks sind in der Regel 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, je nach Verwendung des Bildes, z. B. als Miniaturansicht für Benachrichtigungen oder als Vollbildhintergrund. Bei der Standardimplementierung von ImagePicker
wird immer das erste Bild ausgewählt oder es wird „null“ zurückgegeben, wenn in der MediaMetadata
kein Bild verfügbar ist. Sie können in Ihrer App eine Unterklasse von ImagePicker
erstellen und die Methode onPickImage(MediaMetadata, ImageHints)
überschreiben, um eine alternative Implementierung bereitzustellen. Wählen Sie diese Unterklasse dann mit der Methode setImagePicker
von CastMediaOptions.Builder
aus.
ImageHints
gibt einem ImagePicker
Hinweise zum Typ und zur Größe eines Bildes, das für die Anzeige in der Benutzeroberfläche ausgewählt werden soll.
Dialogfelder für die Übertragung anpassen
Sitzungslebenszyklus verwalten
SessionManager
ist die zentrale Stelle für die Verwaltung des Sitzungslebenszyklus. SessionManager
überwacht die Änderungen des Status der Routenauswahl unter Android MediaRouter
, um Sitzungen zu starten, fortzusetzen und zu beenden. Wenn eine Route ausgewählt wird, erstellt SessionManager
ein Session
-Objekt und versucht, es zu starten oder fortzusetzen. Wenn keine Route ausgewählt ist, wird die aktuelle Sitzung durch Drücken der Taste SessionManager
beendet.
Damit SessionManager
den Sitzungslebenszyklus richtig verwaltet, müssen Sie Folgendes beachten:
- Rufe im Dialogfeld für die Routenauswahl
MediaRouter.selectRoute(MediaRouter.RouteInfo)
auf, wenn ein Nutzer ein Gerät auswählt. - Rufe im Dialogfeld „Routencontroller“ (entweder im Verbunden-Status oder im Streaming-Status)
MediaRouter.unselect(int)
auf, wenn der Nutzer das Streaming beendet.
Je nachdem, wie Sie die Übertragungsdialoge erstellen, müssen möglicherweise zusätzliche Aktionen ausgeführt werden:
- Wenn Sie Übertragungsdialoge mit
MediaRouteChooserDialog
undMediaRouteControllerDialog
erstellen, wird die Routenauswahl inMediaRouter
automatisch aktualisiert. Sie müssen also nichts weiter tun. - Wenn Sie die Schaltfläche „Streamen“ mit
CastButtonFactory.setUpMediaRouteButton(Context, Menu, int)
oderCastButtonFactory.setUpMediaRouteButton(Context, MediaRouteButton)
eingerichtet haben, werden die Dialogfelder tatsächlich mitMediaRouteChooserDialog
undMediaRouteControllerDialog
erstellt. In diesem Fall müssen Sie nichts weiter tun. - In anderen Fällen erstellen Sie benutzerdefinierte Übertragungsdialoge. Folgen Sie dann der Anleitung oben, um den Status der Routenauswahl in
MediaRouter
zu aktualisieren.
Status „Keine Geräte“
Wenn Sie benutzerdefinierte Übertragungsdialogfelder erstellen, sollte Ihre benutzerdefinierte MediaRouteChooserDialog
den Fall korrekt behandeln, dass keine Geräte gefunden werden. Der Dialog sollte Indikatoren enthalten, die Nutzern klar machen, wann Ihre App noch versucht, Geräte zu finden, und wann der Suchversuch nicht mehr aktiv ist.
Wenn Sie die Standard-MediaRouteChooserDialog
verwenden, wird der Status „Keine Geräte“ bereits verarbeitet.
Nächste Schritte
Das sind alle Funktionen, die du deiner Android-Sender-App hinzufügen kannst. Du kannst jetzt eine Sender-App für eine andere Plattform (iOS oder Web) oder eine Web-Empfänger-App erstellen.