App per Android TV compatibili con Google Cast

1. Panoramica

Logo di Google Cast

Questo codelab ti insegnerà a modificare un'app Android TV esistente per supportare la trasmissione e la comunicazione dalle tue app mittente Cast esistenti.

Che cos'è Google Cast e Cast Connect?

Google Cast consente agli utenti di trasmettere contenuti da un dispositivo mobile a una TV. Una tipica sessione di Google Cast è costituita da due componenti: un'applicazione mittente e un'applicazione ricevitore. Le applicazioni mittenti, come un'app mobile o un sito web come YouTube.com, avviano e controllano la riproduzione di un'applicazione ricevitore Cast. Le applicazioni ricevitore di trasmissione sono app HTML5 eseguite su dispositivi Chromecast e Android TV.

Quasi tutto lo stato di una sessione di trasmissione viene memorizzato nell'applicazione ricevitore. Quando lo stato viene aggiornato, ad esempio se viene caricato un nuovo elemento multimediale, viene trasmesso uno stato multimediale a tutti i mittenti. Queste trasmissioni contengono lo stato attuale della sessione di trasmissione. Le applicazioni mittenti utilizzano questo stato dei contenuti multimediali per visualizzare le informazioni sulla riproduzione nella propria UI.

Cast Connect si basa su questa infrastruttura e la tua app Android TV funge da ricevitore. La libreria Cast Connect consente alla tua app Android TV di ricevere messaggi e trasmettere lo stato dei contenuti multimediali come se fosse un'applicazione ricevitore Cast.

Cosa realizzeremo

Al termine di questo codelab, potrai utilizzare le app mittenti Cast per trasmettere video a un'app Android TV. L'app Android TV può anche comunicare con le app mittenti tramite il protocollo Cast.

Obiettivi didattici

  • Come aggiungere la libreria Cast Connect a un'app ATV di esempio.
  • Come connettere un mittente Cast e avviare l'app ATV.
  • Come avviare la riproduzione di contenuti multimediali nell'app ATV da un'app mittente Cast.
  • Come inviare lo stato dei contenuti multimediali dall'app ATV alle app mittenti Cast.

Che cosa ti serve

2. recupera il codice campione

Puoi scaricare tutto il codice di esempio sul tuo computer…

ed estrai il file ZIP scaricato.

3. Esegui l'app di esempio

Innanzitutto, vediamo come appare l'app di esempio completata. L'app Android TV utilizza l'interfaccia utente Leanback e un video player di base. L'utente può selezionare un video da un elenco, che viene poi riprodotto sulla TV quando viene selezionato. Con l'app mittente mobile di accompagnamento, un utente può anche trasmettere un video all'app Android TV.

Immagine di una serie di miniature di video (una delle quali è evidenziata) sovrapposte a un'anteprima a schermo intero di un video; le parole "Cast Connect" che appaiono in alto a destra

Registrare i dispositivi dello sviluppatore

Per attivare le funzionalità di Cast Connect per lo sviluppo di applicazioni, devi registrare il numero di serie di Google Cast del dispositivo Android TV che utilizzerai nella Cast Developer Console. Puoi trovare il numero di serie andando su Impostazioni > Preferenze del dispositivo > Google Cast > Numero di serie su Android TV. Tieni presente che è diverso dal numero di serie del dispositivo fisico e deve essere ottenuto con il metodo descritto sopra.

Immagine di una schermata di Android TV che mostra la schermata "Google Cast", il numero di versione e il numero di serie

Senza registrazione, Cast Connect funzionerà solo per le app installate dal Google Play Store per motivi di sicurezza. Dopo 15 minuti dall'avvio della procedura di registrazione, riavvia il dispositivo.

Installare l'app mittente Android

Per testare l'invio di richieste da un dispositivo mobile, abbiamo fornito una semplice applicazione di invio chiamata Cast Videos come file mobile-sender-0629.apk nel download del file zip del codice sorgente. Utilizzeremo ADB per installare l'APK. Se hai già installato una versione diversa di Cast Videos, disinstallala da tutti i profili presenti sul dispositivo prima di continuare.

  1. Attiva le opzioni sviluppatore e il debug USB sullo smartphone Android.
  2. Collega un cavo dati USB per connettere lo smartphone Android al computer di sviluppo.
  3. Installa mobile-sender-0629.apk sul tuo smartphone Android.

