Wichtige Funktionen zu Ihrem Android TV-Receiver hinzufügen

Auf dieser Seite finden Sie 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 Ihres Anwendungsmoduls.
  2. Prüfen Sie, ob google() in den aufgeführten repositories enthalten ist.
      repositories {
        google()
      }
  3. Fügen Sie je nach Zielgerätetyp für Ihre App die neuesten Versionen der Bibliotheken zu Ihren Abhängigkeiten hinzu:
    • Für Android-Empfänger-Apps:
        dependencies {
          implementation 'com.google.android.gms:play-services-cast-tv:21.1.1'
          implementation 'com.google.android.gms:play-services-cast:22.1.0'
        }
    • Für Android-Sender-Apps:
        dependencies {
          implementation 'com.google.android.gms:play-services-cast:21.1.1'
          implementation 'com.google.android.gms:play-services-cast-framework:22.1.0'
        }
    Aktualisieren Sie diese Versionsnummer jedes Mal, wenn die Dienste aktualisiert werden.
  4. Speichern Sie die Änderungen und klicken Sie in der Symbolleiste auf Sync Project with Gradle Files.
iOS
  1. Achten Sie darauf, dass Podfile auf google-cast-sdk 4.8.3 oder höher ausgerichtet ist.
  2. Die App muss auf iOS 14 oder höher ausgerichtet sein. Weitere Informationen finden Sie in den Versionshinweisen.
      platform: ios, '14'
    
      def target_pods
         pod 'google-cast-sdk', '~>4.8.3'
      end
Web
  1. Erfordert den Chromium-Browser ab Version M87.
  2. Web Sender API-Bibliothek zum Projekt hinzufügen
      <script src="//www.gstatic.com/cv/js/sender/v1/cast_sender.js?loadCastFramework=1"></script>

AndroidX-Anforderung

Für neue Versionen der Google Play-Dienste muss eine App aktualisiert worden sein, damit sie den Namespace androidx verwenden kann. Folgen Sie der Anleitung zur Migration zu AndroidX.

Android TV-App – Voraussetzungen

Damit Cast Connect in Ihrer Android TV-App unterstützt wird, müssen Sie Ereignisse aus einer Mediensitzung erstellen und unterstützen. Die von Ihrer Mediensitzung bereitgestellten Daten enthalten die grundlegenden Informationen für Ihren Medienstatus, z. B. Position und Wiedergabestatus. Ihre Mediensitzung wird auch von der Cast Connect-Bibliothek verwendet, um zu signalisieren, wann sie bestimmte Nachrichten von einem Absender empfangen hat, z. B. „Pause“.

Weitere Informationen zur Mediensitzung und zum Initialisieren einer Mediensitzung finden Sie im Leitfaden zur Arbeit mit einer Mediensitzung.

Lebenszyklus von Mediensitzungen

Ihre App sollte eine Mediensitzung erstellen, wenn die Wiedergabe beginnt, und sie freigeben, wenn sie nicht mehr gesteuert werden kann. Wenn Ihre App beispielsweise eine Video-App ist, sollten Sie die Sitzung beenden, wenn der Nutzer die Wiedergabeaktivität verlässt, entweder durch Auswahl von „Zurück“, um andere Inhalte zu suchen, oder durch Minimieren der App. Wenn Ihre App eine Musik-App ist, sollten Sie die Sitzung beenden, wenn in Ihrer App keine Medien mehr wiedergegeben werden.

Sitzungsstatus wird aktualisiert

Die Daten in Ihrer Mediensitzung sollten mit dem Status Ihres Players auf dem neuesten Stand gehalten werden. Wenn die Wiedergabe beispielsweise pausiert wird, sollten Sie sowohl den Wiedergabestatus als auch die unterstützten Aktionen aktualisieren. In den folgenden Tabellen ist aufgeführt, welche Status Sie auf dem neuesten Stand halten müssen.

MediaMetadataCompat

Metadatenfeld Beschreibung
METADATA_KEY_TITLE (erforderlich) Der Medientitel.
METADATA_KEY_DISPLAY_SUBTITLE Der Untertitel.
METADATA_KEY_DISPLAY_ICON_URI Die Symbol-URL.
METADATA_KEY_DURATION (erforderlich) Dauer der Media.
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() Legt den Wiedergabestatus und die aktuelle Position fest.

