Wichtige Funktionen zu Ihrem Android TV-Receiver hinzufügen

Diese Seite enthält Code-Snippets und Beschreibungen der Funktionen, die zum Anpassen einer Android TV Receiver-App verfügbar sind.

Bibliotheken konfigurieren

So machen Sie Cast Connect APIs für Ihre Android TV App verfügbar:

Android
  1. Öffnen Sie die Datei build.gradle im Verzeichnis des Anwendungsmoduls.
  2. Prüfen Sie, ob google() im aufgeführten repositories enthalten ist.
      repositories {
        google()
      }
  3. Fügen Sie den Abhängigkeiten je nach Zielgerätetyp Ihrer App die neuesten Versionen der Bibliotheken hinzu:
    • Für die Android Receiver App:
        dependencies {
          implementation 'com.google.android.gms:play-services-cast-tv:21.0.1'
          implementation 'com.google.android.gms:play-services-cast:21.4.0'
        }
    • Für Android Sender App:
        dependencies {
          implementation 'com.google.android.gms:play-services-cast:21.0.1'
          implementation 'com.google.android.gms:play-services-cast-framework:21.4.0'
        }
    Achten Sie darauf, diese Versionsnummer jedes Mal zu aktualisieren, wenn die Dienste aktualisiert werden.
  4. Speichern Sie die Änderungen und klicken Sie in der Symbolleiste auf Sync Project with Gradle Files.
iOS
  1. Podfile muss auf google-cast-sdk 4.8.1 oder höher ausgerichtet sein
  2. Die Kampagne ist auf iOS 14 oder höher ausgerichtet. Weitere Informationen finden Sie in den Versionshinweisen.
      platform: ios, '14'
    
      def target_pods
         pod 'google-cast-sdk', '~>4.8.1'
      end
Web
  1. Chromium-Browserversion M87 oder höher erforderlich.
  2. Fügen Sie Ihrem Projekt
      <script src="//www.gstatic.com/cv/js/sender/v1/cast_sender.js?loadCastFramework=1"></script>
    die Web Sender API-Bibliothek hinzu

AndroidX-Anforderung

Neue Versionen der Google Play-Dienste erfordern, dass eine App zur Verwendung des Namespace androidx aktualisiert wurde. Folgen Sie der Anleitung unter Migration zu Android X.

Voraussetzungen für die Android TV App

Damit Cast Connect in deiner Android TV App unterstützt werden kann, musst du Ereignisse aus einer Mediensitzung erstellen und unterstützen. Die von Ihrer Mediensitzung bereitgestellten Daten liefern die grundlegenden Informationen für Ihren Medienstatus, z. B. Position, Wiedergabestatus usw. Die Mediensitzung wird auch von der Cast Connect-Bibliothek verwendet, um zu signalisieren, wann bestimmte Nachrichten von einem Absender empfangen wurden, z. B. „Pause“.

Weitere Informationen zu Mediensitzungen und zum Initialisieren einer Mediensitzung finden Sie im Leitfaden zum Arbeiten mit Mediensitzungen.

Lebenszyklus von Mediensitzungen

Ihre App sollte zu Beginn der Wiedergabe eine Mediensitzung erstellen und sie loslassen, wenn sie nicht mehr gesteuert werden kann. Wenn es sich bei Ihrer App beispielsweise um eine Video-App handelt, sollten Sie die Sitzung beenden, sobald der Nutzer die Wiedergabe beendet. Dazu wählen Sie entweder „Zurück“ aus, um andere Inhalte zu durchsuchen, oder indem Sie die App im Hintergrund öffnen. Ist Ihre App eine Musik-App, sollten Sie sie loslassen, sobald in Ihrer App keine Medien mehr abgespielt werden.

Sitzungsstatus wird aktualisiert

Die Daten in Ihrer Mediensitzung sollten immer mit dem Status Ihres Players aktualisiert werden. Wenn die Wiedergabe beispielsweise pausiert ist, solltest du den Wiedergabestatus sowie die unterstützten Aktionen aktualisieren. In den folgenden Tabellen sind die Status aufgeführt, für die Sie verantwortlich sind, sie auf dem neuesten Stand zu halten.

MediaMetadataCompat

Metadatenfeld Beschreibung
METADATA_KEY_TITLE (erforderlich) Der Medientitel.
METADATA_KEY_DISPLAY_SUBTITLE Die Untertitel
METADATA_KEY_DISPLAY_ICON_URI Die Symbol-URL.
METADATA_KEY_DURATION (erforderlich) Mediendauer.
METADATA_KEY_MEDIA_URI Die Content ID.
METADATA_KEY_ARTIST Der Künstler.
METADATA_KEY_ALBUM Das Album

PlaybackStateCompat

Erforderliche Methode Beschreibung
setActions() Legt unterstützte Medienbefehle fest.
setState() Legen Sie den Wiedergabestatus und die aktuelle Position fest.

MediaSessionCompat

Erforderliche Methode Beschreibung
setRepeatMode() Legt den Wiederholungsmodus fest.
setShuffleMode() Legt den Zufallsmix fest.
setMetadata() Legt Medienmetadaten fest.
setPlaybackState() Legt den Wiedergabestatus fest.
Kotlin
private fun updateMediaSession() {
    val metadata = MediaMetadataCompat.Builder()
         .putString(MediaMetadataCompat.METADATA_KEY_TITLE, "title")
         .putString(MediaMetadataCompat.METADATA_KEY_DISPLAY_SUBTITLE, "subtitle")
         .putString(MediaMetadataCompat.METADATA_KEY_DISPLAY_ICON_URI, mMovie.getCardImageUrl())
         .build()

    val playbackState = PlaybackStateCompat.Builder()
         .setState(
             PlaybackStateCompat.STATE_PLAYING,
             player.getPosition(),
             player.getPlaybackSpeed(),
             System.currentTimeMillis()
        )
         .build()

    mediaSession.setMetadata(metadata)
    mediaSession.setPlaybackState(playbackState)
}
Java
private void updateMediaSession() {
  MediaMetadataCompat metadata =
      new MediaMetadataCompat.Builder()
          .putString(MediaMetadataCompat.METADATA_KEY_TITLE, "title")
          .putString(MediaMetadataCompat.METADATA_KEY_DISPLAY_SUBTITLE, "subtitle")
          .putString(MediaMetadataCompat.METADATA_KEY_DISPLAY_ICON_URI,mMovie.getCardImageUrl())
          .build();

  PlaybackStateCompat playbackState =
      new PlaybackStateCompat.Builder()
          .setState(
               PlaybackStateCompat.STATE_PLAYING,
               player.getPosition(),
               player.getPlaybackSpeed(),
               System.currentTimeMillis())
          .build();

  mediaSession.setMetadata(metadata);
  mediaSession.setPlaybackState(playbackState);
}

