Für Google Cast optimierte Android-App

1. Übersicht

Google Cast-Logo

In diesem Codelab erfahren Sie, wie Sie eine vorhandene Android-Video-App so ändern, dass Inhalte auf einem für Google Cast optimierten Gerät wiedergegeben werden.

Was ist Google Cast?

Mit Google Cast können Nutzer Inhalte von einem Mobilgerät auf einen Fernseher streamen. Nutzer können ihr Mobilgerät dann als Fernbedienung für die Medienwiedergabe auf dem Fernseher verwenden.

Mit dem Google Cast SDK können Sie Ihre App erweitern, um einen Fernseher oder ein Soundsystem zu steuern. Mit dem Cast SDK können Sie die erforderlichen UI-Komponenten basierend auf der Google Cast-Design-Checkliste hinzufügen.

Die Google Cast-Design-Checkliste soll dafür sorgen, dass die Cast-User Experience auf allen unterstützten Plattformen einfach und vorhersehbar ist.

Ziele

Nach Abschluss dieses Codelabs haben Sie eine Android-Video-App, mit der Sie Videos auf ein für Google Cast optimiertes Gerät streamen können.

Lerninhalte

  • So fügen Sie das Google Cast SDK einer Beispiel-Video-App hinzu.
  • So fügen Sie die Schaltfläche „Streamen“ zum Auswählen eines Google Cast-Geräts hinzu.
  • Verbindung zu einem Übertragungsgerät herstellen und einen Media Receiver starten
  • So streamst du ein Video.
  • So fügen Sie Ihrer App einen Cast-Mini-Controller hinzu.
  • Unterstützung von Medienbenachrichtigungen und Steuerelementen auf dem Sperrbildschirm
  • So fügen Sie einen erweiterten Controller hinzu:
  • So stellen Sie ein Intro-Overlay bereit.
  • Cast-Widgets anpassen
  • Cast Connect einbinden

Voraussetzungen

  • Das aktuelle Android SDK.
  • Android Studio ab Version 3.2
  • Ein Mobilgerät mit Android 4.1+ Jelly Bean (API-Level 16).
  • Ein USB-Datenkabel zum Verbinden Ihres Mobilgeräts mit Ihrem Entwicklercomputer.
  • Ein Google Cast-Gerät wie ein Chromecast oder Android TV, das für den Internetzugriff konfiguriert ist.
  • Einen Fernseher oder Monitor mit HDMI-Eingang
  • Für das Testen der Cast Connect-Integration ist ein Chromecast mit Google TV erforderlich. Für den Rest des Codelabs ist er optional. Wenn Sie keine haben, können Sie den Schritt Cast Connect-Unterstützung hinzufügen am Ende dieser Anleitung überspringen.

Erfahrung

  • Sie benötigen Vorkenntnisse in Kotlin und in der Android-Entwicklung.
  • Außerdem sollten Sie sich mit dem Fernsehen auskennen :)

Wie werden Sie diese Anleitung verwenden?

Nur lesen Lesen und Übungen durchführen

Wie würden Sie Ihre Erfahrung beim Entwickeln von Android-Apps bewerten?

Anfänger Mittelstufe Fortgeschrittene

Wie würdest du deine Erfahrung beim Fernsehen bewerten?

Anfänger Mittelstufe Fortgeschritten

2. Beispielcode abrufen

Sie können den gesamten Beispielcode auf Ihren Computer herunterladen…

und entpacken Sie die heruntergeladene ZIP-Datei.

3. Beispiel-App ausführen

Symbol eines Zirkels

Sehen wir uns zuerst an, wie die fertige Beispiel-App aussieht. Die App ist ein einfacher Videoplayer. Der Nutzer kann ein Video aus einer Liste auswählen und es dann lokal auf dem Gerät abspielen oder auf ein Google Cast-Gerät streamen.

Nachdem Sie den Code heruntergeladen haben, können Sie die vollständige Beispiel-App in Android Studio öffnen und ausführen. Folgen Sie dazu der Anleitung unten:

Wählen Sie auf dem Begrüßungsbildschirm Import Project oder die Menüoptionen File > New > Import Project... aus.

Wählen Sie das Verzeichnis Ordnersymbolapp-done aus dem Ordner mit dem Beispielcode aus und klicken Sie auf „OK“.

Klicken Sie auf Datei > Schaltfläche „Projekt mit Gradle synchronisieren“ in Android Studio Projekt mit Gradle-Dateien synchronisieren.

Aktivieren Sie das USB-Debugging auf Ihrem Android-Gerät. Unter Android 4.2 und höher ist der Bildschirm „Entwickleroptionen“ standardmäßig ausgeblendet. Um sie sichtbar zu machen, rufen Sie Einstellungen > Über das Telefon auf und tippen Sie sieben Mal auf Build-Nummer. Kehren Sie zum vorherigen Bildschirm zurück, gehen Sie zu System > Erweitert und tippen Sie unten auf Entwickleroptionen. Tippen Sie dann auf USB-Debugging, um die Funktion zu aktivieren.

Schließen Sie Ihr Android-Gerät an und klicken Sie in Android Studio auf die Schaltfläche Die Schaltfläche „Ausführen“ in Android Studio, ein grünes Dreieck, das nach rechts zeigtRun (Ausführen). Nach einigen Sekunden sollte die Video-App mit dem Namen Videos streamen angezeigt werden.

Klicke in der Video-App auf das Cast-Symbol und wähle dein Google Cast-Gerät aus.

Wählen Sie ein Video aus und klicken Sie auf die Wiedergabeschaltfläche.

Die Wiedergabe des Videos beginnt auf deinem Google Cast-Gerät.

Der erweiterte Controller wird angezeigt. Mit der Wiedergabe-/Pausetaste kannst du die Wiedergabe steuern.

Kehren Sie zur Liste der Videos zurück.

Unten auf dem Bildschirm wird jetzt ein Mini-Controller angezeigt. Abbildung eines Android-Smartphones, auf dem die App „Videos streamen“ ausgeführt wird. Unten auf dem Display wird eine Mini-Steuerung angezeigt.

Klicke im Mini-Controller auf die Pausenschaltfläche, um das Video auf dem Empfängergerät zu pausieren. Klicke auf die Wiedergabeschaltfläche in der Mini-Steuerung, um die Wiedergabe des Videos fortzusetzen.

Klicken Sie auf die Home-Taste des Mobilgeräts. Wische nach unten, um die Benachrichtigungen aufzurufen. Dort solltest du jetzt eine Benachrichtigung für die Cast-Sitzung sehen.