Immagine di una finestra del terminale in cui viene eseguito il comando adb install per installare mobile-sender.apk

  1. Puoi trovare l'app mittente Trasmetti video sul tuo smartphone Android. Icona dell'app mittente Trasmetti video

Immagine dell'app mittente Trasmetti video in esecuzione sullo schermo di uno smartphone Android

Installare l'app Android TV

Le seguenti istruzioni descrivono come aprire ed eseguire l'app di esempio completata in Android Studio:

  1. Seleziona Importa progetto nella schermata di benvenuto o le opzioni di menu File > Nuovo > Importa progetto….
  2. Seleziona la directory icona cartellaapp-done dalla cartella del codice di esempio e fai clic su OK.
  3. Fai clic su File > Pulsante Sincronizza progetto con Gradle di Android App Studio Sincronizza progetto con file Gradle.
  4. Attiva le opzioni sviluppatore e il debug USB sul tuo dispositivo Android TV.
  5. ADB connect con il tuo dispositivo Android TV, il dispositivo dovrebbe essere visualizzato in Android Studio. Immagine che mostra il dispositivo Android TV nella barra degli strumenti di Android Studio
  6. Fai clic sul pulsante Pulsante Esegui di Android Studio, un triangolo verde rivolto a destraEsegui. Dopo qualche secondo, dovrebbe essere visualizzata l'app ATV denominata Cast Connect Codelab.

Giocare a Cast Connect con l'app ATV

  1. Vai alla schermata Home di Android TV.
  2. Apri l'app mittente Trasmetti video dal tuo smartphone Android. Fai clic sul pulsante Trasmetti Icona del pulsante Trasmetti e seleziona il tuo dispositivo ATV.
  3. L'app Cast Connect Codelab ATV verrà avviata su ATV e il pulsante Trasmetti nel mittente indicherà che è connesso Icona del pulsante Trasmetti con colori invertiti.
  4. Seleziona un video dall'app ATV e il video inizierà a essere riprodotto su ATV.
  5. Sul tuo cellulare, ora è visibile un mini controller nella parte inferiore dell'app mittente. Puoi utilizzare il pulsante di riproduzione/pausa per controllare la riproduzione.
  6. Seleziona un video dal cellulare e riproducilo. Il video inizierà la riproduzione su ATV e il controller espanso verrà visualizzato sul mittente mobile.
  7. Blocca lo smartphone e, quando lo sblocchi, dovresti visualizzare una notifica nella schermata di blocco per controllare la riproduzione dei contenuti multimediali o interrompere la trasmissione.

Immagine di una sezione dello schermo di uno smartphone Android con un mini player che riproduce un video

4. Prepara il progetto iniziale

Ora che abbiamo verificato l'integrazione di Cast Connect nell'app completata, dobbiamo aggiungere il supporto di Cast Connect all'app di avvio che hai scaricato. Ora puoi creare il tuo progetto a partire da quello iniziale utilizzando Android Studio:

  1. Seleziona Importa progetto nella schermata di benvenuto o le opzioni di menu File > Nuovo > Importa progetto….
  2. Seleziona la directory icona cartellaapp-start dalla cartella del codice di esempio e fai clic su OK.
  3. Fai clic su File > Pulsante Sincronizza progetto con Gradle di Android Studio Sincronizza progetto con file Gradle.
  4. Seleziona il dispositivo ATV e fai clic sul pulsante Il pulsante Esegui di Android Studio, un triangolo verde rivolto a destraEsegui per eseguire l'app ed esplorare la UI. Barra degli strumenti di Android Studio che mostra il dispositivo Android TV selezionato

Immagine di una serie di miniature di video (una delle quali è evidenziata) sovrapposte a un'anteprima a schermo intero di un video; le parole "Cast Connect" che appaiono in alto a destra

Progettazione di app

L'app fornisce un elenco di video che l'utente può sfogliare. Gli utenti possono selezionare un video da riprodurre su Android TV. L'app è composta da due attività principali: MainActivity e PlaybackActivity.

MainActivity

Questa attività contiene un frammento (MainFragment). L'elenco dei video e i relativi metadati sono configurati nella classe MovieList e viene chiamato il metodo setupMovies() per creare un elenco di oggetti Movie.

Un oggetto Movie rappresenta un'entità video con titolo, descrizione, miniature delle immagini e URL del video. Ogni oggetto Movie è associato a un CardPresenter per presentare la miniatura del video con titolo e studio e viene passato a ArrayObjectAdapter.

Quando viene selezionato un elemento, l'oggetto Movie corrispondente viene passato a PlaybackActivity.