MediaSessionCompat

Erforderliche Methode Beschreibung
setRepeatMode() Legt den Wiederholungsmodus fest.
setShuffleMode() Legt den Zufallsmix fest.
setMetadata() Legt Media-Metadaten 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

In Ihrer App sollte ein Callback für die Transportsteuerung der Mediensitzung implementiert sein. In der folgenden Tabelle sehen Sie, welche Transportsteuerungsaktionen sie verarbeiten müssen:

MediaSessionCompat.Callback

Aktionen Beschreibung
onPlay() Fortsetzen
onPause() Pausieren
onSeekTo() Zu einer Position springen
onStop() Aktuelle Medien stoppen
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 Senderanwendung eine Startanfrage sendet, wird ein Intent mit einem Anwendungs-Namespace erstellt. Ihre Anwendung ist für die Verarbeitung zuständig und muss beim Start der TV-App eine Instanz des CastReceiverContext-Objekts erstellen. Das CastReceiverContext-Objekt ist erforderlich, um mit Cast zu interagieren, während die TV-App ausgeführt wird. Mit diesem Objekt kann Ihre TV-Anwendung Cast-Mediennachrichten von allen verbundenen Absendern empfangen.

Android TV einrichten

Start-Intent-Filter hinzufügen

Fügen Sie der Aktivität, die den Start-Intent Ihrer Absender-App verarbeiten soll, 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 von Empfängeroptionen angeben

Sie müssen ein 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" />

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

Kontext des Streamingempfängers

Initialisieren Sie CastReceiverContext beim Erstellen Ihrer App:

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

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

  ...
}

Starten Sie CastReceiverContext, wenn Ihre 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 stop() für die CastReceiverContext auf, wenn die Wiedergabe im Hintergrund beendet wird.

Wir empfehlen dringend, den LifecycleObserver aus der Bibliothek androidx.lifecycle zu verwenden, um CastReceiverContext.start() und CastReceiverContext.stop() aufzurufen, insbesondere wenn Ihre native App mehrere Aktivitäten hat. So werden Race-Bedingungen vermieden, wenn Sie start() und stop() aus 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 angeben, damit es weiß, wohin die Befehle gesendet und der Medienwiedergabestatus abgerufen werden soll:

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

Wenn du dein MediaSession aufgrund von Inaktivität freigibst, solltest du ein Null-Token für MediaManager festlegen:

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

Wenn Ihre App die Medienwiedergabe im Hintergrund unterstützt, sollten Sie CastReceiverContext.stop() nicht aufrufen, wenn Ihre App in den Hintergrund verschoben wird, sondern nur, wenn Ihre App im Hintergrund ausgeführt wird und keine Medien mehr wiedergegeben werden. 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 mit MediaSessionConnector die Sitzung und alle zugehörigen Informationen, einschließlich des Wiedergabestatus, automatisch beibehalten, anstatt die Änderungen manuell zu erfassen.

Mit MediaSessionConnector.MediaButtonEventHandler können MediaButton-Ereignisse verarbeitet werden, indem setMediaButtonEventHandler(MediaButtonEventHandler) aufgerufen wird. Andernfalls werden sie standardmäßig von MediaSessionCompat.Callback verarbeitet.

Wenn Sie MediaSessionConnector in Ihre App einbinden möchten, fügen Sie Folgendes Ihrer Player-Aktivitätsklasse oder dem Ort hinzu, an dem Sie Ihre Mediensitzung verwalten:

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);
    ...
  }
}

Einrichtung der Sender-App

Cast Connect-Unterstützung aktivieren

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

Android

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

Das Flag androidReceiverCompatible ist in LaunchOptions (Teil von CastOptions) gesetzt:

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 ist in GCKLaunchOptions (Teil von GCKCastOptions) festgelegt:

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ügen Sie den Paketnamen Ihrer Android TV-App in der Cast Developer Console hinzu, um ihn mit Ihrer Cast-App-ID zu verknüpfen.

Entwicklergeräte registrieren

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

Ohne Registrierung funktioniert Cast Connect aus Sicherheitsgründen nur für Apps, die über den Google Play Store installiert wurden.

Weitere Informationen zum Registrieren eines Cast- oder Android TV-Geräts für die Cast-Entwicklung findest du auf der Registrierungsseite.

Medien werden geladen