Sperre dein Smartphone. Wenn du es entsperrst, solltest du auf dem Sperrbildschirm eine Benachrichtigung sehen, über die du die Medienwiedergabe steuern oder die Übertragung beenden kannst.

Kehre zur Video-App zurück und klicke auf das Cast-Symbol, um das Streaming auf dem Google Cast-Gerät zu beenden.

Häufig gestellte Fragen

4. Startprojekt vorbereiten

Abbildung eines Android-Smartphones mit der App „Videos streamen“

Wir müssen der heruntergeladenen Start-App Unterstützung für Google Cast hinzufügen. Hier sind einige Google Cast-Begriffe, die in diesem Codelab verwendet werden:

  • Eine Absender-App wird auf einem Mobilgerät oder Laptop ausgeführt.
  • Auf dem Google Cast-Gerät wird eine Receiver-App ausgeführt.

Jetzt können Sie das Starterprojekt in Android Studio verwenden:

  1. Wählen Sie das Verzeichnis Ordnersymbolapp-start aus dem heruntergeladenen Beispielcode aus (wählen Sie auf dem Begrüßungsbildschirm Projekt importieren oder die Menüoption Datei > Neu > Projekt importieren… aus).
  2. Klicken Sie auf die Schaltfläche Schaltfläche „Projekt mit Gradle synchronisieren“ in Android Studio Projekt mit Gradle-Dateien synchronisieren.
  3. Klicken Sie auf die Schaltfläche Die Schaltfläche „Ausführen“ in Android Studio, ein grünes Dreieck, das nach rechts zeigtAusführen, um die App auszuführen und die Benutzeroberfläche zu erkunden.

App-Design

Die App ruft eine Liste von Videos von einem Remote-Webserver ab und stellt dem Nutzer eine Liste zum Durchsuchen zur Verfügung. Nutzer können ein Video auswählen, um die Details aufzurufen oder das Video lokal auf dem Mobilgerät abzuspielen.

Die App besteht aus zwei Hauptaktivitäten: VideoBrowserActivity und LocalPlayerActivity. Damit die Google Cast-Funktionalität eingebunden werden kann, müssen die Aktivitäten entweder von AppCompatActivity oder von deren übergeordneter Klasse FragmentActivity abgeleitet werden. Diese Einschränkung besteht, da wir MediaRouteButton (in der MediaRouter-Supportbibliothek enthalten) als MediaRouteActionProvider hinzufügen müssten. Das funktioniert nur, wenn die Aktivität von den oben genannten Klassen abgeleitet wird. Die MediaRouter-Supportbibliothek ist von der AppCompat-Supportbibliothek abhängig, die die erforderlichen Klassen bereitstellt.

VideoBrowserActivity

Diese Aktivität enthält eine Fragment (VideoBrowserFragment). Diese Liste wird von einer ArrayAdapter (VideoListAdapter) unterstützt. Die Liste der Videos und der zugehörigen Metadaten wird auf einem Remote-Server als JSON-Datei gehostet. Ein AsyncTaskLoader (VideoItemLoader) ruft dieses JSON ab und verarbeitet es, um eine Liste von MediaItem-Objekten zu erstellen.

Ein MediaItem-Objekt modelliert ein Video und die zugehörigen Metadaten wie Titel, Beschreibung, URL für den Stream, URL für die unterstützenden Bilder und zugehörige Text-Tracks (für Untertitel), falls vorhanden. Das MediaItem-Objekt wird zwischen Aktivitäten übergeben. Daher enthält MediaItem Hilfsmethoden, um es in ein Bundle umzuwandeln und umgekehrt.

Wenn der Loader die Liste der MediaItems erstellt, wird diese Liste an die VideoListAdapter übergeben, die die Liste der MediaItems dann in der VideoBrowserFragment präsentiert. Dem Nutzer wird eine Liste mit Video-Thumbnails und einer kurzen Beschreibung für jedes Video angezeigt. Wenn ein Element ausgewählt wird, wird das entsprechende MediaItem in ein Bundle umgewandelt und an LocalPlayerActivity übergeben.

LocalPlayerActivity

Bei dieser Aktivität werden die Metadaten zu einem bestimmten Video angezeigt und der Nutzer kann das Video lokal auf dem Mobilgerät abspielen.

Die Aktivität enthält ein VideoView, einige Media-Steuerelemente und einen Textbereich, in dem die Beschreibung des ausgewählten Videos angezeigt wird. Der Player nimmt den oberen Teil des Bildschirms ein und lässt darunter Platz für die ausführliche Videobeschreibung. Der Nutzer kann die lokale Wiedergabe von Videos starten/pausieren oder zu einer anderen Stelle im Video springen.

Abhängigkeiten

Da wir AppCompatActivity verwenden, benötigen wir die AppCompat-Supportbibliothek. Zum Verwalten der Liste der Videos und zum asynchronen Abrufen der Bilder für die Liste verwenden wir die Volley-Bibliothek.

Häufig gestellte Fragen

5. Cast-Symbol hinzufügen

Abbildung des oberen Teils eines Android-Smartphones mit der App „Video streamen“; die Schaltfläche „Streamen“ wird oben rechts auf dem Display angezeigt.

In einer für Google Cast optimierten App wird das Cast-Symbol in jeder Aktivität angezeigt. Wenn ein Nutzer auf das Cast-Symbol klickt, wird eine Liste mit Cast-Geräten angezeigt, die er auswählen kann. Wenn der Nutzer Inhalte lokal auf dem Absendergerät wiedergegeben hat, wird die Wiedergabe auf dem ausgewählten Übertragungsgerät gestartet oder fortgesetzt. Der Nutzer kann während einer Cast-Sitzung jederzeit auf das Cast-Symbol klicken und die Übertragung Ihrer Anwendung auf das Cast-Gerät beenden. Der Nutzer muss sich während jeder Aktivität Ihrer Anwendung mit dem Cast-Gerät verbinden oder die Verbindung trennen können, wie in der Google Cast Design Checklist beschrieben.

Abhängigkeiten

Aktualisieren Sie die Datei „app/build.gradle“, um die erforderlichen Bibliotheksabhängigkeiten einzufügen:

dependencies {
    implementation 'androidx.appcompat:appcompat:1.5.0'
    implementation 'androidx.mediarouter:mediarouter:1.3.1'
    implementation 'androidx.recyclerview:recyclerview:1.2.1'
    implementation 'com.google.android.gms:play-services-cast-framework:21.1.0'
    implementation 'com.android.volley:volley:1.2.1'
    implementation "androidx.core:core-ktx:1.8.0"
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
}