Transportsteuerung

Deine App sollte einen Callback für die Transportsteuerung für Mediensitzungen implementieren. Die folgende Tabelle zeigt, welche Transportsteuerungsaktionen sie verarbeiten müssen:

MediaSessionCompat.Callback

Aktionen Beschreibung
onPlay() Fortsetzen
onPause() Pausieren
onSeekTo() Zu einer Position springen
onStop() Aktuelles Medium anhalten
Kotlin
class MyMediaSessionCallback : MediaSessionCompat.Callback() {
  override fun onPause() {
    // Pause the player and update the play state.
    ...
  }

  override fun onPlay() {
    // Resume the player and update the play state.
    ...
  }

  override fun onSeekTo (long pos) {
    // Seek and update the play state.
    ...
  }
  ...
}

mediaSession.setCallback( MyMediaSessionCallback() );
Java
public MyMediaSessionCallback extends MediaSessionCompat.Callback {
  public void onPause() {
    // Pause the player and update the play state.
    ...
  }

  public void onPlay() {
    // Resume the player and update the play state.
    ...
  }

  public void onSeekTo (long pos) {
    // Seek and update the play state.
    ...
  }
  ...
}

mediaSession.setCallback(new MyMediaSessionCallback());

Cast-Unterstützung konfigurieren

Wenn eine Startanfrage von einer Absenderanwendung gesendet wird, wird ein Intent mit einem Anwendungs-Namespace erstellt. Ihre App ist dafür verantwortlich, diese zu verarbeiten und eine Instanz des CastReceiverContext-Objekts zu erstellen, wenn die TV-App gestartet wird. Das CastReceiverContext-Objekt wird benötigt, um mit Cast zu interagieren, während die TV-App ausgeführt wird. Mit diesem Objekt kann deine TV-App gestreamte Mediennachrichten von verbundenen Absendern akzeptieren.

Einrichtung von Android TV

Filter für Startabsicht hinzufügen

Fügen Sie der Aktivität, mit der Sie den Start-Intent von Ihrer Absender-App verarbeiten möchten, einen neuen Intent-Filter hinzu:

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

Anbieter für Empfängeroptionen angeben

Du musst einen ReceiverOptionsProvider implementieren, um CastReceiverOptions bereitzustellen:

Kotlin
class MyReceiverOptionsProvider : ReceiverOptionsProvider {
  override fun getOptions(context: Context?): CastReceiverOptions {
    return CastReceiverOptions.Builder(context)
          .setStatusText("My App")
          .build()
    }
}
Java
public class MyReceiverOptionsProvider implements ReceiverOptionsProvider {
  @Override
  public CastReceiverOptions getOptions(Context context) {
    return new CastReceiverOptions.Builder(context)
        .setStatusText("My App")
        .build();
  }
}

Geben Sie dann den Optionsanbieter in Ihrem AndroidManifest an:

 <meta-data
    android:name="com.google.android.gms.cast.tv.RECEIVER_OPTIONS_PROVIDER_CLASS_NAME"
    android:value="com.example.mysimpleatvapplication.MyReceiverOptionsProvider" />

Der ReceiverOptionsProvider wird verwendet, um den CastReceiverOptions bereitzustellen, wenn CastReceiverContext initialisiert wird.

Kontext des Streamingempfängers

Initialisieren Sie CastReceiverContext, wenn Ihre App erstellt wird:

Kotlin
override fun onCreate() {
  CastReceiverContext.initInstance(this)

  ...
}
Java
@Override
public void onCreate() {
  CastReceiverContext.initInstance(this);

  ...
}

CastReceiverContext wird gestartet, wenn die App in den Vordergrund wechselt:

Kotlin
CastReceiverContext.getInstance().start()
Java
CastReceiverContext.getInstance().start();

Rufen Sie stop() auf dem CastReceiverContext auf, nachdem die App für Video-Apps oder Apps, die die Hintergrundwiedergabe nicht unterstützen, in den Hintergrund verschoben wurde:

Kotlin
// Player has stopped.
CastReceiverContext.getInstance().stop()
Java
// Player has stopped.
CastReceiverContext.getInstance().stop();

Wenn deine App die Hintergrundwiedergabe unterstützt, rufe außerdem stop() im CastReceiverContext auf, wenn die Wiedergabe im Hintergrund beendet wird.

Wir empfehlen dringend, den LifecycleObserver aus der Bibliothek androidx.lifecycle zu verwenden, um den Aufruf von CastReceiverContext.start() und CastReceiverContext.stop() zu verwalten, insbesondere wenn Ihre native App mehrere Aktivitäten hat. Dadurch werden Race-Bedingungen vermieden, wenn Sie start() und stop() von verschiedenen Aktivitäten aufrufen.

Kotlin
// Create a LifecycleObserver class.
class MyLifecycleObserver : DefaultLifecycleObserver {
  override fun onStart(owner: LifecycleOwner) {
    // App prepares to enter foreground.
    CastReceiverContext.getInstance().start()
  }

  override fun onStop(owner: LifecycleOwner) {
    // App has moved to the background or has terminated.
    CastReceiverContext.getInstance().stop()
  }
}

// Add the observer when your application is being created.
class MyApplication : Application() {
  fun onCreate() {
    super.onCreate()

    // Initialize CastReceiverContext.
    CastReceiverContext.initInstance(this /* android.content.Context */)

    // Register LifecycleObserver
    ProcessLifecycleOwner.get().lifecycle.addObserver(
        MyLifecycleObserver())
  }
}
Java
// Create a LifecycleObserver class.
public class MyLifecycleObserver implements DefaultLifecycleObserver {
  @Override
  public void onStart(LifecycleOwner owner) {
    // App prepares to enter foreground.
    CastReceiverContext.getInstance().start();
  }

  @Override
  public void onStop(LifecycleOwner owner) {
    // App has moved to the background or has terminated.
    CastReceiverContext.getInstance().stop();
  }
}

// Add the observer when your application is being created.
public class MyApplication extends Application {
  @Override
  public void onCreate() {
    super.onCreate();

    // Initialize CastReceiverContext.
    CastReceiverContext.initInstance(this /* android.content.Context */);

    // Register LifecycleObserver
    ProcessLifecycleOwner.get().getLifecycle().addObserver(
        new MyLifecycleObserver());
  }
}
// In AndroidManifest.xml set MyApplication as the application class
<application
    ...
    android:name=".MyApplication">

MediaSession mit MediaManager verbinden