Wenn du bereits Deeplink-Unterstützung in deiner Android TV-App implementiert hast, solltest du eine ähnliche Definition in deinem Android TV-Manifest 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>

Laden nach Absender

Auf den Absendergeräten können Sie den Deeplink übergeben, indem Sie entity in den Media-Informationen für die Ladeanfrage festlegen:

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 auf dem Absendergerät festlegen

Es ist möglich, dass deine Web Receiver-App und deine Android TV-App unterschiedliche Deeplinks und credentials unterstützen, z. B. wenn du die Authentifizierung auf den beiden Plattformen unterschiedlich handhabst. Um dieses Problem zu beheben, können Sie alternative entity und credentials für Android TV bereitstellen:

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-App gestartet wird, werden entity und credentials in der Ladeanfrage verwendet. Wenn Ihre Android TV-App jedoch gestartet wird, überschreibt das SDK die entity und credentials mit Ihren atvEntity und atvCredentials (falls angegeben).

Laden nach Content ID oder MediaQueueData

Wenn Sie entity oder atvEntity nicht verwenden und Content-ID oder Content-URL in Ihren Media-Informationen oder die detaillierteren Daten für Media Load Request verwenden, müssen Sie den folgenden vordefinierten Intent-Filter in Ihre Android TV-App einfü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 Senderseite können Sie ähnlich wie bei load by entity 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

In Ihrer Aktivität müssen Sie die Intents in den Lifecycle-Callbacks Ihrer Aktivität verarbeiten, um diese Ladeanfragen zu bearbeiten:

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 es sich bei der Intention um eine Ladeintention handelt, wird ein MediaLoadRequestData-Objekt aus der Intention 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, ihn in einer onCreate()-Methode für eine Aktivität oder Anwendung zu registrieren.

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);
}

Um die Ladeabsicht zu verarbeiten, können Sie die Absicht in die von uns definierten Datenstrukturen parsen (MediaLoadRequestData für Ladeanfragen).

Unterstützung von Medienbefehlen

Unterstützung der grundlegenden Wiedergabesteuerung

Zu den grundlegenden Integrationsbefehlen gehören die Befehle, die mit der Mediensitzung kompatibel sind. Diese Befehle werden über Rückrufe für Mediensitzungen gemeldet. Dazu müssen Sie einen Callback für die Mediensitzung registrieren (möglicherweise haben Sie das bereits getan).

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ützung von Cast-Steuerungsbefehlen