Synchronisieren Sie das Projekt, um zu bestätigen, dass es ohne Fehler erstellt wird.

Initialisierung

Das Cast-Framework hat ein globales Singleton-Objekt, das CastContext, das alle Cast-Interaktionen koordiniert.

Sie müssen die OptionsProvider-Schnittstelle implementieren, um die CastOptions bereitzustellen, die zum Initialisieren des CastContext-Singletons erforderlich sind. Die wichtigste Option ist die Empfängeranwendungs-ID, mit der die Ergebnisse der Suche nach Cast-Geräten gefiltert und die Empfängeranwendung gestartet wird, wenn eine Cast-Sitzung beginnt.

Wenn Sie Ihre eigene für Google Cast optimierte App entwickeln, müssen Sie sich als Cast-Entwickler registrieren und dann eine Anwendungs-ID für Ihre App erhalten. In diesem Codelab verwenden wir eine Beispiel-App-ID.

Fügen Sie dem Paket com.google.sample.cast.refplayer des Projekts die folgende neue CastOptionsProvider.kt-Datei hinzu:

package com.google.sample.cast.refplayer

import android.content.Context
import com.google.android.gms.cast.framework.OptionsProvider
import com.google.android.gms.cast.framework.CastOptions
import com.google.android.gms.cast.framework.SessionProvider

class CastOptionsProvider : OptionsProvider {
    override fun getCastOptions(context: Context): CastOptions {
        return CastOptions.Builder()
                .setReceiverApplicationId(context.getString(R.string.app_id))
                .build()
    }

    override fun getAdditionalSessionProviders(context: Context): List<SessionProvider>? {
        return null
    }
}

Deklarieren Sie nun OptionsProvider im Tag „application“ der App-Datei AndroidManifest.xml:

<meta-data
    android:name="com.google.android.gms.cast.framework.OPTIONS_PROVIDER_CLASS_NAME"
    android:value="com.google.sample.cast.refplayer.CastOptionsProvider" />

Initialisieren Sie CastContext verzögert in der Methode VideoBrowserActivity onCreate:

import com.google.android.gms.cast.framework.CastContext

private var mCastContext: CastContext? = null

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.video_browser)
    setupActionBar()

    mCastContext = CastContext.getSharedInstance(this)
}

Fügen Sie LocalPlayerActivity dieselbe Initialisierungslogik hinzu.

Cast-Symbol

Nachdem CastContext initialisiert wurde, müssen wir die Schaltfläche „Streamen“ hinzufügen, damit der Nutzer ein Streaminggerät auswählen kann. Die Cast-Schaltfläche wird durch MediaRouteButton aus der Support Library MediaRouter implementiert. Wie bei jedem Aktionssymbol, das Sie Ihrer Aktivität hinzufügen können (entweder mit ActionBar oder Toolbar), müssen Sie zuerst das entsprechende Menüelement zu Ihrem Menü hinzufügen.

Bearbeiten Sie die Datei res/menu/browse.xml und fügen Sie das Element MediaRouteActionProvider im Menü vor dem Element „Einstellungen“ ein:

<item
    android:id="@+id/media_route_menu_item"
    android:title="@string/media_route_menu_title"
    app:actionProviderClass="androidx.mediarouter.app.MediaRouteActionProvider"
    app:showAsAction="always"/>

Überschreiben Sie die Methode onCreateOptionsMenu() von VideoBrowserActivity mit CastButtonFactory, um MediaRouteButton mit dem Cast-Framework zu verbinden:

import com.google.android.gms.cast.framework.CastButtonFactory

private var mediaRouteMenuItem: MenuItem? = null

override fun onCreateOptionsMenu(menu: Menu): Boolean {
     super.onCreateOptionsMenu(menu)
     menuInflater.inflate(R.menu.browse, menu)
     mediaRouteMenuItem = CastButtonFactory.setUpMediaRouteButton(getApplicationContext(), menu,
                R.id.media_route_menu_item)
     return true
}

Überschreiben Sie onCreateOptionsMenu in LocalPlayerActivity auf ähnliche Weise.

Klicken Sie auf die Schaltfläche Die Schaltfläche „Ausführen“ in Android Studio, ein grünes Dreieck, das nach rechts zeigtAusführen, um die App auf Ihrem Mobilgerät auszuführen. In der Aktionsleiste der App sollte ein Cast-Symbol angezeigt werden. Wenn Sie darauf klicken, werden die Cast-Geräte in Ihrem lokalen Netzwerk aufgelistet. Die Geräteerkennung wird automatisch von CastContext verwaltet. Wählen Sie Ihr Übertragungsgerät aus. Die Beispiel-Receiver-App wird auf dem Übertragungsgerät geladen. Sie können zwischen der Browseraktivität und der lokalen Playeraktivität wechseln. Der Status der Schaltfläche „Streamen“ wird synchronisiert.

Wir haben noch keine Unterstützung für die Medienwiedergabe eingerichtet, daher können Sie noch keine Videos auf dem Cast-Gerät abspielen. Klicken Sie auf das Cast-Symbol, um die Verbindung zu trennen.

6. Videoinhalte streamen

Abbildung eines Android-Smartphones mit der App „Videos streamen“

Wir werden die Beispiel-App so erweitern, dass Videos auch auf einem Cast-Gerät wiedergegeben werden können. Dazu müssen wir auf die verschiedenen Ereignisse achten, die vom Cast-Framework generiert werden.

Medien streamen

Wenn Sie Medien auf einem Cast-Gerät wiedergeben möchten, müssen Sie im Wesentlichen Folgendes tun:

  1. Erstellen Sie ein MediaInfo-Objekt, das ein Media-Element modelliert.
  2. Stelle eine Verbindung zum Cast-Gerät her und starte die Empfängeranwendung.
  3. Lade das MediaInfo-Objekt auf deinen Empfänger und spiele die Inhalte ab.
  4. Medienstatus verfolgen
  5. Sende Wiedergabebefehle basierend auf Nutzerinteraktionen an den Empfänger.

Schritt 2 haben wir bereits im vorherigen Abschnitt ausgeführt. Schritt 3 ist mit dem Cast-Framework ganz einfach. In Schritt 1 wird ein Objekt einem anderen zugeordnet. MediaInfo ist etwas, das das Cast-Framework versteht, und MediaItem ist die Kapselung unserer App für ein Media-Element. Wir können MediaItem ganz einfach MediaInfo zuordnen.