Wenn Sie ein MediaSession erstellen, müssen Sie auch das aktuelle MediaSession-Token für CastReceiverContext bereitstellen, damit es weiß, wohin die Befehle gesendet und der Status der Medienwiedergabe abgerufen werden soll:

Kotlin
val mediaManager: MediaManager = receiverContext.getMediaManager()
mediaManager.setSessionCompatToken(currentMediaSession.getSessionToken())
Java
MediaManager mediaManager = receiverContext.getMediaManager();
mediaManager.setSessionCompatToken(currentMediaSession.getSessionToken());

Wenn du MediaSession aufgrund einer inaktiven Wiedergabe freigibst, solltest du für MediaManager ein Null-Token festlegen:

Kotlin
myPlayer.stop()
mediaSession.release()
mediaManager.setSessionCompatToken(null)
Java
myPlayer.stop();
mediaSession.release();
mediaManager.setSessionCompatToken(null);

Wenn Ihre App die Wiedergabe von Medien unterstützt, während die App im Hintergrund ausgeführt wird, sollten Sie statt CastReceiverContext.stop() nur dann CastReceiverContext.stop() aufrufen, wenn die App im Hintergrund ausgeführt wird und keine Medien mehr abspielt. Beispiel:

Kotlin
class MyLifecycleObserver : DefaultLifecycleObserver {
  ...
  // App has moved to the background.
  override fun onPause(owner: LifecycleOwner) {
    mIsBackground = true
    myStopCastReceiverContextIfNeeded()
  }
}

// Stop playback on the player.
private fun myStopPlayback() {
  myPlayer.stop()

  myStopCastReceiverContextIfNeeded()
}

// Stop the CastReceiverContext when both the player has
// stopped and the app has moved to the background.
private fun myStopCastReceiverContextIfNeeded() {
  if (mIsBackground && myPlayer.isStopped()) {
    CastReceiverContext.getInstance().stop()
  }
}
Java
public class MyLifecycleObserver implements DefaultLifecycleObserver {
  ...
  // App has moved to the background.
  @Override
  public void onPause(LifecycleOwner owner) {
    mIsBackground = true;

    myStopCastReceiverContextIfNeeded();
  }
}

// Stop playback on the player.
private void myStopPlayback() {
  myPlayer.stop();

  myStopCastReceiverContextIfNeeded();
}

// Stop the CastReceiverContext when both the player has
// stopped and the app has moved to the background.
private void myStopCastReceiverContextIfNeeded() {
  if (mIsBackground && myPlayer.isStopped()) {
    CastReceiverContext.getInstance().stop();
  }
}

Exoplayer mit Cast Connect verwenden

Wenn Sie Exoplayer verwenden, können Sie den MediaSessionConnector verwenden, um die Sitzung und alle zugehörigen Informationen, einschließlich des Wiedergabestatus, automatisch aufrechtzuerhalten, anstatt die Änderungen manuell zu verfolgen.

MediaSessionConnector.MediaButtonEventHandler kann verwendet werden, um MediaButton-Ereignisse durch Aufrufen von setMediaButtonEventHandler(MediaButtonEventHandler) zu verarbeiten, die ansonsten standardmäßig von MediaSessionCompat.Callback verarbeitet werden.

Um MediaSessionConnector in Ihre App zu integrieren, müssen Sie der Klasse „Player-Aktivität“ oder einem anderen Speicherort, an dem Sie Ihre Mediensitzung verwalten, Folgendes hinzufügen:

Kotlin
class PlayerActivity : Activity() {
  private var mMediaSession: MediaSessionCompat? = null
  private var mMediaSessionConnector: MediaSessionConnector? = null
  private var mMediaManager: MediaManager? = null

  override fun onCreate(savedInstanceState: Bundle?) {
    ...
    mMediaSession = MediaSessionCompat(this, LOG_TAG)
    mMediaSessionConnector = MediaSessionConnector(mMediaSession!!)
    ...
  }

  override fun onStart() {
    ...
    mMediaManager = receiverContext.getMediaManager()
    mMediaManager!!.setSessionCompatToken(currentMediaSession.getSessionToken())
    mMediaSessionConnector!!.setPlayer(mExoPlayer)
    mMediaSessionConnector!!.setMediaMetadataProvider(mMediaMetadataProvider)
    mMediaSession!!.isActive = true
    ...
  }

  override fun onStop() {
    ...
    mMediaSessionConnector!!.setPlayer(null)
    mMediaSession!!.release()
    mMediaManager!!.setSessionCompatToken(null)
    ...
  }
}
Java
public class PlayerActivity extends Activity {
  private MediaSessionCompat mMediaSession;
  private MediaSessionConnector mMediaSessionConnector;
  private MediaManager mMediaManager;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    ...
    mMediaSession = new MediaSessionCompat(this, LOG_TAG);
    mMediaSessionConnector = new MediaSessionConnector(mMediaSession);
    ...
  }

  @Override
  protected void onStart() {
    ...
    mMediaManager = receiverContext.getMediaManager();
    mMediaManager.setSessionCompatToken(currentMediaSession.getSessionToken());

    mMediaSessionConnector.setPlayer(mExoPlayer);
    mMediaSessionConnector.setMediaMetadataProvider(mMediaMetadataProvider);
    mMediaSession.setActive(true);
    ...
  }

  @Override
  protected void onStop() {
    ...
    mMediaSessionConnector.setPlayer(null);
    mMediaSession.release();
    mMediaManager.setSessionCompatToken(null);
    ...
  }
}

Sender-App einrichten

Cast Connect-Unterstützung aktivieren

Sobald Sie die Sender-App mit Cast Connect-Unterstützung aktualisiert haben, können Sie ihre Bereitschaft angeben, indem Sie das Flag androidReceiverCompatible auf LaunchOptions auf „true“ setzen.

Android

Erfordert play-services-cast-framework-Version 19.0.0 oder höher.

Das Flag androidReceiverCompatible wird in LaunchOptions festgelegt, das Teil von CastOptions ist:

Kotlin
class CastOptionsProvider : OptionsProvider {
  override fun getCastOptions(context: Context?): CastOptions {
    val launchOptions: LaunchOptions = Builder()
          .setAndroidReceiverCompatible(true)
          .build()
    return CastOptions.Builder()
          .setLaunchOptions(launchOptions)
          ...
          .build()
    }
}
Java
public class CastOptionsProvider implements OptionsProvider {
  @Override
  public CastOptions getCastOptions(Context context) {
    LaunchOptions launchOptions = new LaunchOptions.Builder()
              .setAndroidReceiverCompatible(true)
              .build();
    return new CastOptions.Builder()
        .setLaunchOptions(launchOptions)
        ...
        .build();
  }
}
iOS

Erfordert google-cast-sdk-Version v4.4.8 oder höher.