PlaybackActivity

Questa attività contiene un frammento (PlaybackVideoFragment) che ospita un VideoView con ExoPlayer, alcuni controlli multimediali e un'area di testo per mostrare la descrizione del video selezionato e consentire all'utente di riprodurlo su Android TV. L'utente può utilizzare il telecomando per riprodurre/mettere in pausa o scorrere la riproduzione dei video.

Prerequisiti di Cast Connect

Cast Connect utilizza nuove versioni di Google Play Services che richiedono l'aggiornamento dell'app ATV per utilizzare lo spazio dei nomi AndroidX.

Per supportare Cast Connect nella tua app Android TV, devi creare e supportare eventi da una sessione multimediale. La libreria Cast Connect genera lo stato dei contenuti multimediali in base allo stato della sessione multimediale. La sessione multimediale viene utilizzata anche dalla libreria Cast Connect per segnalare quando ha ricevuto determinati messaggi da un mittente, ad esempio la pausa.

5. Configurazione del supporto di Cast

Dipendenze

Aggiorna il file build.gradle dell'app per includere le dipendenze della libreria necessarie:

dependencies {
    ....

    // Cast Connect libraries
    implementation 'com.google.android.gms:play-services-cast-tv:20.0.0'
    implementation 'com.google.android.gms:play-services-cast:21.1.0'
}

Sincronizza il progetto per verificare che la build venga creata senza errori.

Inizializzazione

CastReceiverContext è un oggetto singleton per coordinare tutte le interazioni di Cast. Devi implementare l'interfaccia ReceiverOptionsProvider per fornire CastReceiverOptions quando CastReceiverContext viene inizializzato.

Crea il file CastReceiverOptionsProvider.kt e aggiungi la seguente classe al progetto:

package com.google.sample.cast.castconnect

import android.content.Context
import com.google.android.gms.cast.tv.ReceiverOptionsProvider
import com.google.android.gms.cast.tv.CastReceiverOptions

class CastReceiverOptionsProvider : ReceiverOptionsProvider {
    override fun getOptions(context: Context): CastReceiverOptions {
        return CastReceiverOptions.Builder(context)
                .setStatusText("Cast Connect Codelab")
                .build()
    }
}

Quindi, specifica il fornitore delle opzioni del destinatario all'interno del tag <application> del file AndroidManifest.xml dell'app:

<application>
  ...
  <meta-data
    android:name="com.google.android.gms.cast.tv.RECEIVER_OPTIONS_PROVIDER_CLASS_NAME"
    android:value="com.google.sample.cast.castconnect.CastReceiverOptionsProvider" />
</application>

Per connetterti all'app ATV dal mittente della trasmissione, seleziona un'attività che vuoi avviare. In questo codelab, avvieremo l'MainActivity dell'app quando viene avviata una sessione di Cast. Nel file AndroidManifest.xml, aggiungi il filtro per intent di avvio in MainActivity.

<activity android:name=".MainActivity">
  ...
  <intent-filter>
    <action android:name="com.google.android.gms.cast.tv.action.LAUNCH" />
    <category android:name="android.intent.category.DEFAULT" />
  </intent-filter>
</activity>

Ciclo di vita del contesto del ricevitore Cast

Devi avviare CastReceiverContext all'avvio dell'app e arrestare CastReceiverContext quando l'app viene spostata in background. Ti consigliamo di utilizzare LifecycleObserver della libreria androidx.lifecycle per gestire la chiamata di CastReceiverContext.start() e CastReceiverContext.stop().

Apri il file MyApplication.kt, inizializza il contesto di trasmissione chiamando initInstance() nel metodo onCreate dell'applicazione. Nella AppLifeCycleObserver classe start(), CastReceiverContext quando l'applicazione viene ripresa e stop() quando viene sospesa:

package com.google.sample.cast.castconnect

import com.google.android.gms.cast.tv.CastReceiverContext
...

class MyApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        CastReceiverContext.initInstance(this)
        ProcessLifecycleOwner.get().lifecycle.addObserver(AppLifecycleObserver())
    }

    class AppLifecycleObserver : DefaultLifecycleObserver {
        override fun onResume(owner: LifecycleOwner) {
            Log.d(LOG_TAG, "onResume")
            CastReceiverContext.getInstance().start()
        }

        override fun onPause(owner: LifecycleOwner) {
            Log.d(LOG_TAG, "onPause")
            CastReceiverContext.getInstance().stop()
        }
    }
}