In der Beispiel-App LocalPlayerActivity wird bereits zwischen lokaler und Remote-Wiedergabe unterschieden. Dazu wird dieses Enum verwendet:

private var mLocation: PlaybackLocation? = null

enum class PlaybackLocation {
    LOCAL, REMOTE
}

enum class PlaybackState {
    PLAYING, PAUSED, BUFFERING, IDLE
}

In diesem Codelab ist es nicht wichtig, dass Sie genau verstehen, wie die gesamte Beispiel-Player-Logik funktioniert. Es ist wichtig zu wissen, dass der Media Player Ihrer App so angepasst werden muss, dass er die beiden Wiedergabeorte auf ähnliche Weise erkennt.

Der lokale Player befindet sich derzeit immer im lokalen Wiedergabestatus, da er noch nichts über die Streaming-Status weiß. Wir müssen die Benutzeroberfläche basierend auf Statusübergängen im Cast-Framework aktualisieren. Wenn wir beispielsweise mit dem Streamen beginnen, müssen wir die lokale Wiedergabe beenden und einige Steuerelemente deaktivieren. Wenn wir das Streaming während dieser Aktivität beenden, müssen wir zur lokalen Wiedergabe wechseln. Dazu müssen wir auf die verschiedenen Ereignisse achten, die vom Cast-Framework generiert werden.

Verwaltung von Cast-Sitzungen

Im Cast-Framework werden die Schritte zum Herstellen einer Verbindung zu einem Gerät, zum Starten (oder Beitreten) einer Empfängeranwendung, zum Herstellen einer Verbindung zu dieser Anwendung und zum Initialisieren eines Mediensteuerung-Channels (falls erforderlich) in einer Cast-Sitzung zusammengefasst. Über den Media-Steuerkanal werden Nachrichten zwischen dem Cast-Framework und dem Media-Player des Receivers gesendet und empfangen.

Die Cast-Sitzung wird automatisch gestartet, wenn der Nutzer über die Cast-Schaltfläche ein Gerät auswählt, und automatisch beendet, wenn der Nutzer die Verbindung trennt. Die Wiederherstellung der Verbindung zu einer Empfängersitzung aufgrund von Netzwerkproblemen wird ebenfalls automatisch vom Cast SDK verarbeitet.

Fügen wir dem LocalPlayerActivity ein SessionManagerListener hinzu:

import com.google.android.gms.cast.framework.CastSession
import com.google.android.gms.cast.framework.SessionManagerListener
...

private var mSessionManagerListener: SessionManagerListener<CastSession>? = null
private var mCastSession: CastSession? = null
...

private fun setupCastListener() {
    mSessionManagerListener = object : SessionManagerListener<CastSession> {
        override fun onSessionEnded(session: CastSession, error: Int) {
            onApplicationDisconnected()
        }

        override fun onSessionResumed(session: CastSession, wasSuspended: Boolean) {
            onApplicationConnected(session)
        }

        override fun onSessionResumeFailed(session: CastSession, error: Int) {
            onApplicationDisconnected()
        }

        override fun onSessionStarted(session: CastSession, sessionId: String) {
            onApplicationConnected(session)
        }

        override fun onSessionStartFailed(session: CastSession, error: Int) {
            onApplicationDisconnected()
        }

        override fun onSessionStarting(session: CastSession) {}
        override fun onSessionEnding(session: CastSession) {}
        override fun onSessionResuming(session: CastSession, sessionId: String) {}
        override fun onSessionSuspended(session: CastSession, reason: Int) {}
        private fun onApplicationConnected(castSession: CastSession) {
            mCastSession = castSession
            if (null != mSelectedMedia) {
                if (mPlaybackState == PlaybackState.PLAYING) {
                    mVideoView!!.pause()
                    loadRemoteMedia(mSeekbar!!.progress, true)
                    return
                } else {
                    mPlaybackState = PlaybackState.IDLE
                    updatePlaybackLocation(PlaybackLocation.REMOTE)
                }
            }
            updatePlayButton(mPlaybackState)
            invalidateOptionsMenu()
        }

        private fun onApplicationDisconnected() {
            updatePlaybackLocation(PlaybackLocation.LOCAL)
            mPlaybackState = PlaybackState.IDLE
            mLocation = PlaybackLocation.LOCAL
            updatePlayButton(mPlaybackState)
            invalidateOptionsMenu()
       }
   }
}

Bei LocalPlayerActivity-Aktivitäten möchten wir benachrichtigt werden, wenn wir eine Verbindung zum Cast-Gerät herstellen oder die Verbindung trennen, damit wir zum lokalen Player wechseln können. Die Verbindung kann nicht nur durch die Instanz Ihrer Anwendung, die auf Ihrem Mobilgerät ausgeführt wird, sondern auch durch eine andere Instanz Ihrer (oder einer anderen) Anwendung, die auf einem anderen Mobilgerät ausgeführt wird, unterbrochen werden.

Die derzeit aktive Sitzung ist als SessionManager.getCurrentSession() verfügbar. Sitzungen werden automatisch als Reaktion auf Nutzerinteraktionen mit den Cast-Dialogfeldern erstellt und beendet.

Wir müssen unseren Sitzungs-Listener registrieren und einige Variablen initialisieren, die wir in der Aktivität verwenden werden. Ändern Sie die Methode LocalPlayerActivity onCreate in:

import com.google.android.gms.cast.framework.CastContext
...

private var mCastContext: CastContext? = null
...

override fun onCreate(savedInstanceState: Bundle?) {
    ...
    mCastContext = CastContext.getSharedInstance(this)
    mCastSession = mCastContext!!.sessionManager.currentCastSession
    setupCastListener()
    ...
    loadViews()
    ...
    val bundle = intent.extras
    if (bundle != null) {
        ....
        if (shouldStartPlayback) {
              ....

        } else {
            if (mCastSession != null && mCastSession!!.isConnected()) {
                updatePlaybackLocation(PlaybackLocation.REMOTE)
            } else {
                updatePlaybackLocation(PlaybackLocation.LOCAL)
            }
            mPlaybackState = PlaybackState.IDLE
            updatePlayButton(mPlaybackState)
        }
    }
    ...
}

Medien werden geladen