Das Flag androidReceiverCompatible wird in GCKLaunchOptions festgelegt, das Teil von GCKCastOptions ist:

let options = GCKCastOptions(discoveryCriteria: GCKDiscoveryCriteria(applicationID: kReceiverAppID))
...
let launchOptions = GCKLaunchOptions()
launchOptions.androidReceiverCompatible = true
options.launchOptions = launchOptions
GCKCastContext.setSharedInstanceWith(options)
Web

Erfordert die Chromium-Browserversion M87 oder höher.

const context = cast.framework.CastContext.getInstance();
const castOptions = new cast.framework.CastOptions();
castOptions.receiverApplicationId = kReceiverAppID;
castOptions.androidReceiverCompatible = true;
context.setOptions(castOptions);

Cast Developer Console einrichten

Android TV App konfigurieren

Füge den Paketnamen deiner Android TV-App in der Cast Developer Console hinzu, um sie mit deiner Cast App-ID zu verknüpfen.

Entwicklergeräte registrieren

Registriere die Seriennummer des Android TV-Geräts, das du für die Entwicklung in der Cast-Entwicklerkonsole verwenden möchtest.

Ohne Registrierung funktioniert Cast Connect aus Sicherheitsgründen nur bei Apps, die aus dem Google Play Store installiert wurden.

Weitere Informationen zur Registrierung eines Cast- oder Android TV-Geräts für die Cast-Entwicklung finden Sie auf der Registrierungsseite.

Medien werden geladen

Wenn Sie die Deeplink-Unterstützung bereits in Ihrer Android TV-App implementiert haben, sollten Sie in Ihrem Android TV-Manifest eine ähnliche Definition konfiguriert haben:

<activity android:name="com.example.activity">
  <intent-filter>
     <action android:name="android.intent.action.VIEW" />
     <category android:name="android.intent.category.DEFAULT" />
     <data android:scheme="https"/>
     <data android:host="www.example.com"/>
     <data android:pathPattern=".*"/>
  </intent-filter>
</activity>

Nach Entität beim Absender laden

Auf den Absendern können Sie den Deeplink übergeben. Dazu legen Sie in den Medieninformationen für die Ladeanfrage entity fest:

Kotlin
val mediaToLoad = MediaInfo.Builder("some-id")
    .setEntity("https://example.com/watch/some-id")
    ...
    .build()
val loadRequest = MediaLoadRequestData.Builder()
    .setMediaInfo(mediaToLoad)
    .setCredentials("user-credentials")
    ...
    .build()
remoteMediaClient.load(loadRequest)
Android
Java
MediaInfo mediaToLoad =
    new MediaInfo.Builder("some-id")
        .setEntity("https://example.com/watch/some-id")
        ...
        .build();
MediaLoadRequestData loadRequest =
    new MediaLoadRequestData.Builder()
        .setMediaInfo(mediaToLoad)
        .setCredentials("user-credentials")
        ...
        .build();
remoteMediaClient.load(loadRequest);
iOS
let mediaInfoBuilder = GCKMediaInformationBuilder(entity: "https://example.com/watch/some-id")
...
mediaInformation = mediaInfoBuilder.build()

let mediaLoadRequestDataBuilder = GCKMediaLoadRequestDataBuilder()
mediaLoadRequestDataBuilder.mediaInformation = mediaInformation
mediaLoadRequestDataBuilder.credentials = "user-credentials"
...
let mediaLoadRequestData = mediaLoadRequestDataBuilder.build()

remoteMediaClient?.loadMedia(with: mediaLoadRequestData)
Web

Erfordert die Chromium-Browserversion M87 oder höher.

let mediaInfo = new chrome.cast.media.MediaInfo('some-id"', 'video/mp4');
mediaInfo.entity = 'https://example.com/watch/some-id';
...

let request = new chrome.cast.media.LoadRequest(mediaInfo);
request.credentials = 'user-credentials';
...

cast.framework.CastContext.getInstance().getCurrentSession().loadMedia(request);

Der Ladebefehl wird über einen Intent mit Ihrem Deeplink und dem Paketnamen gesendet, den Sie in der Entwicklerkonsole definiert haben.

ATV-Anmeldedaten für Absender festlegen

Es ist möglich, dass deine Web Receiver-App und die Android TV-App unterschiedliche Deeplinks und credentials unterstützen (z. B. wenn die Authentifizierung auf den beiden Plattformen unterschiedlich verarbeitet wird). Um das Problem zu beheben, kannst du alternative entity und credentials für Android TV angeben:

Android
Kotlin
val mediaToLoad = MediaInfo.Builder("some-id")
        .setEntity("https://example.com/watch/some-id")
        .setAtvEntity("myscheme://example.com/atv/some-id")
        ...
        .build()
val loadRequest = MediaLoadRequestData.Builder()
        .setMediaInfo(mediaToLoad)
        .setCredentials("user-credentials")
        .setAtvCredentials("atv-user-credentials")
        ...
        .build()
remoteMediaClient.load(loadRequest)
Java
MediaInfo mediaToLoad =
    new MediaInfo.Builder("some-id")
        .setEntity("https://example.com/watch/some-id")
        .setAtvEntity("myscheme://example.com/atv/some-id")
        ...
        .build();
MediaLoadRequestData loadRequest =
    new MediaLoadRequestData.Builder()
        .setMediaInfo(mediaToLoad)
        .setCredentials("user-credentials")
        .setAtvCredentials("atv-user-credentials")
        ...
        .build();
remoteMediaClient.load(loadRequest);
iOS
let mediaInfoBuilder = GCKMediaInformationBuilder(entity: "https://example.com/watch/some-id")
mediaInfoBuilder.atvEntity = "myscheme://example.com/atv/some-id"
...
mediaInformation = mediaInfoBuilder.build()

let mediaLoadRequestDataBuilder = GCKMediaLoadRequestDataBuilder()
mediaLoadRequestDataBuilder.mediaInformation = mediaInformation
mediaLoadRequestDataBuilder.credentials = "user-credentials"
mediaLoadRequestDataBuilder.atvCredentials = "atv-user-credentials"
...
let mediaLoadRequestData = mediaLoadRequestDataBuilder.build()

remoteMediaClient?.loadMedia(with: mediaLoadRequestData)
Web

Erfordert die Chromium-Browserversion M87 oder höher.

let mediaInfo = new chrome.cast.media.MediaInfo('some-id"', 'video/mp4');
mediaInfo.entity = 'https://example.com/watch/some-id';
mediaInfo.atvEntity = 'myscheme://example.com/atv/some-id';
...