Connessione di MediaSession a MediaManager

MediaManager è una proprietà del singleton CastReceiverContext, gestisce lo stato dei contenuti multimediali, gestisce l'intent di caricamento, traduce i messaggi dello spazio dei nomi dei contenuti multimediali dai mittenti in comandi multimediali e invia lo stato dei contenuti multimediali ai mittenti.

Quando crei un MediaSession, devi anche fornire il token MediaSession corrente a MediaManager in modo che sappia dove inviare i comandi e recuperare lo stato di riproduzione dei contenuti multimediali. Nel file PlaybackVideoFragment.kt, assicurati che MediaSession sia inizializzato prima di impostare il token su MediaManager.

import com.google.android.gms.cast.tv.CastReceiverContext
import com.google.android.gms.cast.tv.media.MediaManager
...

class PlaybackVideoFragment : VideoSupportFragment() {
    private var castReceiverContext: CastReceiverContext? = null
    ...

    private fun initializePlayer() {
        if (mPlayer == null) {
            ...
            mMediaSession = MediaSessionCompat(getContext(), LOG_TAG)
            ...
            castReceiverContext = CastReceiverContext.getInstance()
            if (castReceiverContext != null) {
                val mediaManager: MediaManager = castReceiverContext!!.getMediaManager()
                mediaManager.setSessionCompatToken(mMediaSession!!.getSessionToken())
            }

        }
    }
}

Quando rilasci il tuo MediaSession a causa della riproduzione inattiva, devi impostare un token nullo su MediaManager:

private fun releasePlayer() {
    mMediaSession?.release()
    castReceiverContext?.mediaManager?.setSessionCompatToken(null)
    ...
}

Eseguiamo l'app di esempio

Fai clic sul pulsante Il pulsante Esegui di Android Studio, un triangolo verde rivolto a destraEsegui per eseguire il deployment dell'app sul tuo dispositivo ATV, chiudere l'app e tornare alla schermata Home di ATV. Dal mittente, fai clic sul pulsante Trasmetti Icona del pulsante Trasmetti e seleziona il tuo dispositivo ATV. Vedrai che l'app ATV viene avviata sul dispositivo ATV e lo stato del pulsante Trasmetti è Connesso.

6. Caricamento dei contenuti multimediali

Il comando di caricamento viene inviato tramite un intent con il nome del pacchetto definito nella console per gli sviluppatori. Devi aggiungere il seguente filtro per intent predefinito nella tua app Android TV per specificare l'attività di destinazione che riceverà questo intent. Nel file AndroidManifest.xml, aggiungi il filtro per intent di caricamento a PlayerActivity:

<activity android:name="com.google.sample.cast.castconnect.PlaybackActivity"
          android:launchMode="singleTask"
          android:exported="true">
  <intent-filter>
     <action android:name="com.google.android.gms.cast.tv.action.LOAD"/>
     <category android:name="android.intent.category.DEFAULT" />
  </intent-filter>
</activity>

Gestione delle richieste di caricamento su Android TV

Ora che l'attività è configurata per ricevere questo intent contenente una richiesta di caricamento, dobbiamo gestirlo.

L'app chiama un metodo privato denominato processIntent all'avvio dell'attività. Questo metodo contiene la logica per l'elaborazione degli intent in entrata. Per gestire una richiesta di caricamento, modificheremo questo metodo e invieremo l'intent da elaborare ulteriormente chiamando il metodo onNewIntent dell'istanza MediaManager. Se MediaManager rileva che l'intent è una richiesta di caricamento, estrae l'oggetto MediaLoadRequestData dall'intent e richiama MediaLoadCommandCallback.onLoad(). Modifica il metodo processIntent nel file PlaybackVideoFragment.kt per gestire l'intent contenente la richiesta di caricamento:

fun processIntent(intent: Intent?) {
    val mediaManager: MediaManager = CastReceiverContext.getInstance().getMediaManager()
    // Pass intent to Cast SDK
    if (mediaManager.onNewIntent(intent)) {
        return
    }

    // Clears all overrides in the modifier.
    mediaManager.getMediaStatusModifier().clear()

    // If the SDK doesn't recognize the intent, handle the intent with your own logic.
    ...
}

Successivamente, estenderemo la classe astratta MediaLoadCommandCallback, che sostituirà il metodo onLoad() chiamato da MediaManager. Questo metodo riceve i dati della richiesta di caricamento e li converte in un oggetto Movie. Una volta convertito, il film viene riprodotto dal player locale. Il MediaManager viene quindi aggiornato con il MediaLoadRequest e trasmette il MediaStatus ai mittenti connessi. Crea una classe privata nidificata denominata MyMediaLoadCommandCallback nel file PlaybackVideoFragment.kt:

import com.google.android.gms.cast.MediaLoadRequestData
import com.google.android.gms.cast.MediaInfo
import com.google.android.gms.cast.MediaMetadata
import com.google.android.gms.cast.MediaError
import com.google.android.gms.cast.tv.media.MediaException
import com.google.android.gms.cast.tv.media.MediaCommandCallback
import com.google.android.gms.cast.tv.media.QueueUpdateRequestData
import com.google.android.gms.cast.tv.media.MediaLoadCommandCallback
import com.google.android.gms.tasks.Task
import com.google.android.gms.tasks.Tasks
import android.widget.Toast
...

private inner class MyMediaLoadCommandCallback :  MediaLoadCommandCallback() {
    override fun onLoad(
        senderId: String?, mediaLoadRequestData: MediaLoadRequestData): Task<MediaLoadRequestData> {
        Toast.makeText(activity, "onLoad()", Toast.LENGTH_SHORT).show()
        return if (mediaLoadRequestData == null) {
            // Throw MediaException to indicate load failure.
            Tasks.forException(MediaException(
                MediaError.Builder()
                    .setDetailedErrorCode(MediaError.DetailedErrorCode.LOAD_FAILED)
                    .setReason(MediaError.ERROR_REASON_INVALID_REQUEST)
                    .build()))
        } else Tasks.call {
            play(convertLoadRequestToMovie(mediaLoadRequestData)!!)
            // Update media metadata and state
            val mediaManager = castReceiverContext!!.mediaManager
            mediaManager.setDataFromLoad(mediaLoadRequestData)
            mediaLoadRequestData
        }
    }
}

private fun convertLoadRequestToMovie(mediaLoadRequestData: MediaLoadRequestData?): Movie? {
    if (mediaLoadRequestData == null) {
        return null
    }
    val mediaInfo: MediaInfo = mediaLoadRequestData.getMediaInfo() ?: return null
    var videoUrl: String = mediaInfo.getContentId()
    if (mediaInfo.getContentUrl() != null) {
        videoUrl = mediaInfo.getContentUrl()
    }
    val metadata: MediaMetadata = mediaInfo.getMetadata()
    val movie = Movie()
    movie.videoUrl = videoUrl
    movie.title = metadata?.getString(MediaMetadata.KEY_TITLE)
    movie.description = metadata?.getString(MediaMetadata.KEY_SUBTITLE)
    if(metadata?.hasImages() == true) {
        movie.cardImageUrl = metadata.images[0].url.toString()
    }
    return movie
}

Ora che il callback è stato definito, dobbiamo registrarlo in MediaManager. Il richiamo deve essere registrato prima che venga chiamato il numero MediaManager.onNewIntent(). Aggiungi setMediaLoadCommandCallback quando il player viene inizializzato:

private fun initializePlayer() {
    if (mPlayer == null) {
        ...
        mMediaSession = MediaSessionCompat(getContext(), LOG_TAG)
        ...
        castReceiverContext = CastReceiverContext.getInstance()
        if (castReceiverContext != null) {
            val mediaManager: MediaManager = castReceiverContext.getMediaManager()
            mediaManager.setSessionCompatToken(mMediaSession.getSessionToken())
            mediaManager.setMediaLoadCommandCallback(MyMediaLoadCommandCallback())
        }
    }
}

Eseguiamo l'app di esempio

Fai clic sul pulsante Il pulsante Esegui di Android Studio, un triangolo verde rivolto a destraEsegui per implementare l'app sul tuo dispositivo ATV. Dal mittente, fai clic sul pulsante Trasmetti Icona del pulsante Trasmetti e seleziona il tuo dispositivo ATV. L'app ATV verrà avviata sul dispositivo ATV. Seleziona un video sul dispositivo mobile e inizierà la riproduzione su ATV. Controlla se ricevi una notifica sullo smartphone in cui sono presenti i controlli di riproduzione. Prova a utilizzare i controlli come la pausa. Il video sul dispositivo ATV dovrebbe essere messo in pausa.

7. Supporto dei comandi di controllo della trasmissione

