Werbeunterbrechungen
Das Android Sender SDK unterstützt Werbeunterbrechungen und Companion-Anzeigen in einem bestimmten Media-Stream.
Weitere Informationen zu Werbeunterbrechungen finden Sie in der Übersicht zu Werbeunterbrechungen im Web Receiver für weitere Informationen dazu, wie Werbeunterbrechungen funktionieren.
Unterbrechungen können sowohl auf dem Sender als auch auf dem Receiver 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 das Verhalten zu überschreiben. Wenn Sie einen eigenen MediaIntentReceiver implementiert haben, müssen Sie ihn dem Manifest hinzufügen und seinen Namen auch in den CastMediaOptions festlegen. Dieses Beispiel enthält benutzerdefinierte Aktionen, die die Umschaltung der 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 Kanal hinzufügen
Damit die Sender-App mit der Receiver-App kommunizieren kann, muss Ihre App einen benutzerdefinierten Kanal erstellen. Der Sender kann den benutzerdefinierten Kanal verwenden, um String-Nachrichten an den Receiver zu 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 können mehrere benutzerdefinierte Kanäle mit jeweils einem eindeutigen Namespace vorhanden sein. Die Receiver-App kann auch
Nachrichten senden und empfangen
mit demselben Namespace.
Der benutzerdefinierte Kanal 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 Receiver-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 Kanal erstellt wurde, kann der Sender mit der
sendMessage
Methode String-Nachrichten über diesen Kanal an den Receiver 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); } } }
Automatische Wiedergabe unterstützen
Weitere Informationen finden Sie im Abschnitt APIs für automatische Wiedergabe und Warteschlange.
Bildauswahl für UX-Widgets überschreiben
Verschiedene Komponenten des Frameworks (nämlich das Cast-Dialogfeld, der Mini-Controller und der UIMediaController, falls konfiguriert) zeigen das Artwork für die aktuell übertragenen Medien an. Die URLs zum Bild-Artwork sind in der Regel in den MediaMetadata für die Medien enthalten, aber die Sender-App hat möglicherweise eine alternative Quelle für die URLs.
Die
ImagePicker
Klasse definiert eine Möglichkeit, ein geeignetes Bild aus der Liste der Bilder
in einem MediaMetadataauszuwählen, basierend auf der Verwendung des Bildes, z. B. als Miniaturansicht für Benachrichtigungen
oder als Vollbildhintergrund. Die Standardimplementierung von ImagePicker wählt immer das erste Bild aus oder gibt „null“ zurück, wenn in den MediaMetadata kein Bild verfügbar ist. Ihre App kann ImagePicker unterklassen und die
onPickImage(MediaMetadata, ImageHints)
Methode überschreiben, um eine alternative Implementierung bereitzustellen. Wählen Sie dann diese Unterklasse
mit der
setImagePicker
Methode von CastMediaOptions.Builder aus.
ImageHints
enthält Hinweise für einen ImagePicker 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 Auswahlstatus der Android
MediaRouter
-Route, 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 die Auswahl einer Route aufgehoben wird, beendet SessionManager die aktuelle Sitzung.
Damit SessionManager Sitzungslebenszyklen ordnungsgemäß verwalten kann, müssen Sie Folgendes beachten:
- 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
Status oder
im Übertragungsstatus)
MediaRouter.unselect(int)auf, wenn der Nutzer die Übertragung beendet.
Je nachdem, wie Sie die Cast-Dialogfelder erstellen, sind möglicherweise zusätzliche Maßnahmen erforderlich:
- Wenn Sie Cast-Dialogfelder mit
MediaRouteChooserDialogundMediaRouteControllerDialogerstellen, wird die Routenauswahl inMediaRouterautomatisch aktualisiert. Sie müssen also nichts weiter tun. - Wenn Sie die Cast-Schaltfläche mit
CastButtonFactory.setUpMediaRouteButton(Context, Menu, int)oderCastButtonFactory.setUpMediaRouteButton(Context, MediaRouteButton)einrichten, werden die Dialogfelder mitMediaRouteChooserDialogundMediaRouteControllerDialogerstellt. Auch hier müssen Sie nichts weiter tun. - In anderen Fällen erstellen Sie benutzerdefinierte Cast-Dialogfelder. Folgen Sie daher der obigen Anleitung, um den Status der Routenauswahl in
MediaRouterzu aktualisieren.
Status „Keine Geräte“
Wenn Sie benutzerdefinierte Cast-Dialogfelder erstellen, sollte Ihr benutzerdefinierter MediaRouteChooserDialog den Fall verarbeiten, dass keine Geräte gefunden werden. Das Dialogfeld sollte Indikatoren enthalten, die Nutzern zeigen, wann Ihre App noch versucht, Geräte zu finden, und wann der Suchversuch nicht mehr aktiv ist.
Wenn Sie den Standard-MediaRouteChooserDialog verwenden, wird der Status „Keine Geräte“ bereits verarbeitet.
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.