let request = new chrome.cast.media.LoadRequest(mediaInfo);
request.credentials = 'user-credentials';
request.atvCredentials = 'atv-user-credentials';
...

cast.framework.CastContext.getInstance().getCurrentSession().loadMedia(request);

Wenn die Web Receiver-Anwendung gestartet wird, verwendet sie entity und credentials in der Ladeanfrage. Wenn Ihre Android TV-App jedoch gestartet wird, überschreibt das SDK entity und credentials mit atvEntity und atvCredentials (falls angegeben).

Laden nach Content ID oder MediaQueueData

Wenn du nicht entity oder atvEntity verwendest und Content ID oder Content URL in deinen Medieninformationen oder die detaillierteren Media Load Request-Daten verwendest, musst du deiner Android TV-App den folgenden vordefinierten Intent-Filter hinzufügen:

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

Auf der Absenderseite können Sie ähnlich wie bei Laden nach Entität eine Ladeanfrage mit Ihren Inhaltsinformationen erstellen und load() aufrufen.

Android
Kotlin
val mediaToLoad = MediaInfo.Builder("some-id").build()
val loadRequest = MediaLoadRequestData.Builder()
    .setMediaInfo(mediaToLoad)
    .setCredentials("user-credentials")
    ...
    .build()
remoteMediaClient.load(loadRequest)
Java
MediaInfo mediaToLoad =
    new MediaInfo.Builder("some-id").build();
MediaLoadRequestData loadRequest =
    new MediaLoadRequestData.Builder()
        .setMediaInfo(mediaToLoad)
        .setCredentials("user-credentials")
        ...
        .build();
remoteMediaClient.load(loadRequest);
iOS
let mediaInfoBuilder = GCKMediaInformationBuilder(contentId: "some-id")
...
mediaInformation = mediaInfoBuilder.build()

let mediaLoadRequestDataBuilder = GCKMediaLoadRequestDataBuilder()
mediaLoadRequestDataBuilder.mediaInformation = mediaInformation
mediaLoadRequestDataBuilder.credentials = "user-credentials"
...
let mediaLoadRequestData = mediaLoadRequestDataBuilder.build()

remoteMediaClient?.loadMedia(with: mediaLoadRequestData)
Web

Erfordert die Chromium-Browserversion M87 oder höher.

let mediaInfo = new chrome.cast.media.MediaInfo('some-id"', 'video/mp4');
...

let request = new chrome.cast.media.LoadRequest(mediaInfo);
...

cast.framework.CastContext.getInstance().getCurrentSession().loadMedia(request);

Ladeanfragen verarbeiten

Zur Verarbeitung dieser Ladeanfragen müssen Sie in Ihrer Aktivität die Intents in Ihren Callbacks für den Aktivitätslebenszyklus verarbeiten:

Kotlin
class MyActivity : Activity() {
  override fun onStart() {
    super.onStart()
    val mediaManager = CastReceiverContext.getInstance().getMediaManager()
    // Pass the intent to the SDK. You can also do this in onCreate().
    if (mediaManager.onNewIntent(intent)) {
        // If the SDK recognizes the intent, you should early return.
        return
    }
    // If the SDK doesn't recognize the intent, you can handle the intent with
    // your own logic.
    ...
  }

  // For some cases, a new load intent triggers onNewIntent() instead of
  // onStart().
  override fun onNewIntent(intent: Intent) {
    val mediaManager = CastReceiverContext.getInstance().getMediaManager()
    // Pass the intent to the SDK. You can also do this in onCreate().
    if (mediaManager.onNewIntent(intent)) {
        // If the SDK recognizes the intent, you should early return.
        return
    }
    // If the SDK doesn't recognize the intent, you can handle the intent with
    // your own logic.
    ...
  }
}
Java
public class MyActivity extends Activity {
  @Override
  protected void onStart() {
    super.onStart();
    MediaManager mediaManager =
        CastReceiverContext.getInstance().getMediaManager();
    // Pass the intent to the SDK. You can also do this in onCreate().
    if (mediaManager.onNewIntent(getIntent())) {
      // If the SDK recognizes the intent, you should early return.
      return;
    }
    // If the SDK doesn't recognize the intent, you can handle the intent with
    // your own logic.
    ...
  }

  // For some cases, a new load intent triggers onNewIntent() instead of
  // onStart().
  @Override
  protected void onNewIntent(Intent intent) {
    MediaManager mediaManager =
        CastReceiverContext.getInstance().getMediaManager();
    // Pass the intent to the SDK. You can also do this in onCreate().
    if (mediaManager.onNewIntent(intent)) {
      // If the SDK recognizes the intent, you should early return.
      return;
    }
    // If the SDK doesn't recognize the intent, you can handle the intent with
    // your own logic.
    ...
  }
}

Wenn MediaManager erkennt, dass der Intent ein Lade-Intent ist, wird ein MediaLoadRequestData-Objekt aus dem Intent extrahiert und MediaLoadCommandCallback.onLoad() aufgerufen. Sie müssen diese Methode überschreiben, um die Ladeanfrage zu verarbeiten. Der Callback muss registriert werden, bevor MediaManager.onNewIntent() aufgerufen wird. Es wird empfohlen, die Methode „Aktivität“ oder „Anwendung“ onCreate() zu verwenden.

Kotlin
class MyActivity : Activity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val mediaManager = CastReceiverContext.getInstance().getMediaManager()
        mediaManager.setMediaLoadCommandCallback(MyMediaLoadCommandCallback())
    }
}

class MyMediaLoadCommandCallback : MediaLoadCommandCallback() {
  override fun onLoad(
        senderId: String?,
        loadRequestData: MediaLoadRequestData
  ): Task {
      return Tasks.call {
        // Resolve the entity into your data structure and load media.
        val mediaInfo = loadRequestData.getMediaInfo()
        if (!checkMediaInfoSupported(mediaInfo)) {
            // Throw MediaException to indicate load failure.
            throw MediaException(
                MediaError.Builder()
                    .setDetailedErrorCode(DetailedErrorCode.LOAD_FAILED)
                    .setReason(MediaError.ERROR_REASON_INVALID_REQUEST)
                    .build()
            )
        }
        myFillMediaInfo(MediaInfoWriter(mediaInfo))
        myPlayerLoad(mediaInfo.getContentUrl())

        // Update media metadata and state (this clears all previous status
        // overrides).
        castReceiverContext.getMediaManager()
            .setDataFromLoad(loadRequestData)
        ...
        castReceiverContext.getMediaManager().broadcastMediaStatus()

        // Return the resolved MediaLoadRequestData to indicate load success.
        return loadRequestData
     }
  }