Im Cast SDK bietet RemoteMediaClient eine Reihe praktischer APIs zum Verwalten der Remote-Medienwiedergabe auf dem Empfängergerät. Für ein CastSession, das die Medienwiedergabe unterstützt, wird vom SDK automatisch eine Instanz von RemoteMediaClient erstellt. Sie können darauf zugreifen, indem Sie die Methode getRemoteMediaClient() für die CastSession-Instanz aufrufen. Fügen Sie LocalPlayerActivity die folgenden Methoden hinzu, um das aktuell ausgewählte Video auf dem Empfängergerät zu laden:

import com.google.android.gms.cast.framework.media.RemoteMediaClient
import com.google.android.gms.cast.MediaInfo
import com.google.android.gms.cast.MediaLoadOptions
import com.google.android.gms.cast.MediaMetadata
import com.google.android.gms.common.images.WebImage
import com.google.android.gms.cast.MediaLoadRequestData

private fun loadRemoteMedia(position: Int, autoPlay: Boolean) {
    if (mCastSession == null) {
        return
    }
    val remoteMediaClient = mCastSession!!.remoteMediaClient ?: return
    remoteMediaClient.load( MediaLoadRequestData.Builder()
                .setMediaInfo(buildMediaInfo())
                .setAutoplay(autoPlay)
                .setCurrentTime(position.toLong()).build())
}

private fun buildMediaInfo(): MediaInfo? {
    val movieMetadata = MediaMetadata(MediaMetadata.MEDIA_TYPE_MOVIE)
    mSelectedMedia?.studio?.let { movieMetadata.putString(MediaMetadata.KEY_SUBTITLE, it) }
    mSelectedMedia?.title?.let { movieMetadata.putString(MediaMetadata.KEY_TITLE, it) }
    movieMetadata.addImage(WebImage(Uri.parse(mSelectedMedia!!.getImage(0))))
    movieMetadata.addImage(WebImage(Uri.parse(mSelectedMedia!!.getImage(1))))
    return mSelectedMedia!!.url?.let {
        MediaInfo.Builder(it)
            .setStreamType(MediaInfo.STREAM_TYPE_BUFFERED)
            .setContentType("videos/mp4")
            .setMetadata(movieMetadata)
            .setStreamDuration((mSelectedMedia!!.duration * 1000).toLong())
            .build()
    }
}

Aktualisieren Sie nun verschiedene vorhandene Methoden, um die Cast-Sitzungslogik für die Unterstützung der Remote-Wiedergabe zu verwenden:

private fun play(position: Int) {
    startControllersTimer()
    when (mLocation) {
        PlaybackLocation.LOCAL -> {
            mVideoView!!.seekTo(position)
            mVideoView!!.start()
        }
        PlaybackLocation.REMOTE -> {
            mPlaybackState = PlaybackState.BUFFERING
            updatePlayButton(mPlaybackState)
            //seek to a new position within the current media item's new position 
            //which is in milliseconds from the beginning of the stream
            mCastSession!!.remoteMediaClient?.seek(position.toLong())
        }
        else -> {}
    }
    restartTrickplayTimer()
}
private fun togglePlayback() {
    ...
    PlaybackState.IDLE -> when (mLocation) {
        ...
        PlaybackLocation.REMOTE -> {
            if (mCastSession != null && mCastSession!!.isConnected) {
                loadRemoteMedia(mSeekbar!!.progress, true)
            }
        }
        else -> {}
    }
    ...
}
override fun onPause() {
    ...
    mCastContext!!.sessionManager.removeSessionManagerListener(
                mSessionManagerListener!!, CastSession::class.java)
}
override fun onResume() {
    Log.d(TAG, "onResume() was called")
    mCastContext!!.sessionManager.addSessionManagerListener(
            mSessionManagerListener!!, CastSession::class.java)
    if (mCastSession != null && mCastSession!!.isConnected) {
        updatePlaybackLocation(PlaybackLocation.REMOTE)
    } else {
        updatePlaybackLocation(PlaybackLocation.LOCAL)
    }
    super.onResume()
}

Ändern Sie für die Methode updatePlayButton den Wert der Variablen isConnected:

private fun updatePlayButton(state: PlaybackState?) {
    ...
    val isConnected = (mCastSession != null
                && (mCastSession!!.isConnected || mCastSession!!.isConnecting))
    ...
}

Klicken Sie nun auf die Schaltfläche Die Schaltfläche „Ausführen“ in Android Studio, ein grünes Dreieck, das nach rechts zeigtAusführen, um die App auf Ihrem Mobilgerät auszuführen. Verbinde dich mit deinem Cast-Gerät und starte die Wiedergabe eines Videos. Das Video sollte jetzt auf dem Empfängergerät wiedergegeben werden.

7. Mini-Controller

Gemäß der Checkliste für das Cast-Design muss jede Cast-App eine Mini-Steuerung bereitstellen, die angezeigt wird, wenn der Nutzer die aktuelle Inhaltsseite verlässt. Der Mini-Controller bietet sofortigen Zugriff und eine sichtbare Erinnerung an die aktuelle Cast-Sitzung.

Abbildung des unteren Teils eines Android-Smartphones mit dem Miniplayer in der App „Videos streamen“

Das Cast SDK bietet eine benutzerdefinierte Ansicht, MiniControllerFragment, die der App-Layoutdatei der Aktivitäten hinzugefügt werden kann, in denen der Mini-Controller angezeigt werden soll.

Fügen Sie die folgende Fragmentdefinition unten in res/layout/player_activity.xml und res/layout/video_browser.xml ein:

<fragment
    android:id="@+id/castMiniController"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:visibility="gone"
    class="com.google.android.gms.cast.framework.media.widget.MiniControllerFragment"/>

Klicken Sie auf die Schaltfläche Die Schaltfläche „Ausführen“ in Android Studio, ein grünes Dreieck, das nach rechts zeigtAusführen, um die App auszuführen und ein Video zu streamen. Wenn die Wiedergabe auf dem Empfängergerät startet, sollte unten bei jeder Aktivität die Mini-Steuerung angezeigt werden. Mit dem Mini-Controller kannst du die Wiedergabe auf dem Remote-Gerät steuern. Wenn du zwischen der Browseraktivität und der Aktivität des lokalen Players wechselst, sollte der Status der Mini-Steuerung mit dem Status der Medienwiedergabe des Empfängers synchronisiert bleiben.

8. Benachrichtigungen und Sperrbildschirm

Die Google Cast-Design-Checkliste erfordert, dass in einer Sender-App Mediensteuerelemente über eine Benachrichtigung und den Sperrbildschirm implementiert werden.