Einige Cast-Befehle sind in MediaSession nicht verfügbar, 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<Void?> {
        // 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 deinem Cast-Empfänger sollte deine Android TV-App angeben, 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 deine Android TV-App nur die grundlegende Mediensteuerung unterstützt, deine Web Receiver-App jedoch eine erweiterte Steuerung, solltest du dafür sorgen, dass sich deine Sender-App beim Streamen auf die Android TV-App korrekt verhält. Wenn deine Android TV-App beispielsweise keine Änderung der Wiedergaberate unterstützt, deine Web Receiver-App jedoch schon, solltest du die unterstützten Aktionen auf jeder Plattform richtig festlegen und dafür sorgen, dass die Benutzeroberfläche deiner Sender-App richtig gerendert wird.

MediaStatus wird geändert

Damit erweiterte Funktionen wie Tracks, Werbung, Live-Inhalte und Warteschlangen unterstützt werden, muss deine Android TV-App zusätzliche Informationen bereitstellen, die nicht über MediaSession ermittelt werden können.

Dazu stellen wir Ihnen die Klasse MediaStatusModifier zur Verfügung. MediaStatusModifier wird immer auf der MediaSession ausgeführt, die Sie in CastReceiverContext festgelegt haben.

So erstellst du ein MediaStatus und streamst es:

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 die Basis-MediaStatus aus MediaSession ab. Ihre Android TV-App kann zusätzliche Status und Überschreibungsstatus über einen MediaStatus-Modifikator 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. Das wird jedoch nicht empfohlen, da der Status im Modifikator immer eine höhere Priorität hat als die von MediaSession bereitgestellten Werte.

MediaStatus vor dem Senden abfangen

Wie beim Web Receiver SDK können Sie auch hier eine MediaStatusInterceptor angeben, um die MediaStatus zu verarbeiten, die gesendet werden soll. Wir übergeben ein MediaStatusWriter, um die MediaStatus zu bearbeiten, bevor sie 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. Sie können beispielsweise festlegen, dass ein Absender eine Videokonferenz nur starten oder ihr beitreten darf, wenn:

  • In der Sender-App ist dasselbe Konto und Profil angemeldet wie in der Android TV-App.
  • In der Sender-App ist dasselbe Konto angemeldet, aber ein anderes Profil als in der ATV-App.

Wenn Ihre App mehrere oder anonyme Nutzer verarbeiten kann, können Sie zulassen, dass jeder Nutzer der ATV-Sitzung beitritt. Wenn der Nutzer Anmeldedaten angibt, muss deine ATV-App diese Anmeldedaten verarbeiten, damit der Fortschritt und andere Nutzerdaten richtig erfasst werden können.

Wenn Ihre Sender-App gestartet wird oder Ihrer Android TV-App beitritt, sollte sie die Anmeldedaten angeben, die den Nutzer repräsentieren, der der Sitzung beitritt.

Bevor ein Absender Ihre Android TV-App startet und ihr beitritt, können Sie einen Start-Checker angeben, um zu prüfen, ob die Anmeldedaten des Absenders zulässig sind. Andernfalls wird Ihr Web Receiver mit dem Cast Connect SDK gestartet.

Anmeldedaten für den Start der Sender-App

Auf der Senderseite können Sie die 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. Mit credentialsType wird definiert, von welcher Plattform CredentialsData stammt. Es kann auch ein benutzerdefinierter Wert sein. Standardmäßig ist die Plattform festgelegt, von der die Nachricht gesendet wird.

Der CredentialsData wird nur beim Start oder beim Beitreten an Ihre Android TV-App übergeben. Wenn Sie das Profil noch einmal festlegen, während Sie verbunden sind, wird es nicht an Ihre Android TV-App übergeben. Wenn der Absender das Profil während der Verbindung ändert, können Sie entweder in der Sitzung bleiben oder SessionManager.endCurrentCastSession(boolean stopCasting) aufrufen, wenn Sie der Meinung sind, dass das neue Profil nicht mit der Sitzung kompatibel ist.

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

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.3 oder höher.

Kann jederzeit nach dem Festlegen der Optionen aufgerufen werden: GCKCastContext.setSharedInstanceWith(options).

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

Erfordert die Chromium-Browserversion M87 oder höher.

Kann jederzeit nach dem Festlegen der Optionen aufgerufen werden: cast.framework.CastContext.getInstance().setOptions(options);.

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

ATV-Startanfrageprüfung implementieren

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

Wenn eine Anfrage abgelehnt wird, wird der Web Receiver geladen, anstatt die ATV-App nativ zu starten. Sie sollten eine Anfrage ablehnen, wenn Ihr ATV die Anfrage des Nutzers zum Starten oder Beitreten nicht verarbeiten kann. Das kann beispielsweise der Fall sein, wenn ein anderer Nutzer in der ATV-App angemeldet ist als der, der die Anfrage stellt, und deine App die Anmeldedaten nicht wechseln kann oder wenn derzeit kein Nutzer in der ATV-App angemeldet ist.

Wenn eine Anfrage zulässig ist, wird die ATV-App gestartet. Sie können dieses Verhalten anpassen, je nachdem, ob Ihre App das Senden von Ladeanfragen unterstützt, wenn ein Nutzer nicht in der ATV-App angemeldet ist oder wenn es eine Nutzerabweichung gibt. Dieses Verhalten kann in der LaunchRequestChecker vollständig angepasst werden.

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

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 sie 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();
  }
}

Durch das Auflösen von true in der LaunchRequestChecker wird die ATV-App gestartet und durch false wird die Web Receiver-App gestartet.

Benutzerdefinierte Nachrichten senden und empfangen

Mit dem Cast-Protokoll können Sie benutzerdefinierte String-Nachrichten zwischen Sendern und Ihrer Empfängeranwendung senden. Sie müssen einen Namespace (Channel) registrieren, um Nachrichten zu senden, bevor Sie Ihre CastReceiverContext initialisieren.

Android TV – Benutzerdefinierten Namespace angeben

Sie müssen Ihre unterstützten Namespaces während der Einrichtung in Ihrem 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 – benutzerdefinierte Namespace-Nachrichten empfangen

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());