L'applicazione attuale ora supporta i comandi di base compatibili con una sessione multimediale, come riproduci, pausa e cerca. Tuttavia, alcuni comandi di controllo della trasmissione non sono disponibili nella sessione multimediale. Per supportare questi comandi di controllo della trasmissione, devi registrare un MediaCommandCallback.

Aggiungi MyMediaCommandCallback all'istanza MediaManager utilizzando setMediaCommandCallback quando il player viene inizializzato:

private fun initializePlayer() {
    ...
    castReceiverContext = CastReceiverContext.getInstance()
    if (castReceiverContext != null) {
        val mediaManager = castReceiverContext!!.mediaManager
        ...
        mediaManager.setMediaCommandCallback(MyMediaCommandCallback())
    }
}

Crea la classe MyMediaCommandCallback per eseguire l'override dei metodi, ad esempio onQueueUpdate(), per supportare questi comandi di controllo della trasmissione:

private inner class MyMediaCommandCallback : MediaCommandCallback() {
    override fun onQueueUpdate(
        senderId: String?,
        queueUpdateRequestData: QueueUpdateRequestData
    ): Task<Void> {
        Toast.makeText(getActivity(), "onQueueUpdate()", Toast.LENGTH_SHORT).show()
        // Queue Prev / Next
        if (queueUpdateRequestData.getJump() != null) {
            Toast.makeText(
                getActivity(),
                "onQueueUpdate(): Jump = " + queueUpdateRequestData.getJump(),
                Toast.LENGTH_SHORT
            ).show()
        }
        return super.onQueueUpdate(senderId, queueUpdateRequestData)
    }
}

8. Utilizzo dello stato dei contenuti multimediali

Modificare lo stato dei contenuti multimediali

Cast Connect recupera lo stato di base dei contenuti multimediali dalla sessione multimediale. Per supportare le funzionalità avanzate, l'app Android TV può specificare ed eseguire l'override di proprietà di stato aggiuntive tramite un MediaStatusModifier. MediaStatusModifier opererà sempre sul MediaSession che hai impostato in CastReceiverContext.

Ad esempio, per specificare setMediaCommandSupported quando viene attivato il callback onLoad:

import com.google.android.gms.cast.MediaStatus
...
private class MyMediaLoadCommandCallback : MediaLoadCommandCallback() {
    fun onLoad(
        senderId: String?,
        mediaLoadRequestData: MediaLoadRequestData
    ): Task<MediaLoadRequestData> {
        Toast.makeText(getActivity(), "onLoad()", Toast.LENGTH_SHORT).show()
        ...
        return Tasks.call({
            play(convertLoadRequestToMovie(mediaLoadRequestData)!!)
            ...
            // Use MediaStatusModifier to provide additional information for Cast senders.
            mediaManager.getMediaStatusModifier()
                .setMediaCommandSupported(MediaStatus.COMMAND_QUEUE_NEXT, true)
                .setIsPlayingAd(false)
            mediaManager.broadcastMediaStatus()
            // Return the resolved MediaLoadRequestData to indicate load success.
            mediaLoadRequestData
        })
    }
}

Intercettazione di MediaStatus prima dell'invio

Analogamente a MessageInterceptor dell'SDK Web Receiver, puoi specificare un MediaStatusWriter in MediaManager per apportare ulteriori modifiche a MediaStatus prima che venga trasmesso ai mittenti connessi.

Ad esempio, puoi impostare dati personalizzati in MediaStatus prima di inviarli ai mittenti di dispositivi mobili:

import com.google.android.gms.cast.tv.media.MediaManager.MediaStatusInterceptor
import com.google.android.gms.cast.tv.media.MediaStatusWriter
import org.json.JSONObject
import org.json.JSONException
...

private fun initializePlayer() {
    if (mPlayer == null) {
        ...
        if (castReceiverContext != null) {
            ...
            val mediaManager: MediaManager = castReceiverContext.getMediaManager()
            ...
            // Use MediaStatusInterceptor to process the MediaStatus before sending out.
            mediaManager.setMediaStatusInterceptor(
                MediaStatusInterceptor { mediaStatusWriter: MediaStatusWriter ->
                    try {
                        mediaStatusWriter.setCustomData(JSONObject("{myData: 'CustomData'}"))
                    } catch (e: JSONException) {
                        Log.e(LOG_TAG,e.message,e);
                    }
            })
        }
    }
}        

9. Complimenti

Ora sai come attivare la trasmissione per un'app Android TV utilizzando la libreria Cast Connect.

Per ulteriori dettagli, consulta la guida per gli sviluppatori: /cast/docs/android_tv_receiver.