Abbildung eines Android-Smartphones mit Mediensteuerelementen im Benachrichtigungsbereich

Das Cast SDK bietet ein MediaNotificationService, mit dem die Sender-App Mediensteuerelemente für die Benachrichtigung und den Sperrbildschirm erstellen kann. Der Dienst wird von Gradle automatisch in das Manifest Ihrer App eingefügt.

Die MediaNotificationService wird im Hintergrund ausgeführt, wenn der Absender Inhalte streamt. Es wird eine Benachrichtigung mit einem Bild-Thumbnail und Metadaten zum aktuellen Streaming-Element, einer Schaltfläche zum Starten/Pausieren und einer Schaltfläche zum Beenden angezeigt.

Die Benachrichtigungs- und Sperrbildschirm-Steuerelemente können beim Initialisieren von CastContext mit CastOptions aktiviert werden. Die Mediensteuerung für die Benachrichtigungsleiste und den Sperrbildschirm ist standardmäßig aktiviert. Die Sperrbildschirmfunktion ist aktiviert, solange Benachrichtigungen aktiviert sind.

Bearbeiten Sie CastOptionsProvider und ändern Sie die getCastOptions-Implementierung so, dass sie diesem Code entspricht:

import com.google.android.gms.cast.framework.media.CastMediaOptions
import com.google.android.gms.cast.framework.media.NotificationOptions

override fun getCastOptions(context: Context): CastOptions {
   val notificationOptions = NotificationOptions.Builder()
            .setTargetActivityClassName(VideoBrowserActivity::class.java.name)
            .build()
    val mediaOptions = CastMediaOptions.Builder()
            .setNotificationOptions(notificationOptions)
            .build()
   return CastOptions.Builder()
                .setReceiverApplicationId(context.getString(R.string.app_id))
                .setCastMediaOptions(mediaOptions)
                .build()
}

Klicken Sie auf die Schaltfläche Die Schaltfläche „Ausführen“ in Android Studio, ein grünes Dreieck, das nach rechts zeigtAusführen, um die App auf Ihrem Mobilgerät auszuführen. Streame ein Video und wechsle die Beispiel-App. Es sollte eine Benachrichtigung für das Video angezeigt werden, das gerade auf dem Empfängergerät wiedergegeben wird. Sperren Sie Ihr Mobilgerät. Auf dem Sperrbildschirm sollten nun Steuerelemente für die Medienwiedergabe auf dem Cast-Gerät angezeigt werden.

Abbildung eines Android-Smartphones mit Mediensteuerungen auf dem Sperrbildschirm

9. Einführungs-Overlay

Die Google Cast-Design-Checkliste erfordert, dass in einer Sender-App die Cast-Schaltfläche eingeführt wird, um bestehende Nutzer darüber zu informieren, dass die Sender-App jetzt das Casting unterstützt. Außerdem hilft sie Nutzern, die Google Cast noch nicht kennen.

Abbildung des Einführungs-Overlays für Google Cast um das Cast-Symbol in der Android-App „Cast Videos“

Das Cast SDK bietet eine benutzerdefinierte Ansicht, IntroductoryOverlay, mit der die Cast-Schaltfläche hervorgehoben werden kann, wenn sie Nutzern zum ersten Mal angezeigt wird. Fügen Sie den folgenden Code zu VideoBrowserActivity hinzu:

import com.google.android.gms.cast.framework.IntroductoryOverlay
import android.os.Looper

private var mIntroductoryOverlay: IntroductoryOverlay? = null

private fun showIntroductoryOverlay() {
    mIntroductoryOverlay?.remove()
    if (mediaRouteMenuItem?.isVisible == true) {
       Looper.myLooper().run {
           mIntroductoryOverlay = com.google.android.gms.cast.framework.IntroductoryOverlay.Builder(
                    this@VideoBrowserActivity, mediaRouteMenuItem!!)
                   .setTitleText("Introducing Cast")
                   .setSingleTime()
                   .setOnOverlayDismissedListener(
                           object : IntroductoryOverlay.OnOverlayDismissedListener {
                               override fun onOverlayDismissed() {
                                   mIntroductoryOverlay = null
                               }
                          })
                   .build()
          mIntroductoryOverlay!!.show()
        }
    }
}

Fügen Sie nun ein CastStateListener hinzu und rufen Sie die Methode showIntroductoryOverlay auf, wenn ein Cast-Gerät verfügbar ist. Ändern Sie dazu die Methode onCreate und überschreiben Sie die Methoden onResume und onPause so, dass sie dem Folgenden entsprechen:

import com.google.android.gms.cast.framework.CastState
import com.google.android.gms.cast.framework.CastStateListener

private var mCastStateListener: CastStateListener? = null

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.video_browser)
    setupActionBar()
    mCastStateListener = object : CastStateListener {
            override fun onCastStateChanged(newState: Int) {
                if (newState != CastState.NO_DEVICES_AVAILABLE) {
                    showIntroductoryOverlay()
                }
            }
        }
    mCastContext = CastContext.getSharedInstance(this)
}

override fun onResume() {
    super.onResume()
    mCastContext?.addCastStateListener(mCastStateListener!!)
}

override fun onPause() {
    super.onPause()
    mCastContext?.removeCastStateListener(mCastStateListener!!)
}

Löschen Sie die App-Daten oder entfernen Sie die App von Ihrem Gerät. Klicken Sie dann auf die Schaltfläche Die Schaltfläche „Ausführen“ in Android Studio, ein grünes Dreieck, das nach rechts zeigtAusführen, um die App auf Ihrem Mobilgerät auszuführen. Das Einführungs-Overlay sollte angezeigt werden. Wenn das Overlay nicht angezeigt wird, löschen Sie die App-Daten.

10. Erweiterter Controller

Die Google Cast-Design-Checkliste erfordert, dass eine Sender-App einen erweiterten Controller für die übertragenen Medien bereitstellt. Der maximierte Controller ist eine Vollbildversion des Mini-Controllers.

Abbildung eines Videos, das auf einem Android-Smartphone abgespielt wird, mit dem maximierten Controller-Overlay

Das Cast SDK bietet ein Widget für die erweiterte Steuerung namens ExpandedControllerActivity. Dies ist eine abstrakte Klasse, die Sie unterteilen müssen, um eine Cast-Schaltfläche hinzuzufügen.