  private fun myPlayerLoad(contentURL: String) {
    myPlayer.load(contentURL)

    // Update the MediaSession state.
    val playbackState: PlaybackStateCompat = Builder()
        .setState(
            player.getState(), player.getPosition(), System.currentTimeMillis()
        )
        ...
        .build()
    mediaSession.setPlaybackState(playbackState)
  }
Java
public class MyActivity extends Activity {
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    MediaManager mediaManager =
        CastReceiverContext.getInstance().getMediaManager();
    mediaManager.setMediaLoadCommandCallback(new MyMediaLoadCommandCallback());
  }
}

public class MyMediaLoadCommandCallback extends MediaLoadCommandCallback {
  @Override
  public Task onLoad(String senderId, MediaLoadRequestData loadRequestData) {
    return Tasks.call(() -> {
        // Resolve the entity into your data structure and load media.
        MediaInfo mediaInfo = loadRequestData.getMediaInfo();
        if (!checkMediaInfoSupported(mediaInfo)) {
          // Throw MediaException to indicate load failure.
          throw new MediaException(
              new MediaError.Builder()
                  .setDetailedErrorCode(DetailedErrorCode.LOAD_FAILED)
                  .setReason(MediaError.ERROR_REASON_INVALID_REQUEST)
                  .build());
        }
        myFillMediaInfo(new MediaInfoWriter(mediaInfo));
        myPlayerLoad(mediaInfo.getContentUrl());

        // Update media metadata and state (this clears all previous status
        // overrides).
        castReceiverContext.getMediaManager()
            .setDataFromLoad(loadRequestData);
        ...
        castReceiverContext.getMediaManager().broadcastMediaStatus();

        // Return the resolved MediaLoadRequestData to indicate load success.
        return loadRequestData;
    });
}

private void myPlayerLoad(String contentURL) {
  myPlayer.load(contentURL);

  // Update the MediaSession state.
  PlaybackStateCompat playbackState =
      new PlaybackStateCompat.Builder()
          .setState(
              player.getState(), player.getPosition(), System.currentTimeMillis())
          ...
          .build();
  mediaSession.setPlaybackState(playbackState);
}

Zum Verarbeiten des Lade-Intents können Sie ihn in die von uns definierten Datenstrukturen parsen (MediaLoadRequestData für Ladeanfragen).

Unterstützte Medienbefehle

Grundlegende Unterstützung für die Wiedergabesteuerung

Die grundlegenden Integrationsbefehle umfassen die Befehle, die mit Mediensitzungen kompatibel sind. Diese Befehle werden über Mediensitzungs-Callbacks benachrichtigt. Dafür musst du einen Callback für die Mediensitzung registrieren. Möglicherweise machst du das bereits.

Kotlin
private class MyMediaSessionCallback : MediaSessionCompat.Callback() {
  override fun onPause() {
    // Pause the player and update the play state.
    myPlayer.pause()
  }

  override fun onPlay() {
    // Resume the player and update the play state.
    myPlayer.play()
  }

  override fun onSeekTo(pos: Long) {
    // Seek and update the play state.
    myPlayer.seekTo(pos)
  }
    ...
 }

mediaSession.setCallback(MyMediaSessionCallback())
Java
private class MyMediaSessionCallback extends MediaSessionCompat.Callback {
  @Override
  public void onPause() {
    // Pause the player and update the play state.
    myPlayer.pause();
  }
  @Override
  public void onPlay() {
    // Resume the player and update the play state.
    myPlayer.play();
  }
  @Override
  public void onSeekTo(long pos) {
    // Seek and update the play state.
    myPlayer.seekTo(pos);
  }

