Ihrer Android-App erweiterte Funktionen hinzufügen

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:

Kotlin
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)
Java
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" />
Kotlin
// 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) {
    }
}
Java
// 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:

Kotlin
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")
    }
}
Java
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:

Kotlin
try {
    mCastSession.setMessageReceivedCallbacks(
        mHelloWorldChannel.namespace,
        mHelloWorldChannel)
} catch (e: IOException) {
    Log.e(TAG, "Exception while creating channel", e)
}
Java
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:

Kotlin
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)
        }
    }
}
Java
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:

Je nachdem, wie Sie die Dialogfelder für das Streamen erstellt haben, müssen möglicherweise weitere Aktionen ausgeführt werden:

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.