Erstellen Sie zuerst eine neue Menüressourcendatei mit dem Namen expanded_controller.xml für den erweiterten Controller, um die Cast-Schaltfläche bereitzustellen:

<?xml version="1.0" encoding="utf-8"?>

<menu xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:app="http://schemas.android.com/apk/res-auto">

    <item
            android:id="@+id/media_route_menu_item"
            android:title="@string/media_route_menu_title"
            app:actionProviderClass="androidx.mediarouter.app.MediaRouteActionProvider"
            app:showAsAction="always"/>

</menu>

Erstellen Sie ein neues Paket expandedcontrols im Paket com.google.sample.cast.refplayer. Erstellen Sie als Nächstes im Paket com.google.sample.cast.refplayer.expandedcontrols eine neue Datei mit dem Namen ExpandedControlsActivity.kt.

package com.google.sample.cast.refplayer.expandedcontrols

import android.view.Menu
import com.google.android.gms.cast.framework.media.widget.ExpandedControllerActivity
import com.google.sample.cast.refplayer.R
import com.google.android.gms.cast.framework.CastButtonFactory

class ExpandedControlsActivity : ExpandedControllerActivity() {
    override fun onCreateOptionsMenu(menu: Menu): Boolean {
        super.onCreateOptionsMenu(menu)
        menuInflater.inflate(R.menu.expanded_controller, menu)
        CastButtonFactory.setUpMediaRouteButton(this, menu, R.id.media_route_menu_item)
        return true
    }
}

Deklarieren Sie nun ExpandedControlsActivity im AndroidManifest.xml innerhalb des application-Tags über dem OPTIONS_PROVIDER_CLASS_NAME:

<application>
    ...
    <activity
        android:name="com.google.sample.cast.refplayer.expandedcontrols.ExpandedControlsActivity"
        android:label="@string/app_name"
        android:launchMode="singleTask"
        android:theme="@style/Theme.CastVideosDark"
        android:screenOrientation="portrait"
        android:exported="true">
        <intent-filter>
            <action android:name="android.intent.action.MAIN"/>
        </intent-filter>
        <meta-data
            android:name="android.support.PARENT_ACTIVITY"
            android:value="com.google.sample.cast.refplayer.VideoBrowserActivity"/>
    </activity>
    ...
</application>

Bearbeiten Sie CastOptionsProvider und ändern Sie NotificationOptions und CastMediaOptions, um die Zielaktivität auf ExpandedControlsActivity festzulegen:

import com.google.sample.cast.refplayer.expandedcontrols.ExpandedControlsActivity

override fun getCastOptions(context: Context): CastOptions {
    val notificationOptions = NotificationOptions.Builder()
            .setTargetActivityClassName(ExpandedControlsActivity::class.java.name)
            .build()
    val mediaOptions = CastMediaOptions.Builder()
            .setNotificationOptions(notificationOptions)
            .setExpandedControllerActivityClassName(ExpandedControlsActivity::class.java.name)
            .build()
    return CastOptions.Builder()
            .setReceiverApplicationId(context.getString(R.string.app_id))
            .setCastMediaOptions(mediaOptions)
            .build()
}

Aktualisieren Sie die Methode LocalPlayerActivity loadRemoteMedia, um ExpandedControlsActivity anzuzeigen, wenn die Remote-Media geladen werden:

import com.google.sample.cast.refplayer.expandedcontrols.ExpandedControlsActivity

private fun loadRemoteMedia(position: Int, autoPlay: Boolean) {
    if (mCastSession == null) {
        return
    }
    val remoteMediaClient = mCastSession!!.remoteMediaClient ?: return
    remoteMediaClient.registerCallback(object : RemoteMediaClient.Callback() {
        override fun onStatusUpdated() {
            val intent = Intent(this@LocalPlayerActivity, ExpandedControlsActivity::class.java)
            startActivity(intent)
            remoteMediaClient.unregisterCallback(this)
        }
    })
    remoteMediaClient.load(MediaLoadRequestData.Builder()
                .setMediaInfo(buildMediaInfo())
                .setAutoplay(autoPlay)
                .setCurrentTime(position.toLong()).build())
}

Klicken Sie auf die Schaltfläche Die Schaltfläche „Ausführen“ in Android Studio, ein grünes Dreieck, das nach rechts zeigtRun (Ausführen), um die App auf Ihrem Mobilgerät auszuführen und ein Video zu streamen. Der erweiterte Controller sollte angezeigt werden. Kehre zur Liste der Videos zurück. Wenn du auf die Mini-Steuerung klickst, wird die erweiterte Steuerung wieder geladen. Verlasse die App, um die Benachrichtigung zu sehen. Klicke auf das Benachrichtigungsbild, um den maximierten Controller zu laden.

11. Cast Connect-Unterstützung hinzufügen

Mit der Cast Connect-Bibliothek können vorhandene Senderanwendungen über das Cast-Protokoll mit Android TV-Anwendungen kommunizieren. Cast Connect basiert auf der Cast-Infrastruktur. Ihre Android TV-App fungiert dabei als Empfänger.

Abhängigkeiten

Hinweis: Für die Implementierung von Cast Connect muss play-services-cast-framework mindestens 19.0.0 sein.

LaunchOptions

Damit die Android TV-Anwendung, auch als Android-Receiver bezeichnet, gestartet werden kann, muss das Flag setAndroidReceiverCompatible im LaunchOptions-Objekt auf „true“ gesetzt werden. Dieses LaunchOptions-Objekt bestimmt, wie der Receiver gestartet wird, und wird an das CastOptions übergeben, das von der Klasse CastOptionsProvider zurückgegeben wird. Wenn Sie das oben genannte Flag auf false setzen, wird der Web-Receiver für die definierte App-ID in der Cast Developer Console gestartet.

Fügen Sie in der Datei CastOptionsProvider.kt der Methode getCastOptions Folgendes hinzu:

import com.google.android.gms.cast.LaunchOptions
...
val launchOptions = LaunchOptions.Builder()
            .setAndroidReceiverCompatible(true)
            .build()
return new CastOptions.Builder()
        .setLaunchOptions(launchOptions)
        ...
        .build()

Startanmeldedaten festlegen

Auf der Senderseite können Sie CredentialsData angeben, um darzustellen, wer der Sitzung beitritt. credentials ist ein String, der vom Nutzer definiert werden kann, sofern Ihre ATV-App ihn interpretieren kann. Der CredentialsData wird nur beim Start oder beim Beitreten an Ihre Android TV-App übergeben. Wenn Sie die Einstellung noch einmal festlegen, während Sie verbunden sind, wird sie nicht an Ihre Android TV-App übergeben.