  ...
}

mediaSession.setCallback(new MyMediaSessionCallback());

Unterstützte Cast-Steuerungsbefehle

Es gibt einige Cast-Befehle, die in MediaSession nicht verfügbar sind, z. B. skipAd() oder setActiveMediaTracks(). Außerdem müssen hier einige Warteschlangenbefehle implementiert werden, da die Cast-Warteschlange nicht vollständig mit der MediaSession-Warteschlange kompatibel ist.

Kotlin
class MyMediaCommandCallback : MediaCommandCallback() {
    override fun onSkipAd(requestData: RequestData?): Task {
        // Skip your ad
        ...
        return Tasks.forResult(null)
    }
}

val mediaManager = CastReceiverContext.getInstance().getMediaManager()
mediaManager.setMediaCommandCallback(MyMediaCommandCallback())
Java
public class MyMediaCommandCallback extends MediaCommandCallback {
  @Override
  public Task onSkipAd(RequestData requestData) {
    // Skip your ad
    ...
    return Tasks.forResult(null);
  }
}

MediaManager mediaManager =
    CastReceiverContext.getInstance().getMediaManager();
mediaManager.setMediaCommandCallback(new MyMediaCommandCallback());

Unterstützte Medienbefehle angeben

Wie bei Ihrem Cast-Receiver sollte auch in der Android TV App angegeben sein, welche Befehle unterstützt werden, damit Absender bestimmte UI-Steuerelemente aktivieren oder deaktivieren können. Geben Sie für Befehle, die Teil von MediaSession sind, die Befehle in PlaybackStateCompat an. Zusätzliche Befehle sollten in der MediaStatusModifier angegeben werden.

Kotlin
// Set media session supported commands
val playbackState: PlaybackStateCompat = PlaybackStateCompat.Builder()
    .setActions(PlaybackStateCompat.ACTION_PLAY or PlaybackStateCompat.ACTION_PAUSE)
    .setState(PlaybackStateCompat.STATE_PLAYING)
    .build()

mediaSession.setPlaybackState(playbackState)

// Set additional commands in MediaStatusModifier
val mediaManager = CastReceiverContext.getInstance().getMediaManager()
mediaManager.getMediaStatusModifier()
    .setMediaCommandSupported(MediaStatus.COMMAND_QUEUE_NEXT)
Java
// Set media session supported commands
PlaybackStateCompat playbackState =
    new PlaybackStateCompat.Builder()
        .setActions(PlaybackStateCompat.ACTION_PLAY | PlaybackStateCompat.ACTION_PAUSE)
        .setState(PlaybackStateCompat.STATE_PLAYING)
        .build();

mediaSession.setPlaybackState(playbackState);

// Set additional commands in MediaStatusModifier
MediaManager mediaManager = CastReceiverContext.getInstance().getMediaManager();
mediaManager.getMediaStatusModifier()
            .setMediaCommandSupported(MediaStatus.COMMAND_QUEUE_NEXT);

Nicht unterstützte Schaltflächen ausblenden

Wenn Ihre Android TV-App nur die grundlegende Mediensteuerung unterstützt, die Web Receiver-App jedoch eine erweiterte Steuerung unterstützt, sollten Sie dafür sorgen, dass sich die Sender-App beim Streamen in die Android TV App korrekt verhalten. Wenn beispielsweise Ihre Android TV-App das Ändern der Wiedergabegeschwindigkeit nicht unterstützt, während dies bei der Web Receiver-App der Fall ist, sollten Sie die unterstützten Aktionen auf jeder Plattform korrekt festlegen und dafür sorgen, dass die Sender-App die UI korrekt rendert.

MediaStatus ändern

Zur Unterstützung erweiterter Funktionen wie Titel, Werbung, Livestreams und Wiedergabeliste muss deine Android TV App zusätzliche Informationen bereitstellen, die nicht über MediaSession ermittelt werden können.

Dafür stellen wir Ihnen die Klasse MediaStatusModifier zur Verfügung. MediaStatusModifier wird immer für die MediaSession ausgeführt, die Sie in CastReceiverContext festgelegt haben.

So erstellen und übertragen Sie MediaStatus:

Kotlin
val mediaManager: MediaManager = castReceiverContext.getMediaManager()
val statusModifier: MediaStatusModifier = mediaManager.getMediaStatusModifier()

statusModifier
    .setLiveSeekableRange(seekableRange)
    .setAdBreakStatus(adBreakStatus)
    .setCustomData(customData)

mediaManager.broadcastMediaStatus()
Java
MediaManager mediaManager = castReceiverContext.getMediaManager();
MediaStatusModifier statusModifier = mediaManager.getMediaStatusModifier();

statusModifier
    .setLiveSeekableRange(seekableRange)
    .setAdBreakStatus(adBreakStatus)
    .setCustomData(customData);

mediaManager.broadcastMediaStatus();

Unsere Clientbibliothek ruft den Basis-MediaStatus von MediaSession ab. Die Android TV-App kann über einen MediaStatus-Modifikator einen zusätzlichen Status und Überschreibungsstatus angeben.

Einige Status und Metadaten können sowohl in MediaSession als auch in MediaStatusModifier festgelegt werden. Wir empfehlen dringend, sie nur in MediaSession festzulegen. Sie können den Modifikator weiterhin verwenden, um die Status in MediaSession zu überschreiben. Dies wird nicht empfohlen, da der Status im Modifikator immer eine höhere Priorität als die von MediaSession bereitgestellten Werte hat.

MediaStatus vor dem Senden abfangen

Wie beim Web Receiver SDK können Sie vor dem Senden noch ein paar letzte Schritte vornehmen. Geben Sie dazu einen MediaStatusInterceptor für die Verarbeitung des MediaStatus-Elements an. Wir übergeben ein MediaStatusWriter, um das MediaStatus zu bearbeiten, bevor es gesendet wird.

Kotlin
mediaManager.setMediaStatusInterceptor(object : MediaStatusInterceptor {
    override fun intercept(mediaStatusWriter: MediaStatusWriter) {
      // Perform customization.
        mediaStatusWriter.setCustomData(JSONObject("{data: \"my Hello\"}"))
    }
})
Java
mediaManager.setMediaStatusInterceptor(new MediaStatusInterceptor() {
    @Override
    public void intercept(MediaStatusWriter mediaStatusWriter) {
        // Perform customization.
        mediaStatusWriter.setCustomData(new JSONObject("{data: \"my Hello\"}"));
    }
});

Umgang mit Nutzeranmeldedaten

Ihre Android TV App erlaubt möglicherweise nur bestimmten Nutzern, die App-Sitzung zu starten oder daran teilzunehmen. Erlauben Sie einem Absender beispielsweise nur unter folgenden Voraussetzungen, den Dienst zu starten oder beizutreten:

  • Die Sender-App ist in demselben Konto und Profil wie die ATV-App angemeldet.
  • Die Sender-App ist in demselben Konto angemeldet, aber mit einem anderen Profil als die ATV-App.

Wenn Ihre App mehrere oder anonyme Nutzer unterstützen kann, können Sie weitere Nutzer zur ATV-Sitzung zulassen. Wenn der Nutzer Anmeldedaten angibt, muss Ihre ATV-App mit den Anmeldedaten umgehen, damit der Fortschritt und andere Nutzerdaten ordnungsgemäß verfolgt werden können.

Wenn Ihre Sender-App Ihre Android TV-App startet oder beitritt, sollte die Sender-App die Anmeldedaten bereitstellen, die angeben, wer an der Sitzung teilnimmt.

Bevor ein Absender Ihre Android TV-App startet und beitritt, können Sie eine Startprüfung festlegen, um festzustellen, ob die Anmeldedaten des Absenders zulässig sind. Falls nicht, startet das Cast Connect SDK deinen Web Receiver.

Anmeldedaten für App-Start-Anmeldedaten des Absenders

Auf der Absenderseite können Sie die CredentialsData angeben, um anzugeben, wer an der Sitzung teilnimmt.

credentials ist ein benutzerdefinierter String, der von der ATV-App verstanden wird. Mit credentialsType wird definiert, von welcher Plattform der CredentialsData stammt, oder er kann ein benutzerdefinierter Wert sein. Standardmäßig ist die Plattform festgelegt, von der aus die Nachrichten gesendet werden.

CredentialsData wird nur beim Start oder der Beitritt zu deiner Android TV-App an deine Android TV-App übergeben. Wenn Sie sie während einer Verbindung wieder festlegen, wird sie nicht an die Android TV App weitergegeben. Wechselt der Absender das Profil, während eine Verbindung besteht, können Sie entweder in der Sitzung bleiben oder SessionManager.endCurrentCastSession(boolean stopCasting) aufrufen, wenn Sie der Meinung sind, dass das neue Profil mit der Sitzung nicht kompatibel ist.

Die CredentialsData für jeden Absender kann mit getSenders auf CastReceiverContext abgerufen werden, um SenderInfo, getCastLaunchRequest() für CastLaunchRequest und dann getCredentialsData() abzurufen.

Android

Erfordert play-services-cast-framework-Version 19.0.0 oder höher.

Kotlin
CastContext.getSharedInstance().setLaunchCredentialsData(
    CredentialsData.Builder()
        .setCredentials("{\"userId\": \"abc\"}")
        .build()
)
Java
CastContext.getSharedInstance().setLaunchCredentialsData(
    new CredentialsData.Builder()
        .setCredentials("{\"userId\": \"abc\"}")
        .build());
iOS

Erfordert google-cast-sdk-Version v4.8.1 oder höher.

Kann jederzeit aufgerufen werden, nachdem die Optionen festgelegt wurden: GCKCastContext.setSharedInstanceWith(options).

GCKCastContext.sharedInstance().setLaunch(
    GCKCredentialsData(credentials: "{\"userId\": \"abc\"}")
Web

Erfordert die Chromium-Browserversion M87 oder höher.

Kann jederzeit aufgerufen werden, nachdem die Optionen festgelegt wurden: cast.framework.CastContext.getInstance().setOptions(options);.

let credentialsData =
    new chrome.cast.CredentialsData("{\"userId\": \"abc\"}");
cast.framework.CastContext.getInstance().setLaunchCredentialsData(credentialsData);

Prüfung von ATV-Startanfragen implementieren

Die CredentialsData wird an Ihre Android TV-App übergeben, wenn ein Absender versucht, die App zu starten oder beizutreten. Sie können eine LaunchRequestChecker implementieren. um diese Anfrage zuzulassen oder abzulehnen.

Wenn eine Anfrage abgelehnt wird, wird der Web Receiver geladen, anstatt nativ in der ATV-App zu starten. Du solltest eine Anfrage ablehnen, wenn dein ATV den Nutzer nicht verarbeiten kann, der den Start oder Beitritt beantragt. Es kann beispielsweise sein, dass in der ATV-App ein anderer Nutzer angemeldet ist als angefordert und Ihre App den Wechsel mit Anmeldedaten nicht verarbeiten kann oder dass momentan kein Nutzer in der ATV-App angemeldet ist.

Wenn eine Anfrage zulässig ist, wird die ATV-App gestartet. Sie können dieses Verhalten abhängig davon anpassen, ob Ihre Anwendung das Senden von Ladeanfragen unterstützt, wenn ein Nutzer nicht in der ATV-App angemeldet ist, oder ob es eine Abweichung bei den Nutzern gibt. Dieses Verhalten ist in LaunchRequestChecker vollständig anpassbar.

Erstellen Sie eine Klasse, in der die CastReceiverOptions.LaunchRequestChecker-Schnittstelle implementiert wird:

Kotlin
class MyLaunchRequestChecker : LaunchRequestChecker {
  override fun checkLaunchRequestSupported(launchRequest: CastLaunchRequest): Task {
    return Tasks.call {
      myCheckLaunchRequest(
           launchRequest
      )
    }
  }
}

private fun myCheckLaunchRequest(launchRequest: CastLaunchRequest): Boolean {
  val credentialsData = launchRequest.getCredentialsData()
     ?: return false // or true if you allow anonymous users to join.

  // The request comes from a mobile device, e.g. checking user match.
  return if (credentialsData.credentialsType == CredentialsData.CREDENTIALS_TYPE_ANDROID) {
     myCheckMobileCredentialsAllowed(credentialsData.getCredentials())
  } else false // Unrecognized credentials type.
}
Java
public class MyLaunchRequestChecker
    implements CastReceiverOptions.LaunchRequestChecker {
  @Override
  public Task checkLaunchRequestSupported(CastLaunchRequest launchRequest) {
    return Tasks.call(() -> myCheckLaunchRequest(launchRequest));
  }
}

private boolean myCheckLaunchRequest(CastLaunchRequest launchRequest) {
  CredentialsData credentialsData = launchRequest.getCredentialsData();
  if (credentialsData == null) {
    return false;  // or true if you allow anonymous users to join.
  }

  // The request comes from a mobile device, e.g. checking user match.
  if (credentialsData.getCredentialsType().equals(CredentialsData.CREDENTIALS_TYPE_ANDROID)) {
    return myCheckMobileCredentialsAllowed(credentialsData.getCredentials());
  }

  // Unrecognized credentials type.
  return false;
}

Legen Sie ihn dann in der ReceiverOptionsProvider fest:

Kotlin
class MyReceiverOptionsProvider : ReceiverOptionsProvider {
  override fun getOptions(context: Context?): CastReceiverOptions {
    return CastReceiverOptions.Builder(context)
        ...
        .setLaunchRequestChecker(MyLaunchRequestChecker())
        .build()
  }
}
Java
public class MyReceiverOptionsProvider implements ReceiverOptionsProvider {
  @Override
  public CastReceiverOptions getOptions(Context context) {
    return new CastReceiverOptions.Builder(context)
        ...
        .setLaunchRequestChecker(new MyLaunchRequestChecker())
        .build();
  }
}

Wenn du true in LaunchRequestChecker auflöst, wird die ATV-App und false die Web Receiver-App gestartet.

Benutzerdefinierte Nachrichten senden und empfangen

Mit dem Cast-Protokoll können Sie benutzerdefinierte Stringnachrichten zwischen Absendern und Ihrer Empfängeranwendung senden. Sie müssen einen Namespace (Kanal) zum Senden von Nachrichten registrieren, bevor Sie CastReceiverContext initialisieren.

Android TV: Benutzerdefinierten Namespace angeben

Sie müssen Ihre unterstützten Namespaces während der Einrichtung in Ihrer CastReceiverOptions angeben:

Kotlin
class MyReceiverOptionsProvider : ReceiverOptionsProvider {
  override fun getOptions(context: Context?): CastReceiverOptions {
    return CastReceiverOptions.Builder(context)
        .setCustomNamespaces(
            Arrays.asList("urn:x-cast:com.example.cast.mynamespace")
        )
        .build()
  }
}
Java
public class MyReceiverOptionsProvider implements ReceiverOptionsProvider {
  @Override
  public CastReceiverOptions getOptions(Context context) {
    return new CastReceiverOptions.Builder(context)
        .setCustomNamespaces(
              Arrays.asList("urn:x-cast:com.example.cast.mynamespace"))
        .build();
  }
}

Android TV: Nachrichten senden

Kotlin
// If senderId is null, then the message is broadcasted to all senders.
CastReceiverContext.getInstance().sendMessage(
    "urn:x-cast:com.example.cast.mynamespace", senderId, customString)
Java
// If senderId is null, then the message is broadcasted to all senders.
CastReceiverContext.getInstance().sendMessage(
    "urn:x-cast:com.example.cast.mynamespace", senderId, customString);

Android TV: Nachrichten für benutzerdefinierte Namespaces erhalten

Kotlin
class MyCustomMessageListener : MessageReceivedListener {
    override fun onMessageReceived(
        namespace: String, senderId: String?, message: String ) {
        ...
    }
}

CastReceiverContext.getInstance().setMessageReceivedListener(
    "urn:x-cast:com.example.cast.mynamespace", new MyCustomMessageListener());
Java
class MyCustomMessageListener implements CastReceiverContext.MessageReceivedListener {
  @Override
  public void onMessageReceived(
      String namespace, String senderId, String message) {
    ...
  }
}

CastReceiverContext.getInstance().setMessageReceivedListener(
    "urn:x-cast:com.example.cast.mynamespace", new MyCustomMessageListener());