Damit Startanmeldedaten festgelegt werden können, muss CredentialsData definiert und an das LaunchOptions-Objekt übergeben werden. Fügen Sie der Methode getCastOptions in Ihrer CastOptionsProvider.kt-Datei den folgenden Code hinzu:

import com.google.android.gms.cast.CredentialsData
...

val credentialsData = CredentialsData.Builder()
        .setCredentials("{\"userId\": \"abc\"}")
        .build()
val launchOptions = LaunchOptions.Builder()
       ...
       .setCredentialsData(credentialsData)
       .build()

Anmeldedaten für LoadRequest festlegen

Wenn Ihre Web Receiver-App und Ihre Android TV-App credentials unterschiedlich verarbeiten, müssen Sie möglicherweise separate credentials für jede App definieren. Fügen Sie dazu in Ihrer LocalPlayerActivity.kt-Datei unter der Funktion loadRemoteMedia den folgenden Code hinzu:

remoteMediaClient.load(MediaLoadRequestData.Builder()
       ...
       .setCredentials("user-credentials")
       .setAtvCredentials("atv-user-credentials")
       .build())

Je nachdem, auf welche Empfänger-App der Absender streamt, wird im SDK jetzt automatisch festgelegt, welche Anmeldedaten für die aktuelle Sitzung verwendet werden.

Cast Connect testen

So installierst du die Android TV-APK auf dem Chromecast mit Google TV

  1. Finde die IP-Adresse deines Android TV-Geräts. Normalerweise finden Sie sie unter Einstellungen > Netzwerk & Internet > (Name des Netzwerks, mit dem Ihr Gerät verbunden ist). Rechts werden die Details und die IP-Adresse Ihres Geräts im Netzwerk angezeigt.
  2. Verwenden Sie die IP-Adresse Ihres Geräts, um über das Terminal eine Verbindung über ADB herzustellen:
$ adb connect <device_ip_address>:5555
  1. Wechseln Sie im Terminalfenster in den Ordner der obersten Ebene für die Codelab-Beispiele, die Sie zu Beginn dieses Codelabs heruntergeladen haben. Beispiel:
$ cd Desktop/android_codelab_src
  1. Installieren Sie die APK-Datei in diesem Ordner auf Ihrem Android TV-Gerät, indem Sie Folgendes ausführen:
$ adb -s <device_ip_address>:5555 install android-tv-app.apk
  1. In der Meine Apps-Ansicht auf deinem Android TV-Gerät sollte jetzt die App Videos streamen angezeigt werden.
  2. Kehren Sie zu Ihrem Android Studio-Projekt zurück und klicken Sie auf die Schaltfläche „Ausführen“, um die Sender-App auf Ihrem physischen Mobilgerät zu installieren und auszuführen. Klicke oben rechts auf das Cast-Symbol und wähle dein Android TV-Gerät aus den verfügbaren Optionen aus. Die Android TV App sollte jetzt auf deinem Android TV-Gerät gestartet werden. Wenn du ein Video abspielst, solltest du die Videowiedergabe mit deiner Android TV-Fernbedienung steuern können.

12. Cast-Widgets anpassen

Du kannst Cast-Widgets anpassen, indem du die Farben festlegst, die Schaltflächen, den Text und die Darstellung von Thumbnails gestaltest und die Arten von Schaltflächen auswählst, die angezeigt werden sollen.

res/values/styles_castvideo.xml aktualisieren

<style name="Theme.CastVideosTheme" parent="Theme.AppCompat.Light.NoActionBar">
    ...
    <item name="mediaRouteTheme">@style/CustomMediaRouterTheme</item>
    <item name="castIntroOverlayStyle">@style/CustomCastIntroOverlay</item>
    <item name="castMiniControllerStyle">@style/CustomCastMiniController</item>
    <item name="castExpandedControllerStyle">@style/CustomCastExpandedController</item>
    <item name="castExpandedControllerToolbarStyle">
        @style/ThemeOverlay.AppCompat.ActionBar
    </item>
    ...
</style>

Deklarieren Sie die folgenden benutzerdefinierten Designs:

<!-- Customize Cast Button -->
<style name="CustomMediaRouterTheme" parent="Theme.MediaRouter">
    <item name="mediaRouteButtonStyle">@style/CustomMediaRouteButtonStyle</item>
</style>
<style name="CustomMediaRouteButtonStyle" parent="Widget.MediaRouter.Light.MediaRouteButton">
    <item name="mediaRouteButtonTint">#EEFF41</item>
</style>

<!-- Customize Introductory Overlay -->
<style name="CustomCastIntroOverlay" parent="CastIntroOverlay">
    <item name="castButtonTextAppearance">@style/TextAppearance.CustomCastIntroOverlay.Button</item>
    <item name="castTitleTextAppearance">@style/TextAppearance.CustomCastIntroOverlay.Title</item>
</style>
<style name="TextAppearance.CustomCastIntroOverlay.Button" parent="android:style/TextAppearance">
    <item name="android:textColor">#FFFFFF</item>
</style>
<style name="TextAppearance.CustomCastIntroOverlay.Title" parent="android:style/TextAppearance.Large">
    <item name="android:textColor">#FFFFFF</item>
</style>

<!-- Customize Mini Controller -->
<style name="CustomCastMiniController" parent="CastMiniController">
    <item name="castShowImageThumbnail">true</item>
    <item name="castTitleTextAppearance">@style/TextAppearance.AppCompat.Subhead</item>
    <item name="castSubtitleTextAppearance">@style/TextAppearance.AppCompat.Caption</item>
    <item name="castBackground">@color/accent</item>
    <item name="castProgressBarColor">@color/orange</item>
</style>

<!-- Customize Expanded Controller -->
<style name="CustomCastExpandedController" parent="CastExpandedController">
    <item name="castButtonColor">#FFFFFF</item>
    <item name="castPlayButtonDrawable">@drawable/cast_ic_expanded_controller_play</item>
    <item name="castPauseButtonDrawable">@drawable/cast_ic_expanded_controller_pause</item>
    <item name="castStopButtonDrawable">@drawable/cast_ic_expanded_controller_stop</item>
</style>

13. Glückwunsch

Sie wissen jetzt, wie Sie eine Video-App mit den Cast SDK-Widgets unter Android für Google Cast optimieren.

Weitere Informationen finden Sie im Entwicklerleitfaden für Android-Absender.